diff --git a/.github/actions/deploy/deploy.mjs b/.github/actions/deploy/deploy.mjs index f2135915e..c5c7a43ce 100644 --- a/.github/actions/deploy/deploy.mjs +++ b/.github/actions/deploy/deploy.mjs @@ -63,9 +63,9 @@ const createHelmCommand = ({ isDryRun }) => { `--set-json sync.service.annotations=\"{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }\"`, ] : []; - const webReplicaCount = isProduction ? 3 : isBeta ? 2 : 1; - const graphqlReplicaCount = isProduction ? 3 : isBeta ? 2 : 1; - const syncReplicaCount = isProduction ? 6 : isBeta ? 3 : 1; + const webReplicaCount = isProduction ? 3 : isBeta ? 2 : 2; + const graphqlReplicaCount = isProduction ? 3 : isBeta ? 2 : 2; + const syncReplicaCount = isProduction ? 6 : isBeta ? 3 : 2; const namespace = isProduction ? 'production' : isBeta ? 'beta' : 'dev'; const deployCommand = [ `helm upgrade --install affine .github/helm/affine`, diff --git a/apps/core/src/components/affine/auth/sign-in.tsx b/apps/core/src/components/affine/auth/sign-in.tsx index d5c378609..39068ca79 100644 --- a/apps/core/src/components/affine/auth/sign-in.tsx +++ b/apps/core/src/components/affine/auth/sign-in.tsx @@ -21,6 +21,8 @@ function validateEmail(email: string) { return emailRegex.test(email); } +const INTERNAL_BETA_URL = `https://community.affine.pro/c/insider-general/`; + function handleSendEmailError( res: SignInResponse | undefined, pushNotification: (notification: Notification) => void @@ -32,6 +34,13 @@ function handleSendEmailError( type: 'error', }); } + if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) { + pushNotification({ + title: 'Sign up error', + message: `You don't have early access permission\nVisit ${INTERNAL_BETA_URL} for more information`, + type: 'error', + }); + } } export const SignIn: FC = ({ diff --git a/apps/server/package.json b/apps/server/package.json index 33e72e8d9..175c16580 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -74,6 +74,7 @@ "@napi-rs/image": "^1.6.1", "@nestjs/testing": "^10.2.1", "@types/cookie-parser": "^1.4.3", + "@types/engine.io": "^3.1.7", "@types/express": "^4.17.17", "@types/lodash-es": "^4.17.8", "@types/node": "^18.17.11", diff --git a/apps/server/src/modules/auth/next-auth-options.ts b/apps/server/src/modules/auth/next-auth-options.ts index 051b1f2ce..2729aa2cf 100644 --- a/apps/server/src/modules/auth/next-auth-options.ts +++ b/apps/server/src/modules/auth/next-auth-options.ts @@ -266,15 +266,16 @@ export const NextAuthOptionsProvider: FactoryProvider = { } return session; }, - signIn: async ({ profile }) => { + signIn: async ({ profile, user }) => { if (!config.affine.beta || !config.node.prod) { return true; } - if (profile?.email) { - return await prisma.newFeaturesWaitingList + const email = profile?.email ?? user.email; + if (email) { + return prisma.newFeaturesWaitingList .findUnique({ where: { - email: profile.email, + email, type: NewFeaturesKind.EarlyAccess, }, }) diff --git a/apps/server/src/modules/auth/next-auth.controller.ts b/apps/server/src/modules/auth/next-auth.controller.ts index 51ec0727f..014b8e75b 100644 --- a/apps/server/src/modules/auth/next-auth.controller.ts +++ b/apps/server/src/modules/auth/next-auth.controller.ts @@ -3,6 +3,7 @@ import { BadRequestException, Controller, Inject, + Logger, Next, NotFoundException, Query, @@ -27,6 +28,8 @@ const BASE_URL = '/api/auth/'; export class NextAuthController { private readonly callbackSession; + private readonly logger = new Logger('NextAuthController'); + constructor( readonly config: Config, readonly prisma: PrismaService, @@ -120,7 +123,11 @@ export class NextAuthController { } if (redirect?.endsWith('api/auth/error?error=AccessDenied')) { - res.redirect('https://community.affine.pro/c/insider-general/'); + res.status(403); + res.json({ + url: 'https://community.affine.pro/c/insider-general/', + error: `You don't have early access permission`, + }); return; } @@ -129,7 +136,7 @@ export class NextAuthController { } if (redirect) { - console.log(providerId, action, req.headers); + this.logger.debug(providerId, action, req.headers); if (providerId === 'credentials') { res.send(JSON.stringify({ ok: true, url: redirect })); } else if ( diff --git a/apps/server/src/modules/sync/events/events.gateway.ts b/apps/server/src/modules/sync/events/events.gateway.ts index 082fe82bd..81daedd2f 100644 --- a/apps/server/src/modules/sync/events/events.gateway.ts +++ b/apps/server/src/modules/sync/events/events.gateway.ts @@ -16,6 +16,7 @@ import { DocManager } from '../../doc'; @WebSocketGateway({ cors: process.env.NODE_ENV !== 'production', + transports: ['websocket'], }) export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect { private connectionCount = 0; diff --git a/packages/workspace/src/affine/index.ts b/packages/workspace/src/affine/index.ts index 9d6d47cb5..bbe9ab1d5 100644 --- a/packages/workspace/src/affine/index.ts +++ b/packages/workspace/src/affine/index.ts @@ -22,6 +22,7 @@ function getIoManager(): Manager { } ioManager = new Manager(runtimeConfig.serverUrlPrefix + '/', { autoConnect: false, + transports: ['websocket'], }); return ioManager; } diff --git a/yarn.lock b/yarn.lock index 93ca8b8af..a0a68ca75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -689,6 +689,7 @@ __metadata: "@prisma/instrumentation": ^5.0.0 "@socket.io/redis-adapter": ^8.2.1 "@types/cookie-parser": ^1.4.3 + "@types/engine.io": ^3.1.7 "@types/express": ^4.17.17 "@types/lodash-es": ^4.17.8 "@types/node": ^18.17.11 @@ -12963,6 +12964,15 @@ __metadata: languageName: node linkType: hard +"@types/engine.io@npm:^3.1.7": + version: 3.1.7 + resolution: "@types/engine.io@npm:3.1.7" + dependencies: + "@types/node": "*" + checksum: 62b129eac3fca625cfae4591d4fab56872c44c1f7bb625af2f9e6c1bb28f8210276026e1007dc2da433ee5943972534078402515168135cc155a18c41dfec6a2 + languageName: node + linkType: hard + "@types/escodegen@npm:^0.0.6": version: 0.0.6 resolution: "@types/escodegen@npm:0.0.6"