Every credential provider says whether it still holds a consumer (hq issue 120) #84

Merged
jschoubben merged 4 commits from fix/120-redis-says-what-it-holds into main 2026-09-25 23:31:29 +00:00
3 changed files with 22 additions and 6 deletions
Showing only changes of commit 620b47d309 - Show all commits
+10 -2
View File
@@ -127,8 +127,16 @@ export class MailuClient {
}
async changePassword(email: string, password: string): Promise<void> {
// enabled: a disabled mailbox is what the provisioner's check reports as lost, so applying the
// mesh's password again also enables it; otherwise the two would disagree for ever.
await this.api("PATCH", `/user/${encodeURIComponent(email)}`, { raw_password: password });
}
/**
* Set the mesh's password on a mailbox the mesh provisions, and enable it. A disabled mailbox is
* what the provisioner's check reports as lost, so applying again must enable it, or the two would
* disagree for ever. Separate from changePassword, which an operator's tool uses and which must
* not re-enable a mailbox someone disabled.
*/
async applyProvisioned(email: string, password: string): Promise<void> {
await this.api("PATCH", `/user/${encodeURIComponent(email)}`, { raw_password: password, enabled: true });
}
+1 -1
View File
@@ -48,7 +48,7 @@ runProvisioner("smtp", {
try {
await mailu.createUser(email, p.password);
} catch {
await mailu.changePassword(email, p.password);
await mailu.applyProvisioned(email, p.password);
}
},
+11 -3
View File
@@ -148,9 +148,17 @@ export class MssqlClient {
if (users.length === 0) {
await this.exec(`CREATE USER ${ident(login)} FOR LOGIN ${ident(login)}`, database);
} else {
// Re-point an existing user at the login. A database restored from elsewhere keeps its user
// under the old login's SID, orphaned; this maps it back, and is a no-op when it already is.
await this.exec(`ALTER USER ${ident(login)} WITH LOGIN = ${ident(login)}`, database);
// Re-point an existing user at the login when its SID is not the login's: a database restored
// from elsewhere keeps its user under the old login's SID, orphaned. Only then, so a user that
// is already mapped is left alone.
const orphaned = await this.query(
`SELECT 1 AS ok FROM sys.database_principals WHERE name = ${literal(login)} ` +
`AND (sid IS NULL OR sid <> SUSER_SID(${literal(login)}))`,
database,
);
if (orphaned.length > 0) {
await this.exec(`ALTER USER ${ident(login)} WITH LOGIN = ${ident(login)}`, database);
}
}
await this.exec(`ALTER ROLE db_owner ADD MEMBER ${ident(login)}`, database);
}