forked from hexlet-rus/runit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[hexlet-rus#537] Implement admin section
- Loading branch information
1 parent
85e73d4
commit ba1e494
Showing
13 changed files
with
368 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,75 @@ | ||
/* eslint-disable no-useless-constructor */ | ||
|
||
import { Injectable } from '@nestjs/common'; | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
import { Repository } from 'typeorm'; | ||
import { User } from '../entities/user.entity'; | ||
import { UsersService } from '../users/users.service'; | ||
import { Snippet } from '../entities/snippet.entity'; | ||
import { UserSettings } from '../entities/user-settings.entity'; | ||
|
||
@Injectable() | ||
export class AdminsService { | ||
constructor(private readonly usersService: UsersService) {} | ||
constructor( | ||
@InjectRepository(User) | ||
private usersRepository: Repository<User>, | ||
@InjectRepository(Snippet) | ||
private snippetsRepository: Repository<Snippet>, | ||
@InjectRepository(UserSettings) | ||
private userSettingsRepository: Repository<UserSettings>, | ||
) {} | ||
|
||
findAllUsers(page: number, take: number): Promise<User[]> { | ||
return this.usersService.findAllUsers(page, take); | ||
async findAllUsers(page: number, take: number): Promise<User[]> { | ||
return this.usersRepository.find({ | ||
skip: (page - 1) * take, | ||
take, | ||
}); | ||
} | ||
|
||
async deleteUser(id: number): Promise<void> { | ||
await this.snippetsRepository.delete({ userId: id }); | ||
await this.userSettingsRepository.delete({ userId: id }); | ||
await this.usersRepository.delete({ id }); | ||
} | ||
|
||
async findOneUser(id: number): Promise<User> { | ||
return this.usersRepository.findOneBy({ id }); | ||
} | ||
|
||
async updateUser(id: number, dto: any): Promise<User> { | ||
const user = await this.findOneUser(id); | ||
|
||
user.username = dto.username; | ||
user.email = dto.email; | ||
user.isAdmin = dto.isAdmin === 'on'; | ||
await this.usersRepository.save(user); | ||
return user; | ||
} | ||
|
||
async create(createUserDto: any): Promise<User> { | ||
const user = new User(); | ||
user.username = createUserDto.username; | ||
user.email = createUserDto.email.toLowerCase(); | ||
user.password = createUserDto.password; | ||
user.isAdmin = createUserDto.isAdmin === 'on'; | ||
const newUser = await this.usersRepository.save(user); | ||
const userSettings = await this.userSettingsRepository.create({ | ||
userId: newUser.id, | ||
theme: 'system', | ||
language: 'ru', | ||
avatar_base64: null, | ||
}); | ||
await this.userSettingsRepository.save(userSettings); | ||
return newUser; | ||
} | ||
|
||
async findAllSnippets(page: number, take: number): Promise<Snippet[]> { | ||
return this.snippetsRepository.find({ | ||
skip: (page - 1) * take, | ||
take, | ||
}); | ||
} | ||
|
||
async deleteSnippet(id: number): Promise<void> { | ||
await this.snippetsRepository.delete(id); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { | ||
IsEmail, | ||
// IsNotEmpty, | ||
IsOptional, | ||
IsString, | ||
Length, | ||
Matches, | ||
// Validate, | ||
} from 'class-validator'; | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
// import { CheckUsername } from '../../users/validation/check-username'; | ||
// import { CheckEmail } from '../../users/validation/check-email'; | ||
|
||
export class UpdateUserDto { | ||
@ApiProperty({ | ||
minLength: 3, | ||
maxLength: 20, | ||
description: 'Must be unique!', | ||
example: 'UpdatedJohnDoe', | ||
pattern: '/[A-Za-z]/', | ||
required: false, | ||
}) | ||
@IsOptional() | ||
@Length(3, 20) | ||
@IsString() | ||
@Matches(/^[\w\S]*$/) | ||
// @Validate(CheckUsername, { | ||
// message: 'usernameIsUsed', | ||
// }) | ||
username?: string; | ||
|
||
@ApiProperty({ | ||
description: 'Must be unique!', | ||
example: '[email protected]', | ||
required: false, | ||
}) | ||
@IsOptional() | ||
@IsString() | ||
@IsEmail() | ||
// @Validate(CheckEmail, { | ||
// message: 'emailIsUsed', | ||
// }) | ||
email?: string; | ||
|
||
@ApiProperty({ | ||
description: 'Administrator privileges', | ||
example: 'on | off', | ||
}) | ||
@IsOptional() | ||
@IsString() | ||
isAdmin?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
doctype html | ||
html | ||
head | ||
meta(charset='utf-8') | ||
meta(name='viewport' content='width=device-width, initial-scale=1') | ||
title Create User | ||
link(href=' https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css' rel='stylesheet') | ||
body | ||
nav.navbar.navbar-expand-lg | ||
.container-fluid | ||
.collapse.navbar-collapse#navbarSupportedContent | ||
ul.navbar-nav.me-auto.mb-2.mb-lg-0 | ||
li.nav-item | ||
a.nav-link(href='/api/admin/users') Назад | ||
.container-fluid | ||
h1.text-center.font-weight-bold.pb-3 | ||
| Создание пользователя | ||
.d-flex.align-items-center.justify-content-center | ||
form(action='/api/admin/users/create', method="post") | ||
div.mb-3 | ||
label.form-label(for="username") Имя | ||
input.form-control(id="username" name="username" type="text") | ||
div.mb-3 | ||
label.form-label(for="email") Емейл | ||
input.form-control(id="email" name="email" type="email") | ||
div.mb-3 | ||
label.form-label(for="password") Пароль | ||
input.form-control(id="password" name="password" type="text") | ||
div.mb-3 | ||
label.form-label(for="status") Роль | ||
select.form-select(id="status" name="isAdmin") | ||
option(value="off" selected) Пользователь | ||
option(value="on") Администратор | ||
button.btn.btn-primary(type="submit") Создать |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
doctype html | ||
html | ||
head | ||
meta(charset='utf-8') | ||
meta(name='viewport' content='width=device-width, initial-scale=1') | ||
title Edit User | ||
link(href=' https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css' rel='stylesheet') | ||
body | ||
nav.navbar.navbar-expand-lg | ||
.container-fluid | ||
.collapse.navbar-collapse#navbarSupportedContent | ||
ul.navbar-nav.me-auto.mb-2.mb-lg-0 | ||
li.nav-item | ||
a.nav-link(href='/api/admin/users') Назад | ||
.container-fluid | ||
h1.text-center.font-weight-bold.pb-3 | ||
| Редактирование профиля | ||
.d-flex.align-items-center.justify-content-center | ||
form(action=`/api/admin/users/edit/${user.id}`, method="post") | ||
div.mb-3 | ||
label.form-label(for="username") Имя | ||
input.form-control(id="username" name="username" type="text" value=user.username) | ||
div.mb-3 | ||
label.form-label(for="email") Емейл | ||
input.form-control(id="email" name="email" type="email" value=user.email) | ||
div.mb-3 | ||
label.form-label(for="status") Роль | ||
select.form-select(id="status" name="isAdmin") | ||
option(value="off" selected=user.isAdmin) Пользователь | ||
option(value="on" selected=user.isAdmin) Администратор | ||
button.btn.btn-primary(type="submit") Сохранить |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
doctype html | ||
html | ||
head | ||
meta(charset='utf-8') | ||
meta(name='viewport' content='width=device-width, initial-scale=1') | ||
title Snippets List | ||
link(href=' https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css' rel='stylesheet') | ||
body | ||
//- script(src='https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js') | ||
nav.navbar.navbar-expand-lg | ||
.container-fluid | ||
.collapse.navbar-collapse#navbarSupportedContent | ||
ul.navbar-nav.me-auto.mb-2.mb-lg-0 | ||
li.nav-item | ||
a.nav-link(href='http://localhost:3000/') На главную | ||
li.nav-item | ||
if activeTemplate === 'snippets' | ||
a.nav-link(href='/api/admin/users') Пользователи | ||
if activeTemplate === 'users' | ||
a.nav-link(href='/api/admin/snippets') Сниппеты | ||
//- a.btn.btn-primary(href='users/create' role='button') + | ||
.container | ||
.d-flex.align-items-center.justify-content-center | ||
h1.text-center.font-weight-bold.pb-3 | ||
| Сниппеты | ||
table.table | ||
thead | ||
tr | ||
th ID | ||
th Имя | ||
th Язык | ||
//- th Админ | ||
th Действие | ||
tbody | ||
each snippet in snippets | ||
tr.align-middle | ||
td= snippet.id | ||
td= snippet.name | ||
td= snippet.language | ||
//- td= user.isAdmin ? 'Да' : 'Нет' | ||
td | ||
//- div | ||
//- a.link-dark.link-offset-2.link-underline-opacity-25.link-underline-opacity-100-hover(href=`users/edit/${user.id}`) Редактировать | ||
div | ||
a.link-dark.link-offset-2.link-underline-opacity-25.link-underline-opacity-100-hover(href=`snippets/delete/${snippet.id}`) Удалить | ||
.container | ||
.d-flex.align-items-center.justify-content-center.gap-3 | ||
if currentPage > 1 | ||
a(href=`snippets?page=${currentPage - 1}`) Предыдущая | ||
span Страница № #{currentPage} | ||
if snippets.length >= 10 | ||
a(href=`snippets?page=${currentPage + 1}`) Следующая |
Oops, something went wrong.