2023-04-01 03:37:49 -05:00
|
|
|
import { randomUUID } from 'node:crypto';
|
2023-04-01 09:16:56 -05:00
|
|
|
import { z } from 'zod';
|
2023-04-01 02:53:09 -05:00
|
|
|
|
|
|
|
import type {
|
2024-07-05 03:36:40 -05:00
|
|
|
CreateConnector,
|
2023-04-01 02:53:09 -05:00
|
|
|
GetAuthorizationUri,
|
|
|
|
GetUserInfo,
|
|
|
|
SocialConnector,
|
|
|
|
} from '@logto/connector-kit';
|
2024-03-19 01:05:42 -05:00
|
|
|
import {
|
|
|
|
ConnectorError,
|
|
|
|
ConnectorErrorCodes,
|
|
|
|
ConnectorType,
|
|
|
|
jsonGuard,
|
|
|
|
} from '@logto/connector-kit';
|
2023-04-01 02:53:09 -05:00
|
|
|
|
|
|
|
import { defaultMetadata } from './constant.js';
|
|
|
|
import { mockSocialConfigGuard } from './types.js';
|
|
|
|
|
2024-07-05 03:36:40 -05:00
|
|
|
const getAuthorizationUri: GetAuthorizationUri = async (
|
|
|
|
{ state, redirectUri, connectorId },
|
|
|
|
setSession
|
|
|
|
) => {
|
|
|
|
try {
|
|
|
|
await setSession({ state, redirectUri, connectorId });
|
|
|
|
} catch (error: unknown) {
|
|
|
|
// Ignore the error if the method is not implemented
|
|
|
|
if (!(error instanceof ConnectorError && error.code === ConnectorErrorCodes.NotImplemented)) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-07 08:40:26 -05:00
|
|
|
return `http://mock-social/?state=${state}&redirect_uri=${redirectUri}`;
|
2023-04-01 02:53:09 -05:00
|
|
|
};
|
|
|
|
|
2024-07-05 03:36:40 -05:00
|
|
|
const getUserInfo: GetUserInfo = async (data, getSession) => {
|
2023-04-01 02:53:09 -05:00
|
|
|
const dataGuard = z.object({
|
|
|
|
code: z.string(),
|
|
|
|
userId: z.optional(z.string()),
|
|
|
|
email: z.string().optional(),
|
|
|
|
phone: z.string().optional(),
|
2024-07-19 04:41:55 -05:00
|
|
|
name: z.string().optional(),
|
|
|
|
avatar: z.string().optional(),
|
2023-04-01 02:53:09 -05:00
|
|
|
});
|
|
|
|
const result = dataGuard.safeParse(data);
|
|
|
|
|
|
|
|
if (!result.success) {
|
|
|
|
throw new ConnectorError(ConnectorErrorCodes.InvalidResponse, JSON.stringify(data));
|
|
|
|
}
|
|
|
|
|
2024-07-05 03:36:40 -05:00
|
|
|
try {
|
|
|
|
const connectorSession = await getSession();
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
|
|
if (!connectorSession) {
|
|
|
|
throw new ConnectorError(ConnectorErrorCodes.AuthorizationFailed);
|
|
|
|
}
|
|
|
|
} catch (error: unknown) {
|
|
|
|
// Ignore the error if the method is not implemented
|
|
|
|
if (!(error instanceof ConnectorError && error.code === ConnectorErrorCodes.NotImplemented)) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-01 02:53:09 -05:00
|
|
|
const { code, userId, ...rest } = result.data;
|
|
|
|
|
|
|
|
// For mock use only. Use to track the created user entity
|
|
|
|
return {
|
|
|
|
id: userId ?? `mock-social-sub-${randomUUID()}`,
|
|
|
|
...rest,
|
2024-03-19 01:05:42 -05:00
|
|
|
rawData: jsonGuard.parse(data),
|
2023-04-01 02:53:09 -05:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const createMockSocialConnector: CreateConnector<SocialConnector> = async ({ getConfig }) => {
|
|
|
|
return {
|
|
|
|
metadata: defaultMetadata,
|
|
|
|
type: ConnectorType.Social,
|
|
|
|
configGuard: mockSocialConfigGuard,
|
|
|
|
getAuthorizationUri,
|
|
|
|
getUserInfo,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
export default createMockSocialConnector;
|