mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6b2889f1d | |||
| 69a3346280 |
@@ -41,6 +41,75 @@ describe("userProvisioner", () => {
|
||||
expect(isNewUser).toEqual(false);
|
||||
});
|
||||
|
||||
it("should remove all other UserAuthentication records on sign-in", async () => {
|
||||
const existing = await buildUser();
|
||||
const authentications = await existing.$get("authentications");
|
||||
const existingAuth = authentications[0];
|
||||
|
||||
// Create a second authentication record for the same provider (simulating a stale/duplicate record)
|
||||
const staleAuthSameProvider = await existing.$create("authentication", {
|
||||
authenticationProviderId: existingAuth.authenticationProviderId,
|
||||
providerId: randomUUID(),
|
||||
accessToken: "old-token",
|
||||
scopes: ["read"],
|
||||
});
|
||||
|
||||
// Create a third authentication record for a different provider
|
||||
const team = await existing.$get("team");
|
||||
const otherProvider = await team!.$create("authenticationProvider", {
|
||||
name: "other-provider",
|
||||
providerId: randomUUID(),
|
||||
});
|
||||
const staleAuthDifferentProvider = await existing.$create(
|
||||
"authentication",
|
||||
{
|
||||
authenticationProviderId: otherProvider.id,
|
||||
providerId: randomUUID(),
|
||||
accessToken: "other-provider-token",
|
||||
scopes: ["read"],
|
||||
}
|
||||
);
|
||||
|
||||
// Verify we have 3 auth records
|
||||
const authsBefore = await existing.$get("authentications");
|
||||
expect(authsBefore.length).toEqual(3);
|
||||
|
||||
// Sign in with the original providerId
|
||||
const result = await userProvisioner(ctx, {
|
||||
name: existing.name,
|
||||
email: existing.email!,
|
||||
avatarUrl: existing.avatarUrl,
|
||||
teamId: existing.teamId,
|
||||
authentication: {
|
||||
authenticationProviderId: existingAuth.authenticationProviderId,
|
||||
providerId: existingAuth.providerId,
|
||||
accessToken: "new-token",
|
||||
scopes: ["read", "write"],
|
||||
},
|
||||
});
|
||||
|
||||
const { user, authentication } = result;
|
||||
expect(authentication).toBeDefined();
|
||||
expect(authentication?.accessToken).toEqual("new-token");
|
||||
|
||||
// Verify all stale authentications were removed (including from different provider)
|
||||
const authsAfter = await user.$get("authentications");
|
||||
expect(authsAfter.length).toEqual(1);
|
||||
expect(authsAfter[0].id).toEqual(existingAuth.id);
|
||||
expect(authsAfter[0].accessToken).toEqual("new-token");
|
||||
|
||||
// Verify both stale auths were actually deleted from the database
|
||||
const { UserAuthentication } = await import("@server/models");
|
||||
const deletedAuth1 = await UserAuthentication.findByPk(
|
||||
staleAuthSameProvider.id
|
||||
);
|
||||
expect(deletedAuth1).toBeNull();
|
||||
const deletedAuth2 = await UserAuthentication.findByPk(
|
||||
staleAuthDifferentProvider.id
|
||||
);
|
||||
expect(deletedAuth2).toBeNull();
|
||||
});
|
||||
|
||||
it("should add authentication provider to existing users", async () => {
|
||||
const team = await buildTeam({ inviteRequired: true });
|
||||
const teamAuthProviders = await team.$get("authenticationProviders");
|
||||
@@ -110,6 +179,80 @@ describe("userProvisioner", () => {
|
||||
expect(isNewUser).toEqual(true);
|
||||
});
|
||||
|
||||
it("should remove all stale authentications when adding to invited user", async () => {
|
||||
const team = await buildTeam({ inviteRequired: true });
|
||||
const teamAuthProviders = await team.$get("authenticationProviders");
|
||||
const authenticationProvider = teamAuthProviders[0];
|
||||
|
||||
const email = "mynam@email.com";
|
||||
const existing = await buildInvite({
|
||||
email,
|
||||
teamId: team.id,
|
||||
});
|
||||
|
||||
// Create a stale authentication record for the same provider
|
||||
const staleAuthSameProvider = await existing.$create("authentication", {
|
||||
authenticationProviderId: authenticationProvider.id,
|
||||
providerId: randomUUID(),
|
||||
accessToken: "old-expired-token",
|
||||
scopes: ["read"],
|
||||
});
|
||||
|
||||
// Create a stale authentication record for a different provider
|
||||
const otherProvider = await team.$create("authenticationProvider", {
|
||||
name: "other-provider",
|
||||
providerId: randomUUID(),
|
||||
});
|
||||
const staleAuthDifferentProvider = await existing.$create(
|
||||
"authentication",
|
||||
{
|
||||
authenticationProviderId: otherProvider.id,
|
||||
providerId: randomUUID(),
|
||||
accessToken: "other-provider-token",
|
||||
scopes: ["read"],
|
||||
}
|
||||
);
|
||||
|
||||
// Verify the stale auths exist
|
||||
const authsBefore = await existing.$get("authentications");
|
||||
expect(authsBefore.length).toEqual(2);
|
||||
|
||||
// Sign in with a new providerId
|
||||
const result = await userProvisioner(ctx, {
|
||||
name: existing.name,
|
||||
email,
|
||||
avatarUrl: existing.avatarUrl,
|
||||
teamId: existing.teamId,
|
||||
authentication: {
|
||||
authenticationProviderId: authenticationProvider.id,
|
||||
providerId: randomUUID(),
|
||||
accessToken: "new-token",
|
||||
scopes: ["read", "write"],
|
||||
},
|
||||
});
|
||||
|
||||
const { user, authentication, isNewUser } = result;
|
||||
expect(authentication).toBeDefined();
|
||||
expect(authentication?.accessToken).toEqual("new-token");
|
||||
expect(isNewUser).toEqual(true);
|
||||
|
||||
// Verify only the new authentication exists
|
||||
const authsAfter = await user.$get("authentications");
|
||||
expect(authsAfter.length).toEqual(1);
|
||||
expect(authsAfter[0].accessToken).toEqual("new-token");
|
||||
|
||||
// Verify both stale auths were deleted
|
||||
const { UserAuthentication } = await import("@server/models");
|
||||
const deletedAuth1 = await UserAuthentication.findByPk(
|
||||
staleAuthSameProvider.id
|
||||
);
|
||||
expect(deletedAuth1).toBeNull();
|
||||
const deletedAuth2 = await UserAuthentication.findByPk(
|
||||
staleAuthDifferentProvider.id
|
||||
);
|
||||
expect(deletedAuth2).toBeNull();
|
||||
});
|
||||
|
||||
it("should create user with deleted user matching providerId", async () => {
|
||||
const existing = await buildUser();
|
||||
const authentications = await existing.$get("authentications");
|
||||
|
||||
@@ -99,6 +99,17 @@ export default async function userProvisioner(
|
||||
await user.update({ email });
|
||||
await auth.update(rest);
|
||||
|
||||
// Remove any other UserAuthentication records for the user
|
||||
// to prevent expired tokens from causing premature logout
|
||||
await UserAuthentication.destroy({
|
||||
where: {
|
||||
userId: user.id,
|
||||
id: {
|
||||
[Op.ne]: auth.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
user,
|
||||
authentication: auth,
|
||||
@@ -160,6 +171,15 @@ export default async function userProvisioner(
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove any other UserAuthentication records for the user
|
||||
// to prevent expired tokens from causing premature logout
|
||||
await UserAuthentication.destroy({
|
||||
where: {
|
||||
userId: existingUser.id,
|
||||
},
|
||||
transaction,
|
||||
});
|
||||
|
||||
return await existingUser.$create<UserAuthentication>(
|
||||
"authentication",
|
||||
authentication,
|
||||
|
||||
Reference in New Issue
Block a user