refactor(server): auth (#5895)

Remove `next-auth` and implement our own Authorization/Authentication system from scratch.

## Server

- [x] tokens
  - [x] function
  - [x] encryption

- [x] AuthController
  - [x] /api/auth/sign-in
  - [x] /api/auth/sign-out
  - [x] /api/auth/session
  - [x] /api/auth/session (WE SUPPORT MULTI-ACCOUNT!)

- [x] OAuthPlugin
  - [x] OAuthController
  - [x] /oauth/login
  - [x] /oauth/callback
  - [x] Providers
    - [x] Google
    - [x] GitHub

## Client

- [x] useSession
- [x] cloudSignIn
- [x] cloudSignOut

## NOTE:

Tests will be adding in the future
This commit is contained in:
liuyi
2024-03-12 10:00:09 +00:00
parent af49e8cc41
commit fb3a0e7b8f
148 changed files with 3407 additions and 2851 deletions
+25 -8
View File
@@ -1,16 +1,18 @@
import type { INestApplication } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import request from 'supertest';
import type { TokenType } from '../../src/core/auth';
import type { UserType } from '../../src/core/users';
import type { ClientTokenType } from '../../src/core/auth';
import type { UserType } from '../../src/core/user';
import { gql } from './common';
export async function signUp(
app: INestApplication,
name: string,
email: string,
password: string
): Promise<UserType & { token: TokenType }> {
password: string,
autoVerifyEmail = true
): Promise<UserType & { token: ClientTokenType }> {
const res = await request(app.getHttpServer())
.post(gql)
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
@@ -24,9 +26,23 @@ export async function signUp(
`,
})
.expect(200);
if (autoVerifyEmail) {
await setEmailVerified(app, email);
}
return res.body.data.signUp;
}
async function setEmailVerified(app: INestApplication, email: string) {
await app.get(PrismaClient).user.update({
where: { email },
data: {
emailVerifiedAt: new Date(),
},
});
}
export async function currentUser(app: INestApplication, token: string) {
const res = await request(app.getHttpServer())
.post(gql)
@@ -36,7 +52,7 @@ export async function currentUser(app: INestApplication, token: string) {
query: `
query {
currentUser {
id, name, email, emailVerified, avatarUrl, createdAt, hasPassword,
id, name, email, emailVerified, avatarUrl, hasPassword,
token { token }
}
}
@@ -94,8 +110,9 @@ export async function sendVerifyChangeEmail(
export async function changeEmail(
app: INestApplication,
userToken: string,
token: string
): Promise<UserType & { token: TokenType }> {
token: string,
email: string
): Promise<UserType & { token: ClientTokenType }> {
const res = await request(app.getHttpServer())
.post(gql)
.auth(userToken, { type: 'bearer' })
@@ -103,7 +120,7 @@ export async function changeEmail(
.send({
query: `
mutation {
changeEmail(token: "${token}") {
changeEmail(token: "${token}", email: "${email}") {
id
name
avatarUrl
+13 -2
View File
@@ -1,11 +1,13 @@
import { INestApplication, ModuleMetadata } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { Query, Resolver } from '@nestjs/graphql';
import { Test, TestingModuleBuilder } from '@nestjs/testing';
import { PrismaClient } from '@prisma/client';
import cookieParser from 'cookie-parser';
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
import { AppModule, FunctionalityModules } from '../../src/app.module';
import { AuthModule } from '../../src/core/auth';
import { AuthGuard, AuthModule } from '../../src/core/auth';
import { UserFeaturesInit1698652531198 } from '../../src/data/migrations/1698652531198-user-features-init';
import { GqlModule } from '../../src/fundamentals/graphql';
@@ -78,7 +80,14 @@ export async function createTestingModule(
const builder = Test.createTestingModule({
imports,
providers: [MockResolver, ...(moduleDef.providers ?? [])],
providers: [
{
provide: APP_GUARD,
useClass: AuthGuard,
},
MockResolver,
...(moduleDef.providers ?? []),
],
controllers: moduleDef.controllers,
});
@@ -113,6 +122,8 @@ export async function createTestingApp(moduleDef: TestingModuleMeatdata = {}) {
})
);
app.use(cookieParser());
if (moduleDef.tapApp) {
moduleDef.tapApp(app);
}