0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

feat(core): add sign-in timestamp in session interaction (#2325)

This commit is contained in:
Charles Zhao 2022-11-09 15:10:37 +08:00 committed by GitHub
parent 960fbc38c4
commit ec36266a1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 26 deletions

View file

@ -1,3 +1,5 @@
import { conditional } from '@silverhand/essentials';
import { getUnixTime } from 'date-fns';
import type { Context } from 'koa';
import type { InteractionResults, Provider } from 'oidc-provider';
@ -14,20 +16,32 @@ export const assignInteractionResults = async (
// have to do it manually
// refer to: https://github.com/panva/node-oidc-provider/blob/c243bf6b6663c41ff3e75c09b95fb978eba87381/lib/actions/authorization/interactions.js#L106
const details = merge ? await provider.interactionDetails(ctx.req, ctx.res) : undefined;
const ts = getUnixTime(new Date());
const mergedResult = {
// Merge with current result
...details?.result,
...result,
};
const redirectTo = await provider.interactionResult(
ctx.req,
ctx.res,
{
// Merge with current result
...details?.result,
...result,
...mergedResult,
...conditional(
mergedResult.login && {
login: {
...mergedResult.login,
// Update ts(timestamp) if the accountId has been set in result
ts: result.login?.accountId ? ts : mergedResult.login.ts,
},
}
),
},
{
mergeWithLastSubmission: merge,
}
);
ctx.body = { redirectTo };
ctx.body = { redirectTo, ts };
};
export const saveUserFirstConsentedAppId = async (userId: string, applicationId: string) => {

View file

@ -89,7 +89,8 @@ describe('session -> continueRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: mockUser.id } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: mockUser.id, ts: expect.any(Number) } }),
expect.anything()
);
});
@ -121,7 +122,8 @@ describe('session -> continueRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: mockUser.id } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: mockUser.id, ts: expect.any(Number) } }),
expect.anything()
);
});
@ -156,7 +158,8 @@ describe('session -> continueRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: mockUser.id } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: mockUser.id, ts: expect.any(Number) } }),
expect.anything()
);
});
@ -188,7 +191,8 @@ describe('session -> continueRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: mockUser.id } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: mockUser.id, ts: expect.any(Number) } }),
expect.anything()
);
});

View file

@ -111,7 +111,8 @@ describe('session -> password routes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: 'id' } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: 'id', ts: expect.any(Number) } }),
expect.anything()
);
});
@ -127,7 +128,8 @@ describe('session -> password routes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: 'id' } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: 'id', ts: expect.any(Number) } }),
expect.anything()
);
});
@ -143,7 +145,8 @@ describe('session -> password routes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: 'id' } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: 'id', ts: expect.any(Number) } }),
expect.anything()
);
});
@ -172,7 +175,8 @@ describe('session -> password routes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: 'user1' } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: 'user1', ts: expect.any(Number) } }),
expect.anything()
);
jest.useRealTimers();

View file

@ -392,7 +392,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: mockUser.id },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: mockUser.id, ts: expect.any(Number) },
}),
expect.anything()
);
@ -414,7 +415,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: mockUser.id },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: mockUser.id, ts: expect.any(Number) },
}),
expect.anything()
);
@ -555,7 +557,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: mockUser.id },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: mockUser.id, ts: expect.any(Number) },
}),
expect.anything()
);
@ -579,7 +582,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: mockUser.id },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: mockUser.id, ts: expect.any(Number) },
}),
expect.anything()
);
@ -688,7 +692,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: 'user1' },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: 'user1', ts: expect.any(Number) },
}),
expect.anything()
);
@ -710,7 +715,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: 'user1' },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: 'user1', ts: expect.any(Number) },
}),
expect.anything()
);
@ -816,7 +822,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: 'user1' },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: 'user1', ts: expect.any(Number) },
}),
expect.anything()
);
@ -838,7 +845,8 @@ describe('session -> passwordlessRoutes', () => {
expect.anything(),
expect.anything(),
expect.objectContaining({
login: { accountId: 'user1' },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
login: { accountId: 'user1', ts: expect.any(Number) },
}),
expect.anything()
);

View file

@ -1,3 +1,4 @@
/* eslint-disable max-lines */
import { ConnectorType } from '@logto/connector-kit';
import type { User } from '@logto/schemas';
import { SignUpIdentifier } from '@logto/schemas';
@ -233,7 +234,8 @@ describe('session -> socialRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: mockUser.id } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: mockUser.id, ts: expect.any(Number) } }),
expect.anything()
);
});
@ -316,7 +318,8 @@ describe('session -> socialRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: 'user1' } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: 'user1', ts: expect.any(Number) } }),
expect.anything()
);
});
@ -350,7 +353,8 @@ describe('session -> socialRoutes', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: 'user1' } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: 'user1', ts: expect.any(Number) } }),
expect.anything()
);
});
@ -364,7 +368,10 @@ describe('session -> socialRoutes', () => {
});
it('throw error if result parsing fails', async () => {
interactionDetails.mockResolvedValueOnce({ result: { login: { accountId: mockUser.id } } });
interactionDetails.mockResolvedValueOnce({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
result: { login: { accountId: mockUser.id, ts: expect.any(Number) } },
});
const response = await sessionRequest
.post(`${registerRoute}`)
.send({ connectorId: 'connectorId' });
@ -436,3 +443,4 @@ describe('session -> socialRoutes', () => {
});
});
});
/* eslint-enable max-lines */

View file

@ -121,7 +121,8 @@ describe('signInWithPassword()', () => {
expect(interactionResult).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ login: { accountId: mockUser.id } }),
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
expect.objectContaining({ login: { accountId: mockUser.id, ts: expect.any(Number) } }),
expect.anything()
);
});