diff --git a/src/errors/UserErrors.ts b/src/errors/UserErrors.ts index 37f2987..8cee607 100644 --- a/src/errors/UserErrors.ts +++ b/src/errors/UserErrors.ts @@ -4,7 +4,7 @@ import { NotAcceptableError, NotFoundError } from 'routing-controllers'; /** * Error to throw when no username or email is set. - * We somehow need to identify you :) + * We somehow need to identify you on login. */ export class UsernameOrEmailNeededError extends NotFoundError { @IsString() @@ -14,6 +14,18 @@ export class UsernameOrEmailNeededError extends NotFoundError { message = "No username or email is set!" } +/** + * Error to throw when no email is set. + * We somehow need to identify you :) + */ +export class UserEmailNeededError extends NotFoundError { + @IsString() + name = "UserEmailNeededError" + + @IsString() + message = "No email is set! \n You have to provide email addresses for users (used for password reset among others)." +} + /** * Error to throw when a user couldn't be found. */ diff --git a/src/models/actions/create/CreateUser.ts b/src/models/actions/create/CreateUser.ts index a5f20c2..50e5b7b 100644 --- a/src/models/actions/create/CreateUser.ts +++ b/src/models/actions/create/CreateUser.ts @@ -1,9 +1,9 @@ import * as argon2 from "argon2"; -import { IsBoolean, IsEmail, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; +import { IsBoolean, IsEmail, IsNotEmpty, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; import { getConnectionManager } from 'typeorm'; import * as uuid from 'uuid'; import { config } from '../../../config'; -import { UsernameOrEmailNeededError } from '../../../errors/UserErrors'; +import { UserEmailNeededError } from '../../../errors/UserErrors'; import { UserGroupNotFoundError } from '../../../errors/UserGroupErrors'; import { User } from '../../entities/User'; import { UserGroup } from '../../entities/UserGroup'; @@ -33,7 +33,7 @@ export class CreateUser { /** * The new user's username. - * You have to provide at least one of: {email, username}. + * You have to provide a email addres, so this is optional. */ @IsOptional() @IsString() @@ -41,12 +41,11 @@ export class CreateUser { /** * The new user's email address. - * You have to provide at least one of: {email, username}. */ @IsEmail() @IsString() - @IsOptional() - email?: string; + @IsNotEmpty() + email: string; /** * The new user's phone number. @@ -92,8 +91,8 @@ export class CreateUser { public async toEntity(): Promise { let newUser: User = new User(); - if (this.email === undefined && this.username === undefined) { - throw new UsernameOrEmailNeededError(); + if (!this.email) { + throw new UserEmailNeededError(); } newUser.email = this.email diff --git a/src/models/actions/update/UpdateUser.ts b/src/models/actions/update/UpdateUser.ts index 59d95a4..45726b7 100644 --- a/src/models/actions/update/UpdateUser.ts +++ b/src/models/actions/update/UpdateUser.ts @@ -1,8 +1,8 @@ import * as argon2 from "argon2"; -import { IsBoolean, IsEmail, IsInt, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; +import { IsBoolean, IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; import { getConnectionManager } from 'typeorm'; import { config } from '../../../config'; -import { UsernameOrEmailNeededError } from '../../../errors/AuthError'; +import { UserEmailNeededError } from '../../../errors/UserErrors'; import { UserGroupNotFoundError } from '../../../errors/UserGroupErrors'; import { User } from '../../entities/User'; import { UserGroup } from '../../entities/UserGroup'; @@ -40,7 +40,7 @@ export class UpdateUser { /** * The updated user's username. - * You have to provide at least one of: {email, username}. + * You have to provide a email addres, so this is optional. */ @IsOptional() @IsString() @@ -48,12 +48,11 @@ export class UpdateUser { /** * The updated user's email address. - * You have to provide at least one of: {email, username}. */ @IsEmail() @IsString() - @IsOptional() - email?: string; + @IsNotEmpty() + email: string; /** * The updated user's phone number. @@ -99,11 +98,11 @@ export class UpdateUser { * @param user The user that shall be updated. */ public async update(user: User): Promise { + if (!this.email) { + throw new UserEmailNeededError(); + } user.email = this.email; user.username = this.username; - if ((user.email === undefined || user.email === null) && (user.username === undefined || user.username === null)) { - throw new UsernameOrEmailNeededError(); - } if (this.password) { user.password = await argon2.hash(this.password + user.uuid); user.refreshTokenCount = user.refreshTokenCount + 1; diff --git a/src/models/entities/User.ts b/src/models/entities/User.ts index 94e091c..f82e899 100644 --- a/src/models/entities/User.ts +++ b/src/models/entities/User.ts @@ -25,9 +25,10 @@ export class User extends Principal { * The user's e-mail address. * Either username or email has to be set (otherwise the user couldn't log in). */ - @Column({ nullable: true, unique: true }) + @Column({ nullable: false, unique: true }) @IsEmail() - email?: string; + @IsNotEmpty() + email: string; /** * The user's phone number. diff --git a/src/seeds/SeedUsers.ts b/src/seeds/SeedUsers.ts index e70ef84..26fc233 100644 --- a/src/seeds/SeedUsers.ts +++ b/src/seeds/SeedUsers.ts @@ -33,6 +33,7 @@ export default class SeedUsers implements Seeder { initialUser.lastname = "demo"; initialUser.username = "demo"; initialUser.password = "demo"; + initialUser.email = "demo@dev.lauf-fuer-kaya.de" initialUser.groups = group; return await connection.getRepository(User).save(await initialUser.toEntity()); } diff --git a/src/tests/auth/auth_logout.spec.ts b/src/tests/auth/auth_logout.spec.ts index 7c846c1..2594f26 100644 --- a/src/tests/auth/auth_logout.spec.ts +++ b/src/tests/auth/auth_logout.spec.ts @@ -14,7 +14,8 @@ beforeAll(async () => { "middlename": "demo_logout", "lastname": "demo_logout", "username": "demo_logout", - "password": "demo_logout" + "password": "demo_logout", + "email": "demo_logout@dev.lauf-fuer-kaya.de" }, { headers: { "authorization": "Bearer " + res_login.data["access_token"] }, validateStatus: undefined diff --git a/src/tests/auth/auth_refresh.spec.ts b/src/tests/auth/auth_refresh.spec.ts index 02d2a02..bd875ba 100644 --- a/src/tests/auth/auth_refresh.spec.ts +++ b/src/tests/auth/auth_refresh.spec.ts @@ -14,7 +14,8 @@ beforeAll(async () => { "middlename": "demo_refresh", "lastname": "demo_refresh", "username": "demo_refresh", - "password": "demo_refresh" + "password": "demo_refresh", + "email": "demo_refresh@dev.lauf-fuer-kaya.de" }, { headers: { "authorization": "Bearer " + res_login.data["access_token"] }, validateStatus: undefined diff --git a/src/tests/auth/auth_reset.spec.ts b/src/tests/auth/auth_reset.spec.ts index 2ebb8ed..47c61e6 100644 --- a/src/tests/auth/auth_reset.spec.ts +++ b/src/tests/auth/auth_reset.spec.ts @@ -14,7 +14,8 @@ beforeAll(async () => { "middlename": "demo_reset", "lastname": "demo_reset", "username": "demo_reset", - "password": "demo_reset" + "password": "demo_reset", + "email": "demo_reset@dev.lauf-fuer-kaya.de" }, { headers: { "authorization": "Bearer " + res_login.data["access_token"] }, validateStatus: undefined @@ -24,7 +25,8 @@ beforeAll(async () => { "middlename": "demo_reset2", "lastname": "demo_reset2", "username": "demo_reset2", - "password": "demo_reset2" + "password": "demo_reset2", + "email": "demo_reset1@dev.lauf-fuer-kaya.de" }, { headers: { "authorization": "Bearer " + res_login.data["access_token"] }, validateStatus: undefined