Add OIDC sign-in, group-derived roles and declarative instance configuration
Workspaces, group mappings and sign-in methods now come from a configuration file synchronized at startup; workspaces dropped from it are disabled, never deleted. Instance administrators (a new role) see and help every workspace and may delete disabled ones; workspace administrators and employees are derived from the user's groups at every SSO sign-in or administrator edit, and the employee permission set belongs to the workspace. Self-registration is gone: users come from SSO (only when their groups map) or from the administrator. Break-glass bootstrap accounts get an HMAC-derived hourly password that all replicas agree on. First SSO sign-in links a matching email contact to the user. The demo runs on the same model with a generated per-start password. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
e37d583179
commit
4764f3545f
68 files changed
+7220
-964
No files matched your search
@@ -31,6 +31,14 @@ impl Permission {
|
||||
pub fn member() -> Vec<Self> {
|
||||
vec![Self::View, Self::RequestOverrides]
|
||||
}
|
||||
/// Default employee role: calendar access, schedule edits, and approved replacements.
|
||||
pub fn employee_default() -> Vec<Self> {
|
||||
vec![Self::View, Self::EditSchedules, Self::RequestOverrides]
|
||||
}
|
||||
/// Permissions an administrator may grant the employee role.
|
||||
pub fn grantable_to_employees(self) -> bool {
|
||||
!matches!(self, Self::ManageMembers | Self::ManageIntegration)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -43,12 +51,19 @@ pub struct User {
|
||||
pub country: String,
|
||||
/// None follows the browser timezone; this never changes scheduling rules.
|
||||
pub timezone: Option<String>,
|
||||
#[serde(default)]
|
||||
pub email: Option<String>,
|
||||
#[serde(default)]
|
||||
pub instance_admin: bool,
|
||||
#[serde(default)]
|
||||
pub has_password: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Member {
|
||||
pub user: User,
|
||||
pub permissions: Vec<Permission>,
|
||||
pub is_owner: bool,
|
||||
}
|
||||
|
||||
/// Scheduling metadata, not an authentication principal. Registered users retain their ID.
|
||||
@@ -59,6 +74,9 @@ pub struct Person {
|
||||
pub email: Option<String>,
|
||||
pub country: Option<String>,
|
||||
pub user_id: Option<Uuid>,
|
||||
/// Former contact IDs that were merged into this person when a login was linked by email.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub aliases: Vec<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
@@ -85,6 +103,9 @@ pub struct WorkspaceDocument {
|
||||
pub name: String,
|
||||
pub timezone: String,
|
||||
pub horizon_days: u16,
|
||||
/// Grants held by the employee role; administrators always hold every permission.
|
||||
#[serde(default = "Permission::employee_default")]
|
||||
pub member_permissions: Vec<Permission>,
|
||||
#[serde(default)]
|
||||
pub people: Vec<Person>,
|
||||
#[serde(default)]
|
||||
@@ -113,6 +134,7 @@ impl WorkspaceDocument {
|
||||
overwrite_drift: false,
|
||||
timezone: "Europe/Bucharest".into(),
|
||||
horizon_days: 90,
|
||||
member_permissions: Permission::employee_default(),
|
||||
people: vec![],
|
||||
schedules: vec![],
|
||||
holidays: vec![],
|
||||
|
||||
Reference in new issue
Block a user