Merge NEXT: planning, generation map and portable configuration on top of the OIDC access model
NEXT predates the access work, so the identity layer follows master: access comes from configured groups, instance administrators replace the site administration, and accounts are created by SSO or by an administrator. Kept from NEXT: manual publication with the Review changes panel and shared generator drafts, portable import/export (meguri/v2), the layered generation map with binding provenance, JSM provider changes, contact/approval semantics and the account-owned Person. Dropped: site administration, local sign-up, and the mandatory unique email with its contact/account migrations. The manual-publication migration is renumbered m_0010 after m_0009_access. Accounts without an email still get a Person in every workspace they reach, a changed sign-in email updates the account's person, and an account that loses access keeps its linked person so schedules stay valid. Instance administrators may use Sync and shared drafts. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
38105c65c2
57 files changed
+6890
-431
No files matched your search
+32
-2
@@ -6,7 +6,7 @@ use meguri::{
|
||||
admin::{self, NewUser},
|
||||
domain::*,
|
||||
identity,
|
||||
models::UserRow,
|
||||
models::{HistoryRow, UserRow},
|
||||
service,
|
||||
store::{Store, WorkspaceRecord},
|
||||
};
|
||||
@@ -59,7 +59,7 @@ pub async fn account(db: &Store, config: &Config, name: &str, groups: &[String])
|
||||
username: format!("test-{}", Uuid::new_v4().simple()),
|
||||
display_name: name.into(),
|
||||
password: "test-only-password".into(),
|
||||
email: None,
|
||||
email: Some(format!("{}@example.com", Uuid::new_v4())),
|
||||
groups: groups.to_vec(),
|
||||
country: None,
|
||||
},
|
||||
@@ -123,6 +123,13 @@ impl Fixture {
|
||||
config,
|
||||
}
|
||||
}
|
||||
/// Makes `user` a workspace administrator of the fixture workspace through the group mapping.
|
||||
pub async fn make_admin(&self, user: &User) {
|
||||
let groups = self.config.workspaces[0].admin_groups.clone();
|
||||
identity::apply_access(&self.db, &self.config, user.id, Some(groups))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
/// A second workspace whose administrator group is granted to `admin` only.
|
||||
pub async fn extra_workspace(&self, name: &str, admin: &User) -> WorkspaceRecord {
|
||||
let extra = unique_workspace(name);
|
||||
@@ -175,6 +182,29 @@ impl Fixture {
|
||||
}
|
||||
}
|
||||
pub async fn prioritize_publication(&self) {
|
||||
let revision = self.db.workspace(self.team.id).await.unwrap().revision;
|
||||
self.db
|
||||
.retry(self.team.id, self.people[0].id, revision)
|
||||
.await
|
||||
.unwrap();
|
||||
// PostgreSQL and the worker can run on different host clocks. Publish only
|
||||
// once this test's latest committed revision has actually become effective.
|
||||
let workspace = self.team.id.to_string();
|
||||
let effective = query!(HistoryRow, $workspace_id == workspace)
|
||||
.all(&self.db.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|row| row.effective_at)
|
||||
.max()
|
||||
.unwrap();
|
||||
if let Ok(delay) = (effective - Utc::now()).to_std() {
|
||||
assert!(
|
||||
delay < std::time::Duration::from_secs(2),
|
||||
"Database clock is too far ahead of the test worker"
|
||||
);
|
||||
tokio::time::sleep(delay + std::time::Duration::from_millis(1)).await;
|
||||
}
|
||||
// The worker takes a bounded batch. Repeated runs leave other test tenants
|
||||
// in this disposable database, so explicitly put this test's job first.
|
||||
self.db
|
||||
|
||||
Reference in new issue
Block a user