Browse Source

Fix/update account

merge-requests/241/head
Oksana Stepanenko 2 years ago committed by Coder
parent
commit
621d95561f
  1. 5
      src/domain/old-database-seed/services/users.service.ts
  2. 3
      src/rest/admin/account/admin-account.module.ts
  3. 56
      src/rest/admin/account/controllers/admin-accounts.controller.ts
  4. 9
      src/rest/admin/account/dto/update-account.dto.ts
  5. 118
      src/rest/admin/account/services/admin-accounts.service.ts
  6. 3
      src/rest/admin/users/dtos/store-user-payload.dto.ts

5
src/domain/old-database-seed/services/users.service.ts

@ -12,7 +12,7 @@ import { @@ -12,7 +12,7 @@ import {
} from '../typing/consts'
import { OldDbRelationType } from '../typing/enums'
import { IOldUser } from '../typing/interfaces'
import * as randomstring from 'randomstring'
@Injectable()
export class OldDBUsersService {
private oldFilesFolder = 'old'
@ -68,6 +68,7 @@ export class OldDBUsersService { @@ -68,6 +68,7 @@ export class OldDBUsersService {
const nameArr = oldUser.name.trim().split(' ')
const newAvatarUrl = await this.getNewAvatarUrl(oldUser.avatar)
const password = randomstring.generate(6)
const userId = await this.usersService.save(
{
@ -75,7 +76,7 @@ export class OldDBUsersService { @@ -75,7 +76,7 @@ export class OldDBUsersService {
email: String(oldUser.email).trim(),
login: String(oldUser.login).trim(),
phoneNumber: oldUser.phone_login,
password: '123qqq',
password,
firstName: nameArr[1],
lastName: nameArr[0],
middleName: nameArr[2],

3
src/rest/admin/account/admin-account.module.ts

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import { DynamicModule, Module } from '@nestjs/common'
import { MailerModule, SessionsModule, SmsModule, UsersModule } from 'src/domain'
import { JwtModule } from 'src/libs'
import { FilesStorageModule, JwtModule } from 'src/libs'
import { AdminAccountsController } from './controllers'
import { AdminAccountsService } from './services'
@ -15,6 +15,7 @@ export class AdminAccountModule { @@ -15,6 +15,7 @@ export class AdminAccountModule {
SessionsModule.forFeature(),
MailerModule.forFeature(),
SmsModule.forFeature(),
FilesStorageModule.forFeature(),
],
providers: [AdminAccountsService],
controllers: [AdminAccountsController],

56
src/rest/admin/account/controllers/admin-accounts.controller.ts

@ -1,6 +1,19 @@ @@ -1,6 +1,19 @@
import { Body, Controller, Get, Patch, Req } from '@nestjs/common'
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Put,
Req,
UploadedFile,
UseInterceptors,
} from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { ApiBody, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'
import { plainToClass } from 'class-transformer'
import { AvatarUrlDto } from 'src/core/dto'
import { AuthGuard } from 'src/domain/sessions/decorators'
import { removeBearerFromToken, ReqUser } from 'src/shared'
import { GetAccountDto, UpdateAccountDto, UpdatePasswordDto } from '../dto'
@ -11,6 +24,8 @@ import { AdminAccountsService } from '../services' @@ -11,6 +24,8 @@ import { AdminAccountsService } from '../services'
export class AdminAccountsController {
constructor(private readonly accountsService: AdminAccountsService) {}
/*************************************************************************************** */
@ApiOperation({ summary: 'Отримання аккаунту' })
@ApiBody({ type: GetAccountDto })
@ApiOkResponse({
@ -28,12 +43,12 @@ export class AdminAccountsController { @@ -28,12 +43,12 @@ export class AdminAccountsController {
return plainToClass(GetAccountDto, user)
}
/*************************************************************************************** */
@ApiOperation({ summary: 'Оновлення даних аккаунту' })
@ApiBody({ type: UpdateAccountDto })
@ApiOkResponse({
status: 200,
description: 'Повертає аккаунт',
type: GetAccountDto,
description: 'Оновлює дані акаунта',
})
@AuthGuard()
@Patch()
@ -42,6 +57,39 @@ export class AdminAccountsController { @@ -42,6 +57,39 @@ export class AdminAccountsController {
return plainToClass(GetAccountDto, user)
}
/*************************************************************************************** */
@ApiOperation({ summary: 'Оновити аватарку в акаунта' })
@ApiOkResponse({
status: 200,
description: 'Повертає посилання на зображення',
type: String,
})
@AuthGuard()
@Put('avatar')
@UseInterceptors(FileInterceptor('avatar'))
public async updateAvatar(
@UploadedFile() avatar: Express.Multer.File,
@ReqUser() userId: number,
) {
const avatarUrl = await this.accountsService.updateAvatar(userId, avatar)
return plainToClass(AvatarUrlDto, { avatarUrl })
}
/*************************************************************************************** */
@ApiOperation({ summary: 'Видалити аватарку користувача' })
@ApiOkResponse({
status: 200,
})
@AuthGuard()
@Delete('/avatar')
public async removeAvatar(@ReqUser() userId: number) {
return await this.accountsService.removeAvatar(userId)
}
/*************************************************************************************** */
@ApiOperation({ summary: 'Оновлення даних аккаунту' })
@ApiOkResponse({
status: 200,

9
src/rest/admin/account/dto/update-account.dto.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { IsAlphanumeric, IsDateString, IsEmail, IsNumberString, IsString } from 'class-validator'
import { IsDateString, IsEmail, IsString } from 'class-validator'
import { DtoPropertyOptional, TransformPhoneNumber } from 'src/shared'
export class UpdateAccountDto {
@ -7,7 +7,7 @@ export class UpdateAccountDto { @@ -7,7 +7,7 @@ export class UpdateAccountDto {
email?: string
@DtoPropertyOptional()
@IsAlphanumeric()
@IsString()
login?: string
@DtoPropertyOptional()
@ -23,7 +23,7 @@ export class UpdateAccountDto { @@ -23,7 +23,7 @@ export class UpdateAccountDto {
personalPhoneNumber?: string
@DtoPropertyOptional()
@IsNumberString()
@IsString()
innerPhoneNumber?: string
@DtoPropertyOptional()
@ -45,4 +45,7 @@ export class UpdateAccountDto { @@ -45,4 +45,7 @@ export class UpdateAccountDto {
@DtoPropertyOptional()
@IsString()
lastName?: string
@DtoPropertyOptional({ enum: ['email', 'sms'] })
sendPasswordBy?: 'email' | 'sms'
}

118
src/rest/admin/account/services/admin-accounts.service.ts

@ -1,21 +1,30 @@ @@ -1,21 +1,30 @@
import { Inject, Injectable } from '@nestjs/common'
import { $config } from 'src/config'
import { Mailer, Sessions, Sms, Users } from 'src/core'
import { MAILER_SERVICE, SESSIONS_SERVICE, SMS_SERVICE, USERS_SERVICE } from 'src/core/consts'
import { FilesStorage, Mailer, Sessions, Sms, Users } from 'src/core'
import {
FILES_STORAGE_SERVICE,
MAILER_SERVICE,
SESSIONS_SERVICE,
SMS_SERVICE,
USERS_PHONE_NUMBERS_SERVICE,
USERS_SERVICE,
} from 'src/core/consts'
import {
getChangePasswordNotificationHTML,
getChangePasswordNotificationText,
} from 'src/shared/templates'
import { UpdateAccountDto, UpdatePasswordDto } from '../dto'
import * as _ from 'lodash'
@Injectable()
export class AdminAccountsService {
constructor(
@Inject(USERS_SERVICE) private readonly usersService: Users.IUsersService,
@Inject(SESSIONS_SERVICE) private readonly sessionsService: Sessions.ISessionsService,
@Inject(MAILER_SERVICE) private readonly mailerService: Mailer.IMailerService,
@Inject(SMS_SERVICE) private readonly smsService: Sms.ISmsService,
) {}
@Inject(USERS_SERVICE) private readonly usersService: Users.IUsersService
@Inject(SESSIONS_SERVICE) private readonly sessionsService: Sessions.ISessionsService
@Inject(MAILER_SERVICE) private readonly mailerService: Mailer.IMailerService
@Inject(SMS_SERVICE) private readonly smsService: Sms.ISmsService
@Inject(USERS_PHONE_NUMBERS_SERVICE)
private readonly phoneNumbersService: Users.IUsersPhoneNumbersService
@Inject(FILES_STORAGE_SERVICE)
private readonly filesStorageService: FilesStorage.IFilesStorageService
public async getOne(id: number, token: string) {
try {
@ -26,11 +35,66 @@ export class AdminAccountsService { @@ -26,11 +35,66 @@ export class AdminAccountsService {
}
public async update(id: number, dto: UpdateAccountDto) {
const user = await this.usersService.getOne(id)
await this.changePhoneNumber(user.phoneNumber, dto)
await this.changePass(id, dto, user)
await this.usersService.update({ id, ...dto })
}
private async changePhoneNumber(oldPhoneNumber: string, dto: UpdateAccountDto) {
if (!dto.phoneNumber) return
if (dto.password) await this.usersService.changeUserPassword(id, dto.password)
await this.phoneNumbersService.change({
phoneNumber: oldPhoneNumber,
newPhoneNumber: dto.phoneNumber,
})
delete dto.phoneNumber
}
private async changePass(id: number, dto: UpdateAccountDto, user: Users.UserModel) {
if (!dto.password) return
await this.usersService.changeUserPassword(id, dto.password)
return await this.usersService.getOne(id, ['info'])
await this.sendPasswordToUser(user, dto.password, dto.sendPasswordBy)
await this.sessionsService.closeAllUserSessions(user.id)
delete dto.password
}
private async sendPasswordToUser(
_user: Users.UserModel | number,
password: string,
sendBy: 'email' | 'sms',
) {
if (!sendBy) return
let user
if (_.isNumber(_user)) user = await this.usersService.getOne(_user)
else user = _user
const params = {
linkToWeb: $config.getLinkToWeb(),
phoneNumber: user.phoneNumber,
login: user.login,
password,
}
if (sendBy === 'email') {
await this.mailerService.send({
subject: 'Дані для входу в програму Task Me ;)',
to: user.email,
html: getChangePasswordNotificationHTML(params),
})
}
if (sendBy === 'sms') {
await this.smsService.send({
to: user.phoneNumber,
text: getChangePasswordNotificationText(params),
})
}
}
public async changePassword(id: number, dto: UpdatePasswordDto) {
@ -59,4 +123,36 @@ export class AdminAccountsService { @@ -59,4 +123,36 @@ export class AdminAccountsService {
})
}
}
public async updateAvatar(id: number, file: FilesStorage.IInputFile) {
try {
const user = await this.usersService.getOne(id, ['info'])
try {
if (user.info.avatarUrl) {
await this.filesStorageService.removeObject(user.info.avatarUrl)
}
} catch (e) {}
const avatarUrl = await this.filesStorageService.putObject(file)
await this.usersService.update({ id, avatarUrl })
return avatarUrl
} catch (e) {
console.log('Update avatar error ', e)
}
}
public async removeAvatar(id: number) {
const user = await this.usersService.getOne(id, ['info'])
try {
if (user.info.avatarUrl) {
await this.filesStorageService.removeObject(user.info.avatarUrl)
}
} catch (e) {}
await this.usersService.update({ id, avatarUrl: null })
}
}

3
src/rest/admin/users/dtos/store-user-payload.dto.ts

@ -12,8 +12,7 @@ export class StoreUserPayloadDto { @@ -12,8 +12,7 @@ export class StoreUserPayloadDto {
@IsEmail()
email: string
@DtoProperty()
@IsOptional()
@DtoPropertyOptional()
@IsString()
login?: string

Loading…
Cancel
Save