diff --git a/app/Controllers/Http/Api/v1/MeController.ts b/app/Controllers/Http/Api/v1/MeController.ts index 10ac882..ff8a8b3 100644 --- a/app/Controllers/Http/Api/v1/MeController.ts +++ b/app/Controllers/Http/Api/v1/MeController.ts @@ -1,12 +1,10 @@ -import { Exception } from '@adonisjs/core/build/standalone'; +import { Exception, inject, Ioc } from '@adonisjs/core/build/standalone'; import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; -import Hash from '@ioc:Adonis/Core/Hash'; -import Logger from '@ioc:Adonis/Core/Logger'; /** - * Models + * Services */ -import Contact from 'App/Models/Contact'; +import MeService from 'App/Services/MeService'; /** * Validators @@ -14,89 +12,60 @@ import Contact from 'App/Models/Contact'; import ChangePasswordValidator from 'App/Validators/Password/ChangePasswordValidator'; import UpdateContactsValidator from 'App/Validators/Contacts/UpdateContactsValidator'; -export default class MeController { - private readonly guard: 'api'; +import BaseController from '../../BaseController'; - private readonly Contact: typeof Contact; +@inject() +export default class MeController extends BaseController { + private meService: MeService; - constructor() { - this.Contact = Contact; + constructor(meService: MeService) { + super(); + this.meService = meService; } /** * Shows user info of the access token resource owner. * GET /me */ - public async show({ response, auth }: HttpContextContract) { - const user = await auth.use(this.guard).authenticate(); + public async show(ctx: HttpContextContract) { + const result = await this.meService.fetchUserContacts(ctx.auth); - await user.load('contacts'); - await user.load('roles'); + if (!result.success && result.error) { + throw new Exception(result.message, result.status, result.error.code); + } - return response.ok({ - message: 'Fetched data about me.', - data: user, - }); + return this.sendResponse(ctx, result.data, result.message, result.status); } /** * Change password of authenticated user * PATCH /me/password */ - public async changePassword({ request, response, auth }: HttpContextContract) { - await request.validate(ChangePasswordValidator); + public async changePassword(ctx: HttpContextContract) { + const payload = await ctx.request.validate(ChangePasswordValidator); + const result = await this.meService.changeUserPassword(payload.oldPassword, payload.newPassword, ctx.auth); - const user = await auth.use(this.guard).authenticate(); - const oldPassword: string = request.input('oldPassword'); - const newPassword: string = request.input('newPassword'); - - if (oldPassword === newPassword) { - throw new Exception('The new password is the same as the old one.', 400, 'E_PASSWORD_VALUES'); + if (!result.success && result.error) { + throw new Exception(result.message, result.status, result.error.code); } - /** - * Verify old password - */ - if (!(await Hash.verify(user.password, oldPassword))) { - throw new Exception('Invalid credentials.', 403, 'E_INVALID_CREDENTIALS'); - } - - /** - * Update user password - */ - user.password = newPassword; - await user.save(); - - Logger.info(`Password of user with id: "${user.id}" was updated.`); - - return response.ok({ - message: 'The password was successfully changed to the new value.', - }); + return this.sendResponse(ctx, result.data, result.message, result.status); } /** * Update contacts of authenticated user - * PATCH /me/contacts + * PUT /me/contacts */ - public async updateContacts({ request, response, auth }: HttpContextContract) { - const payload = await request.validate(UpdateContactsValidator); - const user = await auth.use(this.guard).authenticate(); - const contacts = await this.Contact.findByOrFail('user_id', user.id); + public async updateContacts(ctx: HttpContextContract) { + const payload = await ctx.request.validate(UpdateContactsValidator); + const result = await this.meService.updateUserContacts(payload, ctx.auth); - /** - * Update contacts - */ - if (payload.email) contacts.email = payload.email; - contacts.phone_number = payload.phone_number ?? null; - contacts.vk_id = payload.vk_id ?? null; - contacts.twitter_id = payload.twitter_id ?? null; - contacts.telegram_id = payload.telegram_id ?? null; + if (!result.success && result.error) { + throw new Exception(result.message, result.status, result.error.code); + } - await contacts.save(); - - return response.ok({ - message: `Contacts has been successfully updated.`, - data: contacts, - }); + return this.sendResponse(ctx, result.data, result.message, result.status); } } + +new Ioc().make(MeController); diff --git a/app/Datatypes/Enums/StatusCodeEnum.ts b/app/Datatypes/Enums/StatusCodeEnum.ts new file mode 100644 index 0000000..79db513 --- /dev/null +++ b/app/Datatypes/Enums/StatusCodeEnum.ts @@ -0,0 +1,12 @@ +enum StatusCodeEnum { + OK = 200, + CREATED = 201, + NO_CONTENT = 204, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + FORBIDDEN = 403, + NOT_FOUND = 404, + INTERNAL_SERVER = 500, +} + +export default StatusCodeEnum; diff --git a/app/Models/Contact.ts b/app/Models/Contact.ts index dc0da12..5cbf3f2 100644 --- a/app/Models/Contact.ts +++ b/app/Models/Contact.ts @@ -9,9 +9,6 @@ export default class Contact extends BaseModel { @column({ serializeAs: null }) public user_id: string; - @column() - public email: string; - @column() public phone_number: string | null; diff --git a/app/Models/User.ts b/app/Models/User.ts index 59d5298..63c8d85 100644 --- a/app/Models/User.ts +++ b/app/Models/User.ts @@ -30,6 +30,9 @@ export default class User extends BaseModel { @column({ serializeAs: null }) public login: string; + @column() + public email: string; + @column({ serializeAs: null }) public password: string; diff --git a/app/Repositories/ContactRepository.ts b/app/Repositories/ContactRepository.ts index f88cad3..7162360 100644 --- a/app/Repositories/ContactRepository.ts +++ b/app/Repositories/ContactRepository.ts @@ -1,7 +1,14 @@ +/** + * Models + */ import Contact from 'App/Models/Contact'; import User from 'App/Models/User'; -import CreateUserValidator from 'App/Validators/User/CreateUserValidator'; -import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator'; + +/** + * Validators + */ +import CreateContactsValidator from 'App/Validators/Contacts/CreateContactsValidator'; +import UpdateContactsValidator from 'App/Validators/Contacts/UpdateContactsValidator'; export default class ContactRepository { private Contact: typeof Contact; @@ -10,6 +17,17 @@ export default class ContactRepository { this.Contact = Contact; } + /** + * Get contacts by user id + * + * @param userId User id + * @returns User contacts or null + */ + public async getByUser(userId: string | number): Promise { + const contacts = await this.Contact.query().where('user_id', userId).first(); + return contacts; + } + /** * Create user contacts in database * @@ -17,10 +35,17 @@ export default class ContactRepository { * @param data Data contacts * @returns Created contacts */ - public async create(user: User, data: Pick) { + public async create(user: User, data: CreateContactsValidator['schema']['props']): Promise { const contacts = await this.Contact.create(data); + /** + * Associate user + */ await contacts.related('user').associate(user); + + /** + * Load updated contacts to user + */ await user.load('contacts'); await user.load('roles'); @@ -32,13 +57,16 @@ export default class ContactRepository { * * @param user User * @param data Data to update - * @returns + * @returns Updated contacts or null */ - public async update(user: User, data: Pick) { + public async update(user: User, data: UpdateContactsValidator['schema']['props']): Promise { const contacts = await this.Contact.query().where('user_id', user.id).first(); if (contacts) { - contacts.email = data.email; + contacts.phone_number = data.phone_number ?? null; + contacts.telegram_id = data.telegram_id ?? null; + contacts.twitter_id = data.twitter_id ?? null; + contacts.vk_id = data.vk_id ?? null; await contacts.save(); await user.load('contacts'); @@ -46,15 +74,6 @@ export default class ContactRepository { return contacts; } - /** - * Create new user contacts if contacts doesn't exist - */ - await user.related('contacts').create({ - email: data.email, - }); - - await user.load('contacts'); - - return user.contacts; + return null; } } diff --git a/app/Repositories/RoleRepository.ts b/app/Repositories/RoleRepository.ts index 495bdc2..3d6163c 100644 --- a/app/Repositories/RoleRepository.ts +++ b/app/Repositories/RoleRepository.ts @@ -1,3 +1,6 @@ +/** + * Models + */ import Role from 'App/Models/Role'; export default class RoleRepository { diff --git a/app/Repositories/UserRepository.ts b/app/Repositories/UserRepository.ts index 6e0e925..4d502e3 100644 --- a/app/Repositories/UserRepository.ts +++ b/app/Repositories/UserRepository.ts @@ -1,5 +1,15 @@ /* eslint-disable @typescript-eslint/naming-convention */ + +import Hash from '@ioc:Adonis/Core/Hash'; + +/** + * Models + */ import User from 'App/Models/User'; + +/** + * Validators + */ import CreateUserValidator from 'App/Validators/User/CreateUserValidator'; import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator'; @@ -16,7 +26,7 @@ export default class UserRepository { * @param id User id * @returns User or null */ - public async getById(id: string | number) { + public async getById(id: string | number): Promise { const data = await this.User.query().preload('contacts').preload('roles').where('id', id).first(); return data; } @@ -28,7 +38,7 @@ export default class UserRepository { * @param value Comparsion column * @returns User or null */ - public async getByColumn(column: string, value: string | number) { + public async getByColumn(column: string, value: string | number): Promise { const data = await this.User.query().preload('contacts').preload('roles').where(column, value).first(); return data; } @@ -39,7 +49,7 @@ export default class UserRepository { * @param role Role * @returns Array of users with role */ - public async getAllByRole(role: string) { + public async getAllByRole(role: string): Promise { const data = await this.User.query() .preload('contacts') .preload('roles') @@ -53,7 +63,7 @@ export default class UserRepository { * @param params Params to find * @returns Array of users */ - public async getAll(params?: any) { + public async getAll(params?: any): Promise { const { email, login, first_name, last_name, role }: any = params || {}; const query = this.User.query(); @@ -87,14 +97,8 @@ export default class UserRepository { * @param data Data for create user * @returns Created user */ - public async create(data: CreateUserValidator['schema']['props']) { - const createdUser = await this.User.create({ - first_name: data.first_name, - last_name: data.last_name, - login: data.login, - password: data.password, - }); - + public async create(data: CreateUserValidator['schema']['props']): Promise { + const createdUser = await this.User.create(data); return createdUser; } @@ -105,18 +109,11 @@ export default class UserRepository { * @param data Data to update * @returns User or null if user is not found */ - public async update(id: number | string, data: UpdateUserValidator['schema']['props']) { + public async update(id: number | string, data: UpdateUserValidator['schema']['props']): Promise { const user = await this.User.query().preload('contacts').preload('roles').where('id', id).first(); if (user) { - await user - .merge({ - first_name: data.first_name, - last_name: data.last_name, - login: data.login, - password: data.password, - }) - .save(); + await user.merge(data).save(); return user; } @@ -129,7 +126,7 @@ export default class UserRepository { * @param id User id * @returns Deleted user or null if user is not found */ - public async delete(id: number | string) { + public async delete(id: number | string): Promise { const user = await this.User.query().preload('contacts').preload('roles').where('id', id).first(); if (user) { @@ -139,4 +136,9 @@ export default class UserRepository { return null; } + + public async updatePassword(password: string, id: string | number): Promise { + const hashedPass = await Hash.make(password); + return this.User.query().where('id', id).update({ password: hashedPass }).first(); + } } diff --git a/app/Services/AuthService.ts b/app/Services/AuthService.ts index 5099df6..19d505b 100644 --- a/app/Services/AuthService.ts +++ b/app/Services/AuthService.ts @@ -8,6 +8,11 @@ import Logger from '@ioc:Adonis/Core/Logger'; import { AuthContract } from '@ioc:Adonis/Addons/Auth'; import IResponse from 'App/Datatypes/Interfaces/IResponse'; +/** + * Enums + */ +import StatusCodeEnum from 'App/Datatypes/Enums/StatusCodeEnum'; + /** * Reposirories */ @@ -17,7 +22,7 @@ import UserRepository from 'App/Repositories/UserRepository'; export default class AuthService { private userRepository: UserRepository; - private guard: 'api'; + private authGuard: 'api'; constructor(userRepository: UserRepository) { this.userRepository = userRepository; @@ -37,11 +42,11 @@ export default class AuthService { if (!user) { return { success: false, - status: 404, + status: StatusCodeEnum.NOT_FOUND, message: 'User not found.', data: {}, error: { - code: 'E_USER_NOT_FOUND', + code: 'E_NOT_FOUND', }, }; } @@ -52,7 +57,7 @@ export default class AuthService { if (!(await Hash.verify(user.password, password))) { return { success: false, - status: 403, + status: StatusCodeEnum.UNAUTHORIZED, message: 'Invalid credentials.', data: {}, error: { @@ -64,7 +69,7 @@ export default class AuthService { /** * Create new token */ - const token = await auth.use(this.guard).generate(user, { + const token = await auth.use(this.authGuard).generate(user, { expiresIn: '1d', userRoles: user.roles.map(role => role.slug), }); @@ -73,7 +78,7 @@ export default class AuthService { return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'Login success.', data: token.toJSON(), }; @@ -86,11 +91,11 @@ export default class AuthService { * @returns Logout message */ public async logout(auth: AuthContract): Promise { - await auth.use(this.guard).revoke(); + await auth.use(this.authGuard).revoke(); return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'Logout success.', data: {}, }; diff --git a/app/Services/MeService.ts b/app/Services/MeService.ts new file mode 100644 index 0000000..42ed7d6 --- /dev/null +++ b/app/Services/MeService.ts @@ -0,0 +1,134 @@ +import { inject, Ioc } from '@adonisjs/core/build/standalone'; +import { AuthContract } from '@ioc:Adonis/Addons/Auth'; +import Hash from '@ioc:Adonis/Core/Hash'; +import Logger from '@ioc:Adonis/Core/Logger'; +import StatusCodeEnum from 'App/Datatypes/Enums/StatusCodeEnum'; +import IResponse from 'App/Datatypes/Interfaces/IResponse'; +import ContactRepository from 'App/Repositories/ContactRepository'; +import UserRepository from 'App/Repositories/UserRepository'; +import UpdateContactsValidator from 'App/Validators/Contacts/UpdateContactsValidator'; + +@inject() +export default class MeService { + private userRepository: UserRepository; + + private contactRepository: ContactRepository; + + private authGuard: 'api'; + + constructor(userRepository: UserRepository, contactRepository: ContactRepository) { + this.userRepository = userRepository; + this.contactRepository = contactRepository; + } + + /** + * Get authorized user data + * + * @param auth AuthContract + * @returns Response + */ + public async fetchUserContacts(auth: AuthContract): Promise { + const user = await auth.use(this.authGuard).authenticate(); + + await user.load('roles'); + await user.load('contacts'); + + return { + success: true, + status: StatusCodeEnum.OK, + message: 'Fetched authorized user data.', + data: user, + }; + } + + /** + * Change password of authorized user + * + * @param oldPassword Old password + * @param newPassword New password + * @param auth AuthContract + * @returns Response + */ + public async changeUserPassword(oldPassword: string, newPassword: string, auth: AuthContract): Promise { + const user = await auth.use(this.authGuard).authenticate(); + + /** + * Verify old password + */ + if (!(await Hash.verify(user.password, oldPassword))) { + return { + success: false, + status: StatusCodeEnum.UNAUTHORIZED, + message: 'Invalid credentials.', + data: {}, + error: { + code: 'E_INVALID_CREDENTIALS', + }, + }; + } + + /** + * Update password + */ + const passwordUpdated = await this.userRepository.updatePassword(newPassword, user.id); + + if (passwordUpdated) { + Logger.info(`Password of user with id: "${user.id}" was updated.`); + + return { + success: true, + status: StatusCodeEnum.OK, + message: 'Password updated.', + data: {}, + }; + } + + return { + success: false, + status: StatusCodeEnum.BAD_REQUEST, + message: 'Unable to change password', + data: {}, + error: { + code: 'E_BAD_REQUEST', + }, + }; + } + + /** + * Update user conctact + * + * @param data Data to update + * @param auth AuthContract + * @returns Updated user contacts + */ + public async updateUserContacts( + data: UpdateContactsValidator['schema']['props'], + auth: AuthContract + ): Promise { + const user = await auth.use(this.authGuard).authenticate(); + const contacts = await this.contactRepository.update(user, data); + + if (contacts) { + return { + success: true, + status: StatusCodeEnum.OK, + message: 'User contacts updated.', + data: contacts, + }; + } + + /** + * Create user contacts if they don't exist + */ + await this.contactRepository.create(user, data); + + return { + success: true, + status: StatusCodeEnum.OK, + message: 'User contacts updated.', + data: user.contacts, + }; + } +} + +new Ioc().make(MeService); diff --git a/app/Services/UserService.ts b/app/Services/UserService.ts index f83d4f0..0c651bd 100644 --- a/app/Services/UserService.ts +++ b/app/Services/UserService.ts @@ -5,6 +5,11 @@ import { inject, Ioc } from '@adonisjs/core/build/standalone'; */ import IResponse from 'App/Datatypes/Interfaces/IResponse'; +/** + * Enums + */ +import StatusCodeEnum from 'App/Datatypes/Enums/StatusCodeEnum'; + /** * Models */ @@ -13,7 +18,6 @@ import Role from 'App/Models/Role'; /** * Repositories */ -import ContactRepository from 'App/Repositories/ContactRepository'; import RoleRepository from 'App/Repositories/RoleRepository'; import UserRepository from 'App/Repositories/UserRepository'; @@ -27,13 +31,10 @@ import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator'; export default class UserService { private userRepository: UserRepository; - private contactRepository: ContactRepository; - private roleRepository: RoleRepository; - constructor(userRepository: UserRepository, contactRepository: ContactRepository, roleRepository: RoleRepository) { + constructor(userRepository: UserRepository, roleRepository: RoleRepository) { this.userRepository = userRepository; - this.contactRepository = contactRepository; this.roleRepository = roleRepository; } @@ -49,18 +50,18 @@ export default class UserService { if (!user) { return { success: false, - status: 404, + status: StatusCodeEnum.NOT_FOUND, message: 'User not found.', data: {}, error: { - code: 'E_USER_NOT_FOUND', + code: 'E_NOT_FOUND', }, }; } return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'Fetched user.', data: user, }; @@ -77,7 +78,7 @@ export default class UserService { return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'Fetched all users.', data: users, }; @@ -92,12 +93,9 @@ export default class UserService { public async createUser(data: CreateUserValidator['schema']['props']): Promise { const user = await this.userRepository.create(data); - /* Associate user contacts */ - await this.contactRepository.create(user, { email: data.email }); - return { success: true, - status: 201, + status: StatusCodeEnum.CREATED, message: 'User created.', data: user, }; @@ -116,23 +114,18 @@ export default class UserService { if (!user) { return { success: false, - status: 404, + status: StatusCodeEnum.NOT_FOUND, message: 'User not found.', data: {}, error: { - code: 'E_USER_NOT_FOUND', + code: 'E_NOT_FOUND', }, }; } - /** - * Update user contacts - */ - await this.contactRepository.update(user, data); - return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'User updated.', data: user, }; @@ -150,18 +143,18 @@ export default class UserService { if (!user) { return { success: false, - status: 404, + status: StatusCodeEnum.NOT_FOUND, message: 'User not found.', data: {}, error: { - code: 'E_USER_NOT_FOUND', + code: 'E_NOT_FOUND', }, }; } return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'User deleted.', data: user, }; @@ -180,11 +173,11 @@ export default class UserService { if (!user) { return { success: false, - status: 404, + status: StatusCodeEnum.NOT_FOUND, message: 'User not found.', data: {}, error: { - code: 'E_USER_NOT_FOUND', + code: 'E_NOT_FOUND', }, }; } @@ -208,11 +201,11 @@ export default class UserService { if (attachedRole) { return { success: false, - status: 404, + status: StatusCodeEnum.BAD_REQUEST, message: `Role "${attachedRole.name}" already attached to that user.`, data: {}, error: { - code: 'E_ROLE_ATTACHED', + code: 'E_BAD_REQUEST', }, }; } @@ -222,7 +215,7 @@ export default class UserService { return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'Roles attached.', data: user.roles, }; @@ -241,11 +234,11 @@ export default class UserService { if (!user) { return { success: false, - status: 404, + status: StatusCodeEnum.NOT_FOUND, message: 'User not found.', data: {}, error: { - code: 'E_USER_NOT_FOUND', + code: 'E_NOT_FOUND', }, }; } @@ -266,11 +259,11 @@ export default class UserService { if (notAttachedRole) { return { success: false, - status: 404, + status: StatusCodeEnum.BAD_REQUEST, message: `Role "${notAttachedRole.name}" not attached to that user.`, data: {}, error: { - code: 'E_ROLE_NOT_ATTACHED', + code: 'E_BAD_REQUEST', }, }; } @@ -280,7 +273,7 @@ export default class UserService { return { success: true, - status: 200, + status: StatusCodeEnum.OK, message: 'Roles detached.', data: user.roles, }; diff --git a/app/Validators/Contacts/CreateContactsValidator.ts b/app/Validators/Contacts/CreateContactsValidator.ts new file mode 100644 index 0000000..999a5bb --- /dev/null +++ b/app/Validators/Contacts/CreateContactsValidator.ts @@ -0,0 +1,20 @@ +import { schema, rules } from '@ioc:Adonis/Core/Validator'; +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; + +export default class CreateContactsValidator { + constructor(protected ctx: HttpContextContract) {} + + public schema = schema.create({ + phone_number: schema.string.optional({}, [ + rules.mobile({ + locales: ['ru-RU', 'en-US'], + strict: true, + }), + ]), + vk_id: schema.string.optional({}, [rules.regex(/^[a-zA-Z0-9_]+$/)]), + twitter_id: schema.string.optional({}, [rules.regex(/^[a-zA-Z0-9_]+$/)]), + telegram_id: schema.string.optional({}, [rules.regex(/^[a-zA-Z0-9_]+$/)]), + }); + + public messages = {}; +} diff --git a/app/Validators/Contacts/UpdateContactsValidator.ts b/app/Validators/Contacts/UpdateContactsValidator.ts index d565e38..8f600c0 100644 --- a/app/Validators/Contacts/UpdateContactsValidator.ts +++ b/app/Validators/Contacts/UpdateContactsValidator.ts @@ -5,7 +5,6 @@ export default class UpdateContactsValidator { constructor(protected ctx: HttpContextContract) {} public schema = schema.create({ - email: schema.string.optional({}, [rules.email()]), phone_number: schema.string.optional({}, [ rules.mobile({ locales: ['ru-RU', 'en-US'], diff --git a/app/Validators/User/CreateUserValidator.ts b/app/Validators/User/CreateUserValidator.ts index e126d67..2c2ed56 100644 --- a/app/Validators/User/CreateUserValidator.ts +++ b/app/Validators/User/CreateUserValidator.ts @@ -27,7 +27,7 @@ export default class CreateUserValidator { first_name: schema.string(), last_name: schema.string(), login: schema.string({}, [rules.maxLength(128), rules.unique({ table: 'users', column: 'login' })]), - email: schema.string({}, [rules.email(), rules.unique({ table: 'contacts', column: 'email' })]), + email: schema.string({}, [rules.email(), rules.unique({ table: 'users', column: 'email' })]), password: schema.string({}, [rules.minLength(6), rules.maxLength(128)]), }); diff --git a/app/Validators/User/UpdateUserValidator.ts b/app/Validators/User/UpdateUserValidator.ts index e481753..efaed0f 100644 --- a/app/Validators/User/UpdateUserValidator.ts +++ b/app/Validators/User/UpdateUserValidator.ts @@ -8,7 +8,7 @@ export default class UpdateUserValidator { first_name: schema.string(), last_name: schema.string(), login: schema.string({}, [rules.unique({ table: 'users', column: 'login' })]), - email: schema.string({}, [rules.email(), rules.unique({ table: 'contacts', column: 'email' })]), + email: schema.string({}, [rules.email(), rules.unique({ table: 'users', column: 'email' })]), password: schema.string(), }); diff --git a/database/factories/index.ts b/database/factories/index.ts index 8d13370..7c443fc 100644 --- a/database/factories/index.ts +++ b/database/factories/index.ts @@ -7,7 +7,7 @@ import User from 'App/Models/User'; export const ContactFactory = Factory.define(Contact, ({ faker }) => { return { - email: faker.internet.exampleEmail(), + phone_number: faker.phone.phoneNumber(), }; }).build(); @@ -16,6 +16,7 @@ export const UserFactory = Factory.define(User, ({ faker }) => { first_name: faker.name.firstName(), last_name: faker.name.lastName(), login: `${faker.lorem.word(6)}${faker.datatype.number(10)}`, + email: faker.internet.exampleEmail(), password: '12345', }; }) diff --git a/database/migrations/1626545059989_users.ts b/database/migrations/1626545059989_users.ts index cee8469..bda7219 100644 --- a/database/migrations/1626545059989_users.ts +++ b/database/migrations/1626545059989_users.ts @@ -9,6 +9,7 @@ export default class Users extends BaseSchema { table.string('first_name', 24).notNullable(); table.string('last_name', 24).notNullable(); table.string('login', 128).notNullable().unique(); + table.string('email').notNullable().unique(); table.string('password').notNullable(); table.timestamp('created_at', { useTz: true }); table.timestamp('updated_at', { useTz: true }); diff --git a/database/migrations/1627022639849_contacts.ts b/database/migrations/1627022639849_contacts.ts index 8494fad..6f4fa41 100644 --- a/database/migrations/1627022639849_contacts.ts +++ b/database/migrations/1627022639849_contacts.ts @@ -7,7 +7,6 @@ export default class Contacts extends BaseSchema { this.schema.createTable(this.tableName, table => { table.increments('id'); table.string('user_id', 21).unsigned().references('users.id').unique().onDelete('CASCADE'); - table.string('email').unique().notNullable(); table.string('phone_number').unique(); table.string('vk_id').unique(); table.string('twitter_id').unique();