Skip to content

Commit a3654dd

Browse files
committed
feat: implement service identity registration and panel integration
- **Auth**: Refactor permissions to distinguish between user and service subjects. - **Identity**: Add sentinel endpoint for dynamic credential retrieval. - **Services**: Scaffolding for `realm` service and `registrar`/`communicator` libraries. - **Panel**: Externalize `API_BASE_URL` and implement dynamic sentinel auth. - **Tests**: Add comprehensive integration tests for organization members and roles. - **Chore**: Cleanup terraform state tracking and fix typos.
1 parent 980f2ff commit a3654dd

File tree

119 files changed

+12287
-1182
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+12287
-1182
lines changed

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,9 @@ docker/surrealdb/database.db
142142
docker/nats
143143
.env
144144

145-
**.task/**
145+
**.task/**
146+
147+
# Terraform state files
148+
*.tfstate
149+
*.tfstate.backup
150+
*.tfstate.*.backup

.output.txt

Lines changed: 827 additions & 0 deletions
Large diffs are not rendered by default.

app/windows/runner/win32_window.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class WindowClassRegistrar {
4242
public:
4343
~WindowClassRegistrar() = default;
4444

45-
// Returns the singleton registar instance.
45+
// Returns the singleton registrar instance.
4646
static WindowClassRegistrar* GetInstance() {
4747
if (!instance_) {
4848
instance_ = new WindowClassRegistrar();

backend/Taskfile.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ tasks:
3333
for taskfile in $TASKFILES; do
3434
DIR=$(dirname "$taskfile")
3535
36-
if ! (cd "$DIR" && task --list 2>/dev/null | grep -q "^{{.TASK_CMD}}"); then
36+
if ! (cd "$DIR" && task --list 2>/dev/null | grep -q "^\* {{.TASK_CMD}}:"); then
3737
echo "⊘ $DIR (task '{{.TASK_CMD}}' not found, skipping)"
3838
continue
3939
fi
@@ -117,6 +117,18 @@ tasks:
117117
echo " - $DIR"
118118
done
119119
120+
test:
121+
desc: "Run integration tests (builds components if needed)"
122+
cmds:
123+
- task: build:all
124+
- cd tests && cargo test {{.CLI_ARGS}}
125+
126+
test:all:
127+
desc: "Run all integration tests in single binary (fastest)"
128+
cmds:
129+
- task: build:all
130+
- cd tests && cargo test --test integration {{.CLI_ARGS}}
131+
120132
default:
121133
desc: Show available tasks
122134
cmds:

backend/auth/auth-callout/.task/checksum/build

Lines changed: 0 additions & 1 deletion
This file was deleted.

backend/auth/auth-typewriter-permissions/.task/checksum/build

Lines changed: 0 additions & 1 deletion
This file was deleted.

backend/auth/auth-typewriter-permissions/manifests/workloaddeployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ spec:
2121
- handler
2222
- consumer
2323
config:
24-
subscriptions: auth.permissions.typewriter
24+
subscriptions: auth.permissions.typewriter-panel,auth.permissions.typewriter-services
2525
- namespace: seamlezz
2626
package: surrealdb
2727
interfaces:
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use std::time::Duration;
2+
3+
use nats_jwt_rs::types::{
4+
Permission as NatsPermission, Permissions as NatsPermissions,
5+
ResponsePermission as NatsResponsePermission,
6+
};
7+
use serde::{Deserialize, Serialize};
8+
9+
use crate::typewriter;
10+
11+
#[derive(Debug, Serialize, Deserialize, Clone)]
12+
pub struct DiscordData {
13+
pub id: String,
14+
pub username: String,
15+
pub discriminator: Option<String>,
16+
pub email: Option<String>,
17+
pub avatar: Option<String>,
18+
pub avatar_url: Option<String>,
19+
#[serde(default)]
20+
pub roles: Vec<String>,
21+
}
22+
23+
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
24+
pub struct AuthentikClaims {
25+
pub name: Option<String>,
26+
pub preferred_username: Option<String>,
27+
pub email: Option<String>,
28+
#[serde(default)]
29+
pub email_verified: bool,
30+
#[serde(default)]
31+
pub groups: Vec<String>,
32+
pub discord: Option<DiscordData>,
33+
pub avatar: Option<String>,
34+
pub avatar_url: Option<String>,
35+
}
36+
37+
#[derive(Debug, Serialize, Deserialize, Clone)]
38+
pub struct User {
39+
pub name: String,
40+
pub email: Option<String>,
41+
pub avatar: Option<String>,
42+
pub avatar_url: Option<String>,
43+
}
44+
45+
/// Build a permission response from NATS permissions and tags
46+
pub fn build_permission_response(
47+
nats_permissions: NatsPermissions,
48+
tags: Vec<String>,
49+
) -> typewriter::api::v1::PermissionResponse {
50+
let proto_permissions = (&nats_permissions).into();
51+
typewriter::api::v1::PermissionResponse {
52+
permissions: Some(proto_permissions),
53+
tags,
54+
}
55+
}
56+
57+
/// Build default NATS permissions structure with response limits
58+
pub fn build_nats_permissions(
59+
allow_publish: Vec<String>,
60+
allow_subscribe: Vec<String>,
61+
) -> NatsPermissions {
62+
NatsPermissions {
63+
publish: NatsPermission {
64+
allow: allow_publish,
65+
deny: vec![],
66+
},
67+
subscribe: NatsPermission {
68+
allow: allow_subscribe,
69+
deny: vec![],
70+
},
71+
resp: Some(NatsResponsePermission {
72+
max_messages: 1,
73+
ttl: Duration::from_secs(60),
74+
}),
75+
}
76+
}
77+
78+
impl From<&NatsPermissions> for typewriter::models::v1::Permissions {
79+
fn from(nats_permissions: &NatsPermissions) -> Self {
80+
use prost_types::Duration;
81+
82+
let publish = Some(typewriter::models::v1::Permission {
83+
allow: nats_permissions.publish.allow.clone(),
84+
deny: nats_permissions.publish.deny.clone(),
85+
});
86+
87+
let subscribe = Some(typewriter::models::v1::Permission {
88+
allow: nats_permissions.subscribe.allow.clone(),
89+
deny: nats_permissions.subscribe.deny.clone(),
90+
});
91+
92+
let resp = nats_permissions.resp.as_ref().map(|r| {
93+
let total_seconds = r.ttl.as_secs();
94+
let nanos = r.ttl.subsec_nanos();
95+
96+
typewriter::models::v1::ResponsePermission {
97+
max_messages: r.max_messages as i32,
98+
ttl: Some(Duration {
99+
seconds: total_seconds as i64,
100+
nanos: nanos as i32,
101+
}),
102+
}
103+
});
104+
105+
typewriter::models::v1::Permissions {
106+
publish,
107+
subscribe,
108+
resp,
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)