mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
feat: update server login feature (#3004)
Co-authored-by: LongYinan <lynweklm@gmail.com>
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
SECRET_KEY="secret"
|
||||
DATABASE_URL="postgresql://affine@localhost:5432/affine"
|
||||
NEXTAUTH_URL="http://localhost:8080"
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"@node-rs/crc32": "^1.7.0",
|
||||
"@node-rs/jsonwebtoken": "^0.2.0",
|
||||
"@prisma/client": "^4.16.2",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"graphql": "^16.7.1",
|
||||
@@ -34,6 +35,7 @@
|
||||
"graphql-upload": "^16.0.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"next-auth": "^4.22.1",
|
||||
"nodemailer": "^6.9.3",
|
||||
"parse-duration": "^1.1.0",
|
||||
"prisma": "^4.16.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
@@ -43,9 +45,11 @@
|
||||
"@affine/storage": "workspace:*",
|
||||
"@napi-rs/image": "^1.6.1",
|
||||
"@nestjs/testing": "^10.0.4",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/lodash-es": "^4.17.7",
|
||||
"@types/node": "^18.16.19",
|
||||
"@types/nodemailer": "^6.4.8",
|
||||
"@types/supertest": "^2.0.12",
|
||||
"c8": "^8.0.0",
|
||||
"nodemon": "^2.0.22",
|
||||
|
||||
@@ -233,5 +233,11 @@ export interface AFFiNEConfig {
|
||||
}
|
||||
>
|
||||
>;
|
||||
email: {
|
||||
server: string;
|
||||
port: number;
|
||||
sender: string;
|
||||
password: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
||||
OAUTH_GOOGLE_CLIENT_SECRET: 'auth.oauthProviders.google.clientSecret',
|
||||
OAUTH_GITHUB_CLIENT_ID: 'auth.oauthProviders.github.clientId',
|
||||
OAUTH_GITHUB_CLIENT_SECRET: 'auth.oauthProviders.github.clientSecret',
|
||||
OAUTH_EMAIL_SENDER: 'auth.email.sender',
|
||||
OAUTH_EMAIL_SERVER: 'auth.email.server',
|
||||
OAUTH_EMAIL_PORT: 'auth.email.port',
|
||||
OAUTH_EMAIL_PASSWORD: 'auth.email.password',
|
||||
} satisfies AFFiNEConfig['ENV_MAP'],
|
||||
env: process.env.NODE_ENV ?? 'development',
|
||||
get prod() {
|
||||
@@ -102,7 +106,6 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
||||
},
|
||||
introspection: true,
|
||||
playground: true,
|
||||
debug: true,
|
||||
},
|
||||
auth: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
@@ -114,8 +117,16 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
||||
publicKey: jwtKeyPair.publicKey,
|
||||
enableSignup: true,
|
||||
enableOauth: false,
|
||||
nextAuthSecret: '',
|
||||
get nextAuthSecret() {
|
||||
return this.privateKey;
|
||||
},
|
||||
oauthProviders: {},
|
||||
email: {
|
||||
server: 'smtp.gmail.com',
|
||||
port: 465,
|
||||
sender: '',
|
||||
password: '',
|
||||
},
|
||||
},
|
||||
objectStorage: {
|
||||
r2: {
|
||||
@@ -129,7 +140,7 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
||||
path: join(homedir(), '.affine-storage'),
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
} satisfies AFFiNEConfig;
|
||||
|
||||
applyEnvToConfig(defaultConfig);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/// <reference types="./global.d.ts" />
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import type { NestExpressApplication } from '@nestjs/platform-express';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import { static as staticMiddleware } from 'express';
|
||||
// @ts-expect-error graphql-upload is not typed
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
||||
@@ -27,6 +28,8 @@ app.use(
|
||||
})
|
||||
);
|
||||
|
||||
app.use(cookieParser());
|
||||
|
||||
const config = app.get(Config);
|
||||
|
||||
const host = config.host ?? 'localhost';
|
||||
|
||||
@@ -2,11 +2,10 @@ import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { PrismaAdapter } from '@auth/prisma-adapter';
|
||||
import {
|
||||
All,
|
||||
BadRequestException,
|
||||
Controller,
|
||||
Get,
|
||||
Next,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
Res,
|
||||
@@ -15,6 +14,7 @@ import { Algorithm, sign, verify as jwtVerify } from '@node-rs/jsonwebtoken';
|
||||
import type { NextFunction, Request, Response } from 'express';
|
||||
import type { AuthAction, AuthOptions } from 'next-auth';
|
||||
import { AuthHandler } from 'next-auth/core';
|
||||
import Email from 'next-auth/providers/email';
|
||||
import Github from 'next-auth/providers/github';
|
||||
import Google from 'next-auth/providers/google';
|
||||
|
||||
@@ -29,15 +29,40 @@ export class NextAuthController {
|
||||
private readonly nextAuthOptions: AuthOptions;
|
||||
|
||||
constructor(readonly config: Config, readonly prisma: PrismaService) {
|
||||
const prismaAdapter = PrismaAdapter(prisma);
|
||||
// createUser exists in the adapter
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const createUser = prismaAdapter.createUser!.bind(prismaAdapter);
|
||||
prismaAdapter.createUser = async data => {
|
||||
if (data.email && !data.name) {
|
||||
data.name = data.email.split('@')[0];
|
||||
}
|
||||
return createUser(data);
|
||||
};
|
||||
this.nextAuthOptions = {
|
||||
providers: [],
|
||||
providers: [
|
||||
// @ts-expect-error esm interop issue
|
||||
Email.default({
|
||||
server: {
|
||||
host: config.auth.email.server,
|
||||
port: config.auth.email.port,
|
||||
auth: {
|
||||
user: config.auth.email.sender,
|
||||
pass: config.auth.email.password,
|
||||
},
|
||||
},
|
||||
from: `AFFiNE <no-reply@toeverything.info>`,
|
||||
}),
|
||||
],
|
||||
// @ts-expect-error Third part library type mismatch
|
||||
adapter: PrismaAdapter(prisma),
|
||||
adapter: prismaAdapter,
|
||||
debug: !config.prod,
|
||||
};
|
||||
|
||||
if (config.auth.oauthProviders.github) {
|
||||
this.nextAuthOptions.providers.push(
|
||||
Github({
|
||||
// @ts-expect-error esm interop issue
|
||||
Github.default({
|
||||
clientId: config.auth.oauthProviders.github.clientId,
|
||||
clientSecret: config.auth.oauthProviders.github.clientSecret,
|
||||
})
|
||||
@@ -46,12 +71,14 @@ export class NextAuthController {
|
||||
|
||||
if (config.auth.oauthProviders.google) {
|
||||
this.nextAuthOptions.providers.push(
|
||||
Google({
|
||||
// @ts-expect-error esm interop issue
|
||||
Google.default({
|
||||
clientId: config.auth.oauthProviders.google.clientId,
|
||||
clientSecret: config.auth.oauthProviders.google.clientSecret,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
this.nextAuthOptions.jwt = {
|
||||
encode: async ({ token, maxAge }) => {
|
||||
if (!token?.email) {
|
||||
@@ -108,8 +135,7 @@ export class NextAuthController {
|
||||
this.nextAuthOptions.secret ??= config.auth.nextAuthSecret;
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Post()
|
||||
@All('*')
|
||||
async auth(
|
||||
@Req() req: Request,
|
||||
@Res() res: Response,
|
||||
|
||||
Reference in New Issue
Block a user