fix: follow a non-member superadmin's instance username on the OAuth accounts they created

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-10-16 10:27:21 +02:00
co-authored by Claude Opus 5.5
parent 245d03b254
commit ae87cff76f
3 changed files with 49 additions and 0 deletions
@@ -1,2 +1,4 @@
DROP TRIGGER IF EXISTS account_created_by_follows_instance_user_trigger ON password;
DROP FUNCTION IF EXISTS account_created_by_follows_instance_user();
DROP TRIGGER IF EXISTS account_created_by_follows_user_trigger ON usr;
DROP FUNCTION IF EXISTS account_created_by_follows_user();
@@ -19,3 +19,28 @@ CREATE TRIGGER account_created_by_follows_user_trigger
AFTER UPDATE OF username OR DELETE ON usr
FOR EACH ROW
EXECUTE FUNCTION account_created_by_follows_user();
-- A superadmin can connect an account in a workspace they are not a member of, which records
-- their instance username with no `usr` row for the trigger above to follow. Follow
-- `password.username` there instead, skipping workspaces where they are a member (handled above)
-- and those where a member holds that username (the name is theirs).
CREATE OR REPLACE FUNCTION account_created_by_follows_instance_user() RETURNS trigger AS $$
BEGIN
IF TG_OP = 'UPDATE' AND NEW.username IS NOT DISTINCT FROM OLD.username THEN
RETURN NULL;
END IF;
UPDATE account a SET created_by = CASE WHEN TG_OP = 'DELETE' THEN NULL ELSE NEW.username END
WHERE a.created_by = OLD.username
AND NOT EXISTS (
SELECT 1 FROM usr u
WHERE u.workspace_id = a.workspace_id
AND (u.email = OLD.email OR u.username = OLD.username)
);
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER account_created_by_follows_instance_user_trigger
AFTER UPDATE OF username OR DELETE ON password
FOR EACH ROW
EXECUTE FUNCTION account_created_by_follows_instance_user();
@@ -482,5 +482,27 @@ async fn test_oauth_account_creator_follows_user(db: Pool<Postgres>) -> anyhow::
.await?;
assert_eq!(creator().await?, None);
// A superadmin who is not a member of the workspace is recorded by their instance username.
sqlx::query(
"INSERT INTO password (email, password_hash, login_type, super_admin, verified, username)
VALUES ('sa@windmill.dev', 'x', 'password', true, true, 'sa')",
)
.execute(&db)
.await?;
sqlx::query("UPDATE account SET created_by = 'sa' WHERE id = $1")
.bind(account)
.execute(&db)
.await?;
sqlx::query("UPDATE password SET username = 'sa2' WHERE email = 'sa@windmill.dev'")
.execute(&db)
.await?;
assert_eq!(creator().await?.as_deref(), Some("sa2"));
sqlx::query("DELETE FROM password WHERE email = 'sa@windmill.dev'")
.execute(&db)
.await?;
assert_eq!(creator().await?, None);
Ok(())
}