fix(server): do not allow registration through gql (#6775)

This commit is contained in:
forehalo
2024-05-06 11:11:56 +00:00
parent 4ea31cbb35
commit d657f4091a
3 changed files with 39 additions and 74 deletions

View File

@@ -1,7 +1,6 @@
import { BadRequestException, ForbiddenException } from '@nestjs/common'; import { BadRequestException, ForbiddenException } from '@nestjs/common';
import { import {
Args, Args,
Context,
Field, Field,
Mutation, Mutation,
ObjectType, ObjectType,
@@ -10,7 +9,6 @@ import {
ResolveField, ResolveField,
Resolver, Resolver,
} from '@nestjs/graphql'; } from '@nestjs/graphql';
import type { Request, Response } from 'express';
import { Config, SkipThrottle, Throttle } from '../../fundamentals'; import { Config, SkipThrottle, Throttle } from '../../fundamentals';
import { UserService } from '../user'; import { UserService } from '../user';
@@ -79,39 +77,6 @@ export class AuthResolver {
}; };
} }
@Public()
@Mutation(() => UserType)
async signUp(
@Context() ctx: { req: Request; res: Response },
@Args('name') name: string,
@Args('email') email: string,
@Args('password') password: string
) {
if (!this.config.auth.allowSignup) {
throw new ForbiddenException('You are not allowed to sign up.');
}
validators.assertValidCredential({ email, password });
const user = await this.auth.signUp(name, email, password);
await this.auth.setCookie(ctx.req, ctx.res, user);
ctx.req.user = user;
return user;
}
@Public()
@Mutation(() => UserType)
async signIn(
@Context() ctx: { req: Request; res: Response },
@Args('email') email: string,
@Args('password') password: string
) {
validators.assertValidEmail(email);
const user = await this.auth.signIn(email, password);
await this.auth.setCookie(ctx.req, ctx.res, user);
ctx.req.user = user;
return user;
}
@Mutation(() => UserType) @Mutation(() => UserType)
async changePassword( async changePassword(
@CurrentUser() user: CurrentUser, @CurrentUser() user: CurrentUser,

View File

@@ -35,6 +35,7 @@ export class UserService {
async createUser(data: Prisma.UserCreateInput) { async createUser(data: Prisma.UserCreateInput) {
return this.prisma.user.create({ return this.prisma.user.create({
select: this.defaultUserSelect,
data: { data: {
...this.userCreatingData, ...this.userCreatingData,
...data, ...data,
@@ -113,18 +114,32 @@ export class UserService {
Pick<Prisma.UserCreateInput, 'emailVerifiedAt' | 'registered'> Pick<Prisma.UserCreateInput, 'emailVerifiedAt' | 'registered'>
> >
) { ) {
return this.prisma.user.upsert({ const user = await this.findUserByEmail(email);
select: this.defaultUserSelect, if (!user) {
where: { return this.createUser({
email,
},
update: data,
create: {
email,
...this.userCreatingData, ...this.userCreatingData,
email,
name: email.split('@')[0],
...data, ...data,
}, });
}); } else {
if (user.registered) {
delete data.registered;
}
if (user.emailVerifiedAt) {
delete data.emailVerifiedAt;
}
if (Object.keys(data).length) {
return await this.prisma.user.update({
select: this.defaultUserSelect,
where: { id: user.id },
data,
});
}
}
return user;
} }
async deleteUser(id: string) { async deleteUser(id: string) {

View File

@@ -1,5 +1,5 @@
import type { INestApplication } from '@nestjs/common'; import type { INestApplication } from '@nestjs/common';
import { PrismaClient } from '@prisma/client'; import { hashSync } from '@node-rs/argon2';
import request, { type Response } from 'supertest'; import request, { type Response } from 'supertest';
import { import {
@@ -7,7 +7,8 @@ import {
type ClientTokenType, type ClientTokenType,
type CurrentUser, type CurrentUser,
} from '../../src/core/auth'; } from '../../src/core/auth';
import type { UserType } from '../../src/core/user'; import { sessionUser } from '../../src/core/auth/service';
import { UserService, type UserType } from '../../src/core/user';
import { gql } from './common'; import { gql } from './common';
export async function internalSignIn(app: INestApplication, userId: string) { export async function internalSignIn(app: INestApplication, userId: string) {
@@ -50,34 +51,18 @@ export async function signUp(
password: string, password: string,
autoVerifyEmail = true autoVerifyEmail = true
): Promise<UserType & { token: ClientTokenType }> { ): Promise<UserType & { token: ClientTokenType }> {
const res = await request(app.getHttpServer()) const user = await app.get(UserService).createUser({
.post(gql) name,
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' }) email,
.send({ password: hashSync(password),
query: ` emailVerifiedAt: autoVerifyEmail ? new Date() : null,
mutation {
signUp(name: "${name}", email: "${email}", password: "${password}") {
id, name, email, token { token }
}
}
`,
})
.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(),
},
}); });
const { sessionId } = await app.get(AuthService).createUserSession(user);
return {
...sessionUser(user),
token: { token: sessionId, refresh: '' },
};
} }
export async function currentUser(app: INestApplication, token: string) { export async function currentUser(app: INestApplication, token: string) {