Restrict workspace settings to administrators, add demo countries, Helm chart and instance event log
Employees keep schedule editing but can no longer change workspace preferences or existing scheduling-directory entries (enforced by the server, hidden in the UI). Demo accounts live in Cyprus, the United Kingdom and Armenia with matching bank holidays. A Helm chart deploys the service with a pre-upgrade migrate hook. Refused SSO sign-ins are stored with their support reference as instance events and searchable on the instance administration page. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
7afdc4be97
commit
548494f12e
11 files changed
+413
-18
No files matched your search
@@ -329,3 +329,61 @@ pub async fn delete_workspace(
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
const EVENT_LIMIT: usize = 300;
|
||||
|
||||
/// The newest instance events, newest first, optionally filtered by a case-insensitive text that
|
||||
/// is matched against the action, the actor and the details. A support reference from a failed
|
||||
/// sign-in (the `ref` shown on the login screen) is found this way.
|
||||
pub async fn events(db: &Store, actor: Uuid, search: &str) -> Result<Value> {
|
||||
require_instance_admin(db, actor).await?;
|
||||
let needle = search.trim().to_lowercase();
|
||||
ensure(
|
||||
needle.len() <= 200,
|
||||
crate::i18n::text("err_the_search_text_is_too_long_7c3d58"),
|
||||
)?;
|
||||
let mut rows = InstanceAuditRow::objects().all(&db.db).await?;
|
||||
rows.sort_by_key(|row| std::cmp::Reverse(row.id.unwrap()));
|
||||
let mut names: BTreeMap<String, String> = BTreeMap::new();
|
||||
let mut events = vec![];
|
||||
let mut more = false;
|
||||
for row in rows {
|
||||
let actor_name = match &row.actor_id {
|
||||
None => None,
|
||||
Some(id) => {
|
||||
if !names.contains_key(id) {
|
||||
let key = id.clone();
|
||||
let name = query!(UserRow,$id==key)
|
||||
.get(&db.db)
|
||||
.await?
|
||||
.map_or_else(|| "unknown".to_owned(), |u| u.username);
|
||||
names.insert(id.clone(), name);
|
||||
}
|
||||
names.get(id).cloned()
|
||||
}
|
||||
};
|
||||
if !needle.is_empty()
|
||||
&& ![
|
||||
row.action.as_str(),
|
||||
actor_name.as_deref().unwrap_or(""),
|
||||
row.details.as_str(),
|
||||
]
|
||||
.iter()
|
||||
.any(|text| text.to_lowercase().contains(&needle))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if events.len() == EVENT_LIMIT {
|
||||
more = true;
|
||||
break;
|
||||
}
|
||||
events.push(json!({
|
||||
"id":row.id.unwrap(),
|
||||
"action":row.action,
|
||||
"actor":actor_name,
|
||||
"details":serde_json::from_str::<Value>(&row.details).unwrap_or(Value::Null),
|
||||
"created_at":row.created_at,
|
||||
}));
|
||||
}
|
||||
Ok(json!({"events":events,"more":more}))
|
||||
}
|
||||
Reference in new issue
Block a user