Create user

This commit is contained in:
Hugo Falcao
2022-04-17 20:32:51 -03:00
commit 60dc95bac8
80 changed files with 10187 additions and 0 deletions

13
.editorconfig Normal file
View File

@@ -0,0 +1,13 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf

3
.eslintignore Normal file
View File

@@ -0,0 +1,3 @@
/*.js
node_modules
dist

45
.eslintrc.json Normal file
View File

@@ -0,0 +1,45 @@
{
"env": {
"es6": true,
"node": true
},
"extends": [
"airbnb-base",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint",
"prettier"
],
"rules": {
"prettier/prettier": "error",
"class-methods-use-this": "off",
"camelcase": "off",
"@typescript-eslint/no-unused-vars": ["error", {
"argsIgnorePattern": "_"
}],
"import/extensions": [
"error",
"ignorePackages",
{
"ts": "never"
}
]
},
"settings": {
"import/resolver": {
"typescript": {}
}
}
}

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules

6
README.md Normal file
View File

@@ -0,0 +1,6 @@
# Getting Started
`npm install`
`npm run typeorm migration:run`
`yarn dev:server`

17
ormconfig.json Normal file
View File

@@ -0,0 +1,17 @@
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "Cara@2012",
"database": "postgres",
"entities": [
"./src/models/*.ts"
],
"migrations": [
"./src/database/migrations/*.ts"
],
"cli": {
"migrationsDir": "./src/database/migrations"
}
}

3401
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
package.json Normal file
View File

@@ -0,0 +1,28 @@
{
"name": "backend",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/cors": "^2.8.10",
"@types/express": "^4.17.11",
"@types/jsonwebtoken": "^8.5.1",
"@types/uuid": "^8.3.0",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-async-errors": "^3.1.1",
"jsonwebtoken": "^8.5.1",
"pg": "^8.5.1",
"reflect-metadata": "^0.1.13",
"ts-node-dev": "^1.1.2",
"typeorm": "^0.2.32",
"typescript": "^4.2.2",
"uuid": "^8.3.2"
},
"scripts": {
"dev:server": "ts-node-dev --inspect --transpile-only --ignore-watch node_modules src/server.ts",
"typeorm": "ts-node-dev ./node_modules/typeorm/cli.js"
}
}

5
prettier.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
singleQuote: true,
trailingComma: 'all',
arrowParens: 'avoid',
}

8
src/@types/express.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
declare namespace Express {
export interface Request {
admin_token: string;
user: {
id_user: string;
};
}
}

3
src/config/admin.ts Normal file
View File

@@ -0,0 +1,3 @@
export default {
key: 'b0df76b7fdf1823196f935f0417c0ad3'
};

7
src/config/auth.ts Normal file
View File

@@ -0,0 +1,7 @@
export default {
jwt: {
secret:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MDk3MTgxMTUsImV4cCI6MTYwOTgwNDUxNSwic3ViIjoiZjI3MTRhMGYtOGYzYy00YmQ4LWFiMTgtYTM4MmEyYTdmNGRjIn0.lYfjIklXqnHUHTnkF_G-Ms4NlmqWdLhI0fPP_mfoHcw',
expiresIn: '1d',
},
};

View File

@@ -0,0 +1,61 @@
import { MigrationInterface, QueryRunner, Table } from "typeorm";
export class CreateUsers1617210132141 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: 'users',
columns: [
{
name: 'id_user',
type: 'uuid',
isPrimary: true,
generationStrategy: 'uuid',
default: 'uuid_generate_v4()',
},
{
name: 'name',
type: 'varchar',
},
{
name: 'email',
type: 'varchar',
},
{
name: 'birth_date',
type: 'date',
},
{
name: 'password',
type: 'varchar',
},
{
name: 'avatar_image',
type: 'varchar',
isNullable: true
},
{
name: 'bio',
type: 'varchar',
isNullable: true
},
{
name: 'created_at',
type: 'timestamp',
default: 'now()',
},
{
name: 'updated_at',
type: 'timestamp',
default: 'now()',
},
],
}),
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable('users');
}
}

12
src/errors/AppError.ts Normal file
View File

@@ -0,0 +1,12 @@
class AppError {
public readonly message: string;
public readonly statusCode: number;
constructor(message: string, statusCode = 400) {
this.message = message;
this.statusCode = statusCode;
}
}
export default AppError;

View File

@@ -0,0 +1,27 @@
import { Request, Response, NextFunction } from 'express';
import { verify } from 'jsonwebtoken';
import admin from '../config/admin';
import authConfig from '../config/auth';
import AppError from '../errors/AppError';
interface TokenPayload {
iat: number;
exp: number;
sub: string;
}
export default function ensureAdmin(
request: Request,
response: Response,
next: NextFunction,
): void {
const adminToken = request.admin_token;
if (admin.key != adminToken) {
throw new AppError('You don\'t have permission to perform this action.', 401);
}
next();
}

View File

@@ -0,0 +1,49 @@
import { Request, Response, NextFunction } from 'express';
import { verify } from 'jsonwebtoken';
import authConfig from '../config/auth';
import AppError from '../errors/AppError';
interface TokenPayload {
iat: number;
exp: number;
sub: string;
}
export default function ensureAuthenticated(
request: Request,
response: Response,
next: NextFunction,
): void {
// validação do token JWT
// pegando o valor do header
const authHeader = request.headers.authorization;
if (!authHeader) {
throw new AppError('JWT token is missing.', 401);
}
// formato do valor do header: "Bearer insert_token_here"
const [, token] = authHeader.split(' ');
try {
const decoded = verify(token, authConfig.jwt.secret);
const { sub } = decoded as TokenPayload;
// sub -> id_user
// ou seja, o JWT informa o uuid do usuário sozinho
// isso ajuda a economizar linhas
// TODO, mas é a melhor prática de segurança?
request.user = {
id_user: sub,
};
return next();
} catch {
throw new AppError('Invalid JWT token', 401);
}
}

34
src/models/Follow.ts Normal file
View File

@@ -0,0 +1,34 @@
import {
Entity,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
OneToOne,
JoinColumn,
ManyToOne,
ManyToMany,
} from 'typeorm';
import User from './User';
@Entity('follows')
class Follow {
@PrimaryGeneratedColumn('increment')
id_follow: string;
@ManyToOne(() => User, { eager: true })
@JoinColumn({ name: 'user_id_following' })
user_following: User;
@ManyToOne(() => User, { eager: true })
@JoinColumn({ name: 'user_id_followed' })
user_followed: User;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
export default Follow;

36
src/models/Inventario.ts Normal file
View File

@@ -0,0 +1,36 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
OneToOne,
JoinColumn,
} from 'typeorm';
import User from './User';
import Item from './Item';
@Entity('inventario')
class Inventario {
@PrimaryGeneratedColumn('increment')
id_inventario: string;
@OneToOne(() => Item, { eager: true })
@JoinColumn({ name: 'item_id' })
item: Item;
@OneToOne(() => User, { eager: true })
@JoinColumn({ name: 'user_id' })
user: User;
@Column()
ativo: boolean;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
export default Inventario;

33
src/models/Item.ts Normal file
View File

@@ -0,0 +1,33 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity('items')
class Item {
@PrimaryGeneratedColumn('increment')
id_item: number;
@Column()
nome: string;
@Column()
tipo: string;
@Column()
asset: string;
@Column()
preco: number;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
export default Item;

27
src/models/Publication.ts Normal file
View File

@@ -0,0 +1,27 @@
import {
Entity,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
OneToOne,
JoinColumn,
} from 'typeorm';
import Tournament from './Tournament';
@Entity('publications')
class Publication {
@PrimaryGeneratedColumn('uuid')
id_publication: string;
@OneToOne(() => Tournament, { eager: true })
@JoinColumn({ name: 'tournament_id' })
tournament: Tournament;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
export default Publication;

42
src/models/Social.ts Normal file
View File

@@ -0,0 +1,42 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
JoinColumn,
PrimaryColumn,
OneToOne,
} from 'typeorm';
import User from './User';
@Entity('socials')
class Social {
@PrimaryGeneratedColumn('increment')
id_social: string;
@OneToOne(() => User)
@JoinColumn({ name: 'user_id' })
user: User;
@Column()
telegram: string;
@Column()
facebook: string;
@Column()
twitter: string;
@Column()
twitch: string;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
export default Social;

46
src/models/Tournament.ts Normal file
View File

@@ -0,0 +1,46 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
JoinColumn,
OneToOne,
} from 'typeorm';
import User from './User';
@Entity('tournaments')
class Tournament {
@PrimaryGeneratedColumn('uuid')
id_tournament: string;
@Column()
name: string;
@Column()
game: string;
@Column()
description: string;
@Column()
password: string;
@CreateDateColumn()
ended_at: Date;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
@OneToOne(() => User, { eager: true })
@JoinColumn({ name: 'user_id' })
user: User;
@Column()
number_participants: number;
}
export default Tournament;

View File

@@ -0,0 +1,47 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
JoinColumn,
OneToOne,
} from 'typeorm';
import Tournament from './Tournament';
@Entity('tournamentColumns')
class TournamentColumns {
@PrimaryGeneratedColumn('increment')
id_tournamentColumns: number;
@OneToOne(() => Tournament, { eager: true })
@JoinColumn({ name: 'tournament_id' })
tournament: Tournament;
@Column()
column1: string;
@Column()
column2: string;
@Column()
column3: string;
@Column()
column4: string;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
@Column()
tournament_initialized: boolean;
@Column()
tournament_ended: boolean;
}
export default TournamentColumns;

View File

@@ -0,0 +1,43 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
JoinColumn,
OneToOne,
} from 'typeorm';
import Tournament from './Tournament';
import User from './User';
@Entity('tournamentParticipants')
class TournamentParticipants {
@PrimaryGeneratedColumn('increment')
id_tournamentParticipants: string;
@OneToOne(() => Tournament, { eager: true })
@JoinColumn({ name: 'tournament_id' })
tournament: Tournament;
@OneToOne(() => User, { eager: true })
@JoinColumn({ name: 'user_id' })
user: User;
@Column()
user_accepted_invite: boolean;
@Column()
invite_refused: boolean;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
@Column()
user_kicked: boolean;
}
export default TournamentParticipants;

39
src/models/User.ts Normal file
View File

@@ -0,0 +1,39 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity('users')
class User {
@PrimaryGeneratedColumn('uuid')
id_user: string;
@Column()
name: string;
@Column()
email: string;
@Column()
birth_date: Date;
@Column()
password: string;
@Column()
avatar_image: string;
@Column()
bio: string;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
export default User;

View File

@@ -0,0 +1,90 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import Follow from '../models/Follow';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import CreateFollowService from '../services/CreateFollowService';
import DeleteFollowService from '../services/DeleteFollowService';
import CheckUserIsFollowingUserService from '../services/CheckUserIsFollowingUserService';
import UpdateFollowCounterService from '../services/UpdateFollowCounterService';
import FindUserFollowersService from '../services/FindUserFollowersService';
const followsRouter = Router();
followsRouter.get('/list', ensureAuthenticated, async (request, response) => {
const followsRepository = getRepository(Follow);
const follows = await followsRepository.find();
return response.json({ data: follows });
});
followsRouter.get('/get/:id', ensureAuthenticated, async (request, response) => {
const { id } = request.params;
const findUserFollowersService = new FindUserFollowersService();
const followers = await findUserFollowersService.execute(id);
return response.json({ data: followers });
});
followsRouter.get(
'/check/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const checkUserIsFollowingUserService = new CheckUserIsFollowingUserService();
const checkUserIsFollowing = await checkUserIsFollowingUserService.execute({
id_user_following: request.user.id_user,
id_user_followed: id,
});
return response.json({ data: checkUserIsFollowing });
},
);
followsRouter.post('/add', ensureAuthenticated, async (request, response) => {
const { id_user_followed } = request.body;
const createFollowService = new CreateFollowService();
// TODO, necessário?
await createFollowService.execute({
id_user_following: request.user.id_user,
id_user_followed,
});
const updateFollowCounterService = new UpdateFollowCounterService();
await updateFollowCounterService.execute({ id_user: id_user_followed });
return response.json({ message: 'User followed succesfully. ' });
});
followsRouter.delete(
'/remove/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const deleteFollowService = new DeleteFollowService();
await deleteFollowService.execute({
id_user_following: request.user.id_user,
id_user_followed: id,
});
const updateFollowCounterService = new UpdateFollowCounterService();
await updateFollowCounterService.execute({ id_user: id });
return response.json({ message: 'Unfollowed user.' });
},
);
export default followsRouter;

25
src/routes/index.ts Normal file
View File

@@ -0,0 +1,25 @@
import { Router } from 'express';
import sessionsRouter from './sessions.routes';
import usersRouter from './users.routes';
import tournamentsRouter from './tournaments.routes';
import pubsRouter from './publications.routes';
import tournamentParticipantsRouter from './tournamentParticipants.routes';
import tournamentColumnsRouter from './tournamentColumns.routes';
import followsRouter from './follows.routes';
import itemRouter from './item.routes';
import inventarioRouter from './inventario.routes';
const routes = Router();
routes.use('/users', usersRouter);
routes.use('/sessions', sessionsRouter);
routes.use('/tournaments', tournamentsRouter);
routes.use('/tournaments/manage', tournamentParticipantsRouter);
routes.use('/tournaments/columns', tournamentColumnsRouter);
routes.use('/pubs', pubsRouter);
routes.use('/follows/', followsRouter);
routes.use('/item/', itemRouter);
routes.use('/inventario/', inventarioRouter);
export default routes;

View File

@@ -0,0 +1,75 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import Inventario from '../models/Inventario';
import AddItemService from '../services/AddItemService';
import FindInventarioUser from '../services/FindInventarioUserService';
import FindItensAtivosService from '../services/FindItensAtivosService';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import UpdateAtivaItemService from '../services/UpdateAtivaItemService';
import UpdateDesativaItemService from '../services/UpdateDesativaItemService';
const inventarioRouter = Router();
inventarioRouter.get('/', ensureAuthenticated, async (request, response) => {
const inventarioRepository = getRepository(Inventario);
const inventario = await inventarioRepository.find();
return response.json({ data: inventario });
});
inventarioRouter.get('/find', ensureAuthenticated, async (request, response) => {
const findInventarioUser = new FindInventarioUser;
const inventario = await findInventarioUser.execute( request.user.id_user );
return response.json({ data: inventario });
});
inventarioRouter.get('/findativos', ensureAuthenticated, async (request, response) => {
const findItensAtivosService = new FindItensAtivosService;
const inventario = await findItensAtivosService.execute( request.user.id_user );
return response.json({ data: inventario });
});
inventarioRouter.post('/', ensureAuthenticated, async (request, response) => {
const { id_item } = request.body;
const addItem = new AddItemService();
await addItem.execute({ id_item, id_user: request.user.id_user});
return response.json({ message: 'Item adicionado com sucesso !' });
});
inventarioRouter.patch('/edit/ativa', ensureAuthenticated, async (request, response) => {
const { id_item } = request.body;
const updateInventarioService = new UpdateAtivaItemService();
await updateInventarioService.execute({
id_user: request.user.id_user,
id_item
});
return response.json({ message: 'Item ativado com sucesso !' });
});
inventarioRouter.patch('/edit/desativa', ensureAuthenticated, async (request, response) => {
const { id_item } = request.body;
const updateDesativaItemService = new UpdateDesativaItemService();
await updateDesativaItemService.execute({
id_user: request.user.id_user,
id_item
});
return response.json({ message: 'Item desativado com sucesso !' });
});
export default inventarioRouter;

46
src/routes/item.routes.ts Normal file
View File

@@ -0,0 +1,46 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import Item from '../models/Item';
import CreateItemService from '../services/CreateItemService';
const itemRouter = Router();
itemRouter.get('/', async (request, response) => {
const itemsRepository = getRepository(Item);
const items = await itemsRepository.find();
return response.json({ data: items });
});
itemRouter.post('/', async (request, response) => {
const { nome, tipo, asset, preco } = request.body;
const createItemService = new CreateItemService();
createItemService.execute({ nome, tipo, asset, preco });
return response.json({ message: 'Item criado com sucesso !!!'});
});
// itemRouter.patch('/edit', ensureAuthenticated, async (request, response) => {
// const { name, itemname, bio, email, birth_date } = request.body;
// const updateitemService = new UpdateitemService();
// await updateitemService.execute({
// id_item: request.item.id_item,
// name,
// itemname,
// bio,
// email,
// birth_date,
// });
// return response.json({ message: 'item info sucessfully updated.' });
// });
export default itemRouter;

View File

@@ -0,0 +1,38 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import Publication from '../models/Publication';
import CreatePublicationService from '../services/CreatePublicationService';
import FindTournamentsPublicatedService from '../services/FindTournamentsPublicatedService';
const pubsRouter = Router();
pubsRouter.get('/', async (request, response) => {
const publicationsRepository = getRepository(Publication);
const publications = await publicationsRepository.find();
return response.json({ data: publications });
});
pubsRouter.post('/', ensureAuthenticated, async (request, response) => {
const { id_tournament } = request.body;
const createPublicationService = new CreatePublicationService();
createPublicationService.execute({ id_user: request.user.id_user, id_tournament });
return response.json({ message: "Publicação criada com sucesso !!!" })
});
pubsRouter.get('/find', ensureAuthenticated, async (request, response) => {
const findPublicationService = new FindTournamentsPublicatedService();
const publications = await findPublicationService.execute( request.user.id_user );
return response.json({ data: publications });
});
export default pubsRouter;

View File

@@ -0,0 +1,21 @@
import { Router } from 'express';
import AuthenticateUserService from '../services/AuthenticateUserService';
const sessionsRouter = Router();
// login pode ser: email ou username
sessionsRouter.post('/', async (request, response) => {
const { login, password } = request.body;
const authenticateUserService = new AuthenticateUserService();
const token = await authenticateUserService.execute({
login,
password,
});
return response.json({ message: 'User logged in sucessfully', token: token });
});
export default sessionsRouter;

View File

@@ -0,0 +1,77 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import TournamentColumns from '../models/TournamentColumns';
import FindTournamentColumnsService from '../services/FindTournamentColumnsService';
import UpdateTournamentColumnsInitializedFlagService from '../services/UpdateTournamentColumnsInitializedFlagService';
import UpdateTournamentColumnsService from '../services/UpdateTournamentColumnsService';
const tournamentColumnsRouter = Router();
// não deve ser lançado
tournamentColumnsRouter.get('/list', async (request, response) => {
const tournamentsColumnsRepository = getRepository(TournamentColumns);
const tournamentsColumns = await tournamentsColumnsRepository.find();
return response.json({ data: tournamentsColumns });
});
// colunas de um torneio específico
tournamentColumnsRouter.get(
'/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const findTournamentColumnsService = new FindTournamentColumnsService();
const tournamentColumns = await findTournamentColumnsService.execute(id);
return response.json({ data: tournamentColumns });
},
);
// atualiza as colunas
tournamentColumnsRouter.patch(
'/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const { column1, column2, column3, column4 } = request.body;
const updateTournamentColumnsService = new UpdateTournamentColumnsService();
await updateTournamentColumnsService.execute(id, {
column1,
column2,
column3,
column4,
});
return response.json({
message: 'Tournament columns updated sucessfully.',
});
},
);
// atualiza a flag da coluna tournament_initialized
tournamentColumnsRouter.patch(
'/flag/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const { flag } = request.body;
const updateTournamentColumnsInitializedFlagService = new UpdateTournamentColumnsInitializedFlagService();
await updateTournamentColumnsInitializedFlagService.execute(id, flag);
return response.json({
message: 'Tournament columns flag updated sucessfully.',
});
},
);
export default tournamentColumnsRouter;

View File

@@ -0,0 +1,203 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import TournamentParticipants from '../models/TournamentParticipant';
import CheckUserIsKickedFromTournamentService from '../services/CheckUserIsKickedFromTournamentService';
import CreateTournamentParticipantService from '../services/CreateTournamentParticipantService';
import FindAcceptedTournamentParticipantsService from '../services/FindAcceptedTournamentParticipantsService';
import FindKickedParticipantsFromTournamentService from '../services/FindKickedParticipantsFromTournamentService';
import FindPendingTournamentInvitesService from '../services/FindPendingTournamentInvitesService';
import FindTournamentsUserIsParticipatingService from '../services/FindTournamentsUserIsParticipatingService';
import KickTournamentParticipantService from '../services/KickTournamentParticipantService';
import UpdateTournamentsInviteUserAcceptedService from '../services/UpdateTournamentsInviteUserAcceptedService';
import UpdateTournamentsInviteUserRefusedService from '../services/UpdateTournamentsInviteUserRefusedService';
const tournamentParticipantsRouter = Router();
// observação:
// essa rota trata da tabela tournamentParticipants
// que vai cuidar da parte tanto do convite da pessoa tanto de sua participação
// pela coluna user_accepted_invite
// não deve ser lançado
tournamentParticipantsRouter.get('/list', async (request, response) => {
const tournamentsParticipantsRepository = getRepository(
TournamentParticipants,
);
const tournamentsParticipants = await tournamentsParticipantsRepository.find();
return response.json({ data: tournamentsParticipants });
});
// rota que vai retornar os tournamentInvites de outra pessoa
// interessante para mostrar os torneios públicos em que a pessoa está participando, isso do perfil dela
// mas não é o foco da sprint atual (2)
/*
tournamentParticipantsRouter.get('/user/:id', ensureAuthenticated, async (request, response) => {
let { id } = request.params;
const findTournamentService = new FindTournamentService();
const tournament = await findTournamentService.execute(id);
return response.json({ data: tournament });
});
*/
// rota que vai retornar os tournamentInvites (com os torneios que o usuário logado está participando)
tournamentParticipantsRouter.get(
'/user',
ensureAuthenticated,
async (request, response) => {
const findTournamentsUserIsParticipatingService = new FindTournamentsUserIsParticipatingService();
const tournamentsUserIsParticipating = await findTournamentsUserIsParticipatingService.execute(
request.user.id_user,
);
return response.json({ data: tournamentsUserIsParticipating });
},
);
// pega os participantes (Users) de um torneio e retorna apenas aqueles que aceitaram (user_accepted_invite -> true)
tournamentParticipantsRouter.get(
'/users/accepted/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const findAcceptedTournamentParticipantsService = new FindAcceptedTournamentParticipantsService();
const tournamentAcceptedParticipantsAsUsers = await findAcceptedTournamentParticipantsService.execute(
id,
);
return response.json({ data: tournamentAcceptedParticipantsAsUsers });
},
);
// pega os invites pendentes de um usuário
tournamentParticipantsRouter.get(
'/user/pending/',
ensureAuthenticated,
async (request, response) => {
const findPendingTournamentInvitesService = new FindPendingTournamentInvitesService();
const pendingInvites = await findPendingTournamentInvitesService.execute(
request.user.id_user,
);
return response.json({ data: pendingInvites });
},
);
// cria um convite
tournamentParticipantsRouter.post(
'/invite/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const { id_tournament } = request.body;
const createTournamentParticipantService = new CreateTournamentParticipantService();
await createTournamentParticipantService.execute({
id_user: id,
id_tournament,
creator_id_user: request.user.id_user,
});
return response.json({ message: 'Invitation created sucessfully.' });
},
);
// aceita um convite de um torneio
tournamentParticipantsRouter.patch(
'/accept/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const updateTournamentsInviteUserAcceptedService = new UpdateTournamentsInviteUserAcceptedService();
await updateTournamentsInviteUserAcceptedService.execute({
id_tournament: id,
id_user: request.user.id_user,
});
return response.json({ message: 'Invitation accepted.' });
},
);
// recusa um convite de um torneio
tournamentParticipantsRouter.patch(
'/refuse/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const updateTournamentsInviteUserRefusedService = new UpdateTournamentsInviteUserRefusedService();
await updateTournamentsInviteUserRefusedService.execute({
id_tournament: id,
id_user: request.user.id_user,
});
return response.json({ message: 'Invitation accepted.' });
},
);
tournamentParticipantsRouter.patch(
'/kick',
ensureAuthenticated,
async (request, response) => {
const { id_user, id_tournament } = request.body;
const kickTournamentParticipantService = new KickTournamentParticipantService();
await kickTournamentParticipantService.execute({
id_user,
id_tournament,
});
return response.json({ message: 'User was kicked from tournament.' });
},
);
// TODO, não devia ser post
tournamentParticipantsRouter.post(
'/iskicked',
ensureAuthenticated,
async (request, response) => {
const { id_user, id_tournament } = request.body;
const checkUserIsKickedFromTournamentService = new CheckUserIsKickedFromTournamentService();
const isUserKicked = await checkUserIsKickedFromTournamentService.execute({
id_user,
id_tournament,
});
return response.json({ message: isUserKicked });
},
);
// retorna um array de users que foram kickados de um torneio
tournamentParticipantsRouter.get(
'/kicked/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const findKickedParticipantsFromTournamentService = new FindKickedParticipantsFromTournamentService();
const tournamentKickedUsers = await findKickedParticipantsFromTournamentService.execute(
id,
);
return response.json({ data: tournamentKickedUsers });
},
);
export default tournamentParticipantsRouter;

View File

@@ -0,0 +1,96 @@
// TODO: Arrumar a rota
import { Router } from 'express';
import { getRepository } from 'typeorm';
import { v4 } from 'uuid';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import Tournament from '../models/Tournament';
import CreateTournamentService from '../services/CreateTournamentService';
import FindTournamentsByUserService from '../services/FindTournamentsByUserService';
import FindTournamentService from '../services/FindTournamentService';
import UpdateTournamentAsEndedService from '../services/UpdateTournamentAsEnded';
import UpdateTournamentService from '../services/UpdateTournamentService';
const tournamentsRouter = Router();
// não deve ser lançado
tournamentsRouter.get('/list', async (request, response) => {
const tournamentsRepository = getRepository(Tournament);
const tournaments = await tournamentsRepository.find();
return response.json({ data: tournaments });
});
tournamentsRouter.get(
'/id/:id',
ensureAuthenticated,
async (request, response) => {
let { id } = request.params;
const findTournamentService = new FindTournamentService();
const tournament = await findTournamentService.execute(id);
return response.json({ data: tournament });
},
);
tournamentsRouter.get(
'/user',
ensureAuthenticated,
async (request, response) => {
const findTournamentByUserService = new FindTournamentsByUserService();
const tournaments = await findTournamentByUserService.execute(
request.user.id_user,
);
return response.json({ data: tournaments });
},
);
tournamentsRouter.post('/', ensureAuthenticated, async (request, response) => {
const {
name,
game,
description,
password,
number_participants,
} = request.body;
const createTournamentService = new CreateTournamentService();
createTournamentService.execute({
id_user: request.user.id_user,
name,
game,
description,
password,
number_participants,
});
return response.json({ message: 'Tournament created sucessfully.' });
});
tournamentsRouter.patch('/edit/:id', async (request, response) => {
const { id } = request.params;
const { name, game, description, password } = request.body;
const updateTournamentService = new UpdateTournamentService();
updateTournamentService.execute({ id, name, game, description, password });
return response.json({ message: 'Tournament updated sucessfully.' });
});
tournamentsRouter.patch('/end/:id', async (request, response) => {
const { id } = request.params;
const updateTournamentAsEndedService = new UpdateTournamentAsEndedService();
await updateTournamentAsEndedService.execute({ id_tournament: id });
return response.json({ message: 'Tournament was set as ended.' });
});
export default tournamentsRouter;

237
src/routes/users.routes.ts Normal file
View File

@@ -0,0 +1,237 @@
import { Router } from 'express';
import { getRepository } from 'typeorm';
import User from '../models/User';
import CreateUserService from '../services/CreateUserService';
import FindUserService from '../services/FindUserService';
import FindUserSocialService from '../services/FindUserSocialService';
import UpdateUserSocialService from '../services/UpdateUserSocialService';
import UpdateUserService from '../services/UpdateUserService';
import UpdateUserAvatarService from '../services/UpdateUserAvatarService';
import UpdateUserBackgroundService from '../services/UpdateUserBackgroundService';
import UpdateUserPasswordService from '../services/UpdateUserPasswordService';
import ensureAuthenticated from '../middlewares/ensureAuthenticated';
import ensureAdmin from '../middlewares/ensureAdmin';
import AuthenticateUserService from '../services/AuthenticateUserService';
import UpdateUserCoinsService from '../services/UpdateUserCoinsService';
import FindUserColocationsService from '../services/FindUserColocationsService';
const usersRouter = Router();
interface userWithoutSensitiveInfo {
id_user: string;
name: string;
email: string;
avatar_image: string;
}
usersRouter.get('/list', async (request, response) => {
const usersRepository = getRepository(User);
const users = await usersRepository.find();
let usersWithoutSensitiveInfo: userWithoutSensitiveInfo[] = [];
users.map(user => {
usersWithoutSensitiveInfo.push({
id_user: user.id_user,
name: user.name,
email: user.email,
avatar_image: user.avatar_image,
});
});
return response.json({ data: usersWithoutSensitiveInfo });
});
// TODO, criar middleware ensureIsOwnUser é necessário?
// usar browserAgent, Encrypted Local Storage ou algo do tipo
usersRouter.get('/:id', ensureAuthenticated, async (request, response) => {
const { id } = request.params;
const findUser = new FindUserService();
const user = await findUser.execute(id);
const userWithoutPassword = {
id_user: user.id_user,
name: user.name,
email: user.email,
birth_date: user.birth_date,
avatar_image: user.avatar_image,
bio: user.bio,
created_at: user.created_at,
updated_at: user.updated_at,
};
return response.json({ data: userWithoutPassword });
});
usersRouter.post('/', async (request, response) => {
const { name, email, birth_date, password } = request.body;
const createUser = new CreateUserService();
const user = await createUser.execute({
name,
email,
birth_date,
password,
});
const authenticateUser = new AuthenticateUserService();
const token = await authenticateUser.execute({
login: user.email,
password: password,
});
return response.json({ message: 'User successfully created.', token: token });
});
usersRouter.patch('/edit', ensureAuthenticated, async (request, response) => {
const { name, username, bio, email, birth_date } = request.body;
const updateUserService = new UpdateUserService();
await updateUserService.execute({
id_user: request.user.id_user,
name,
username,
bio,
email,
birth_date,
});
return response.json({ message: 'User info sucessfully updated.' });
});
usersRouter.patch('/edit/avatar', ensureAuthenticated, async (request, response) => {
const { avatar_image } = request.body;
const updateUserAvatarService = new UpdateUserAvatarService();
await updateUserAvatarService.execute({
id_user: request.user.id_user,
avatar_image,
});
return response.json({ message: 'Avatar atualizado com sucesso !' });
});
usersRouter.patch('/edit/background', ensureAuthenticated, async (request, response) => {
const { background_image } = request.body;
const updateUserBackgroundService = new UpdateUserBackgroundService();
await updateUserBackgroundService.execute({
id_user: request.user.id_user,
background_image,
});
return response.json({ message: 'Background atualizado com sucesso !' });
});
usersRouter.get(
'/social/:id',
ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const findUserSocial = new FindUserSocialService();
const social = await findUserSocial.execute(id);
return response.json({ data: social });
},
);
usersRouter.patch(
'/edit/social',
ensureAuthenticated,
async (request, response) => {
const { social_network, username } = request.body;
const updateUserSocialService = new UpdateUserSocialService();
await updateUserSocialService.execute({
id_user: request.user.id_user,
social_network,
username,
});
return response.json({ message: 'Social info sucessfully updated.' });
},
);
usersRouter.patch(
'/edit/password',
ensureAuthenticated,
async (request, response) => {
const { password_old, password_new } = request.body;
const updateUserPasswordService = new UpdateUserPasswordService();
await updateUserPasswordService.execute({
id_user: request.user.id_user,
password_old: password_old,
password_new: password_new,
});
return response.json({ message: 'Password sucessfully updated.' });
},
);
usersRouter.patch(
'/coins/add',
ensureAuthenticated,
async (request, response) => {
const { id_user, quantity } = request.body;
const updateUserCoins = new UpdateUserCoinsService();
await updateUserCoins.execute({
id_user,
quantity,
operation: 'add',
});
return response.json({ message: quantity + ' coins were given.' });
},
);
usersRouter.patch(
'/coins/remove',
ensureAuthenticated,
async (request, response) => {
const { id_user, quantity } = request.body;
const updateUserCoins = new UpdateUserCoinsService();
await updateUserCoins.execute({
id_user,
quantity,
operation: 'remove',
});
return response.json({ message: quantity + ' coins were taken.' });
},
);
// vai retornar as colocações de um usuário
usersRouter.get(
'/colocations/:id',
// TODO, voltar
// ensureAuthenticated,
async (request, response) => {
const { id } = request.params;
const findUserColocationsService = new FindUserColocationsService();
const userColocations = await findUserColocationsService.execute(id);
return response.json({ data: userColocations });
},
);
export default usersRouter;

39
src/server.ts Normal file
View File

@@ -0,0 +1,39 @@
import 'reflect-metadata';
import express, { Request, Response, NextFunction } from 'express';
import 'express-async-errors';
import { createConnection } from "typeorm";
import routes from './routes';
import AppError from './errors/AppError';
import cors from "cors";
const app = express();
app.use(cors());
app.use(express.json());
app.use(routes);
createConnection();
app.use((err: Error, request: Request, response: Response, _: NextFunction) => {
if (err instanceof AppError) {
return response.status(err.statusCode).json({
status: 'error',
message: err.message,
});
}
console.error(err);
return response.status(500).json({
status: 'error',
message: 'Internal server error',
});
});
app.listen(3333, () => {
console.log('🚀 Server started on port 3333!');
});

View File

@@ -0,0 +1,48 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Inventario from '../models/Inventario';
import User from '../models/User';
import Item from '../models/Item';
interface Request {
id_item: string;
id_user: string;
}
class AddItemService {
public async execute({
id_item,
id_user
}: Request): Promise<Inventario> {
const inventarioRepository = getRepository(Inventario);
const usersRepository = getRepository(User);
const itemsRepository = getRepository(Item);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const item = await itemsRepository.findOne({
where: { id_item },
});
if (!item) {
throw new AppError('User does not exist.');
}
const inventario = inventarioRepository.create({
item, user
});
await inventarioRepository.save(inventario);
return inventario;
}
}
export default AddItemService;

View File

@@ -0,0 +1,58 @@
import { getRepository } from 'typeorm';
import { compare } from 'bcryptjs';
import { sign } from 'jsonwebtoken';
import authConfig from '../config/auth';
import AppError from '../errors/AppError';
import User from '../models/User';
interface Request {
login: string;
password: string;
}
interface Response {
token: string;
id_user: string;
}
class AuthenticateUserService {
public async execute({ login, password }: Request): Promise<Response> {
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: [{email: login }],
});
// TODO, ajeitar todos os HTTP status code
// Por que tem que deixar 200 para funcionar?
if (!user) {
throw new AppError('Incorrect login/password combination.', 200);
}
// user.password -> senha criptografada
// password -> senha não-criptografada
const passwordMatched = await compare(password, user.password);
if (!passwordMatched) {
throw new AppError('Incorrect login/password combination.', 200);
}
// usuário autenticado
const { secret, expiresIn } = authConfig.jwt;
const token = sign({}, secret, {
subject: user.id_user,
expiresIn,
// pensar na questão "experiência de usuário X segurança"
// estratégias de refresh token
});
return { token, id_user: user.id_user };
}
}
export default AuthenticateUserService;

View File

@@ -0,0 +1,48 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Follow from '../models/Follow';
interface Request {
id_user_following: string;
id_user_followed: string;
}
class CheckUserIsFollowingUserService {
public async execute({
id_user_following,
id_user_followed,
}: Request): Promise<boolean> {
const usersRepository = getRepository(User);
const followsRepository = getRepository(Follow);
const user_following = await usersRepository.findOne({
where: { id_user: id_user_following },
});
if (!user_following) {
throw new AppError('User 1 does not exist.');
}
const user_followed = await usersRepository.findOne({
where: { id_user: id_user_followed },
});
if (!user_followed) {
throw new AppError('User 2 does not exist.');
}
const follow = await followsRepository.findOne({
where: { user_following, user_followed },
});
if (!follow) {
return false;
}
return true;
}
}
export default CheckUserIsFollowingUserService;

View File

@@ -0,0 +1,51 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Tournament from '../models/Tournament';
import TournamentParticipants from '../models/TournamentParticipant';
interface Request {
id_user: string;
id_tournament: string;
}
class CheckUserIsKickedFromTournamentService {
public async execute({ id_user, id_tournament }: Request): Promise<boolean> {
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const TournamentsParticipantsRepository = getRepository(
TournamentParticipants,
);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const userInTournamentParticipants = await TournamentsParticipantsRepository.findOne(
{
where: { user, tournament },
},
);
if (!userInTournamentParticipants) {
throw new AppError('User is not in this tournament.');
}
return userInTournamentParticipants.user_kicked;
}
}
export default CheckUserIsKickedFromTournamentService;

View File

@@ -0,0 +1,59 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Follow from '../models/Follow';
import CheckUserIsFollowingUserService from './CheckUserIsFollowingUserService';
interface Request {
id_user_following: string;
id_user_followed: string;
}
class CreateFollowService {
public async execute({
id_user_following,
id_user_followed,
}: Request): Promise<Follow> {
const usersRepository = getRepository(User);
const followsRepository = getRepository(Follow);
const user_following = await usersRepository.findOne({
where: { id_user: id_user_following },
});
if (!user_following) {
throw new AppError('User 1 does not exist.');
}
const user_followed = await usersRepository.findOne({
where: { id_user: id_user_followed },
});
if (!user_followed) {
throw new AppError('User 2 does not exist.');
}
const checkUserIsFollowingUserService = new CheckUserIsFollowingUserService();
const userIsFollowing = await checkUserIsFollowingUserService.execute({
id_user_following,
id_user_followed,
});
if (userIsFollowing) {
throw new AppError('You are already following this user.');
}
const follow = followsRepository.create({
user_following,
user_followed,
});
await followsRepository.save(follow);
return follow;
}
}
export default CreateFollowService;

View File

@@ -0,0 +1,35 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Item from '../models/Item';
interface Request {
nome: string;
tipo: string;
asset: string;
preco: number;
}
class CreateItemService {
public async execute({
nome,
tipo,
asset,
preco
}: Request): Promise<Item> {
const itemsRepository = getRepository(Item);
const item = itemsRepository.create({
nome,
tipo,
asset,
preco
});
await itemsRepository.save(item);
return item;
}
}
export default CreateItemService;

View File

@@ -0,0 +1,48 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Publication from '../models/Publication';
import Tournament from '../models/Tournament';
interface Request {
id_user: string;
id_tournament: string;
}
class CreatePublicationService {
public async execute({
id_user,
id_tournament
}: Request): Promise<Publication> {
const pubsRepository = getRepository(Publication);
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const publication = pubsRepository.create({
tournament
});
await pubsRepository.save(publication);
return publication;
}
}
export default CreatePublicationService;

View File

@@ -0,0 +1,70 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Tournament from '../models/Tournament';
import TournamentParticipant from '../models/TournamentParticipant';
import { request } from 'express';
interface Request {
id_tournament: string;
id_user: string;
creator_id_user: string;
}
class CreateTournamentParticipantService {
public async execute({
id_tournament,
id_user,
creator_id_user,
}: Request): Promise<TournamentParticipant> {
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const tournamentsParticipantRepository = getRepository(
TournamentParticipant,
);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
if (creator_id_user == user.id_user) {
throw new AppError("You can't invite yourself.", 200);
}
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const userIsAlreadyInvited = await tournamentsParticipantRepository.findOne(
{
where: { user, tournament },
},
);
if (userIsAlreadyInvited) {
throw new AppError('User is already invited.', 200);
}
const tournamentParticipant = tournamentsParticipantRepository.create({
tournament,
user,
user_accepted_invite: false,
});
await tournamentsParticipantRepository.save(tournamentParticipant);
return tournamentParticipant;
}
}
export default CreateTournamentParticipantService;

View File

@@ -0,0 +1,60 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import TournamentColumns from '../models/TournamentColumns';
import User from '../models/User';
interface Request {
id_user: string;
name: string;
game: string;
description: string;
password?: string;
number_participants: number;
}
class CreateTournamentService {
public async execute({
id_user,
name,
game,
description,
password,
number_participants,
}: Request): Promise<Tournament> {
const tournamentsRepository = getRepository(Tournament);
const usersRepository = getRepository(User);
const tournamentColumnsRepository = getRepository(TournamentColumns);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournament = tournamentsRepository.create({
user,
name,
game,
description,
password,
number_participants,
});
await tournamentsRepository.save(tournament);
// já cria o registro em tournamentColumns para evitar inconsistências
// igual foi em Users para Socials
const tournamentColumn = tournamentColumnsRepository.create({
tournament,
});
await tournamentColumnsRepository.save(tournamentColumn);
return tournament;
}
}
export default CreateTournamentService;

View File

@@ -0,0 +1,48 @@
import { getRepository } from 'typeorm';
import { v4 } from 'uuid';
import { hash } from 'bcryptjs';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
name: string;
email: string;
birth_date: string;
password: string;
}
class CreateUserService {
public async execute({ name, email, birth_date, password }: Request): Promise<User> {
const usersRepository = getRepository(User);
const socialsRepository = getRepository(Social);
const checkUserEmailExists = await usersRepository.findOne({
where: { email },
});
if (checkUserEmailExists) {
throw new AppError('Email address is already used.', 200);
}
const hashedPassword = await hash(password, 8);
// TODO, arrumar regras de negócio para avatar_image e background_image
// TODO, arrumar o formato das datas e padronizar com a equipe
const user = usersRepository.create({
id_user: v4(), name, email, birth_date, password: hashedPassword, avatar_image: "", bio: ""
});
await usersRepository.save(user);
// já criar registro na tabela Socials para evitar inconsistências
// const social = socialsRepository.create({ user, telegram: "", facebook: "", twitter: "", twitch: "" });
// await socialsRepository.save(social);
return user;
}
}
export default CreateUserService;

View File

@@ -0,0 +1,62 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Follow from '../models/Follow';
import CheckUserIsFollowingUserService from './CheckUserIsFollowingUserService';
interface Request {
id_user_following: string;
id_user_followed: string;
}
class DeleteFollowService {
public async execute({
id_user_following,
id_user_followed,
}: Request): Promise<boolean> {
const usersRepository = getRepository(User);
const followsRepository = getRepository(Follow);
const user_following = await usersRepository.findOne({
where: { id_user: id_user_following },
});
if (!user_following) {
throw new AppError('User 1 does not exist.');
}
const user_followed = await usersRepository.findOne({
where: { id_user: id_user_followed },
});
if (!user_followed) {
throw new AppError('User 2 does not exist.');
}
const checkUserIsFollowingUserService = new CheckUserIsFollowingUserService();
const userIsFollowing = await checkUserIsFollowingUserService.execute({
id_user_following,
id_user_followed,
});
if (!userIsFollowing) {
throw new AppError('You are not following this user.');
}
const follow = await followsRepository.findOne({
where: [{ user_following }, { user_followed }],
});
if (!follow) {
throw new AppError('User is not following.');
}
await followsRepository.remove(follow);
return true;
}
}
export default DeleteFollowService;

View File

@@ -0,0 +1,56 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
// TODO, verificar pluralidade (tournamentParticipant (v, certo) != tournamentParticipants (x, errado))
import TournamentParticipant from '../models/TournamentParticipant';
import User from '../models/User';
class FindAcceptedTournamentParticipantsService {
public async execute(id_tournament: string): Promise<User[]> {
const tournamentsRepository = getRepository(Tournament);
const tournamentParticipantsRepository = getRepository(
TournamentParticipant,
);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentParticipants = await tournamentParticipantsRepository.find({
where: { tournament },
});
if (!tournamentParticipants) {
throw new AppError('Tournament does not have participants yet.', 200);
}
let tournamentAcceptedParticipantsAsUsers: User[] = [];
tournamentParticipants.map(tournamentParticipant => {
if (tournamentParticipant.user_accepted_invite) {
/* TODO, dar um jeito de filtrar as informações desnecessárias
const userWithoutSensitiveInfo = {
id_user: tournamentParticipant.user.id_user,
name: tournamentParticipant.user.name,
username: tournamentParticipant.user.username,
};
*/
tournamentAcceptedParticipantsAsUsers.push(tournamentParticipant.user);
}
});
const newTournaments = tournamentParticipants.filter((element) => {
if (!element.user_accepted_invite) return element;
})
return tournamentAcceptedParticipantsAsUsers;
}
}
export default FindAcceptedTournamentParticipantsService;

View File

@@ -0,0 +1,33 @@
import { Equal, getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Inventario from '../models/Inventario';
import User from '../models/User';
class FindInventarioUserService {
public async execute(id: string): Promise<Inventario[]> {
const inventarioRepository = getRepository(Inventario);
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id },
});
if (!user) {
throw new AppError('User does not exist.');
}
const inventario = await inventarioRepository.find({
where: {user: Equal (user.id_user) }
});
if (!inventario) {
throw new AppError('Tournament does not exist.');
}
return inventario;
}
}
export default FindInventarioUserService;

View File

@@ -0,0 +1,33 @@
import { Equal, getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Inventario from '../models/Inventario';
import User from '../models/User';
class FindItensAtivosService {
public async execute(id: string): Promise<Inventario[]> {
const inventarioRepository = getRepository(Inventario);
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id },
});
if (!user) {
throw new AppError('User does not exist.');
}
const inventario = await inventarioRepository.find({
where: {user: Equal (user.id_user), ativo: Equal(true) }
});
if (!inventario) {
throw new AppError('Tournament does not exist.');
}
return inventario;
}
}
export default FindItensAtivosService;

View File

@@ -0,0 +1,44 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import TournamentParticipant from '../models/TournamentParticipant';
import User from '../models/User';
class FindKickedParticipantsFromTournamentService {
public async execute(id_tournament: string): Promise<User[]> {
const tournamentsRepository = getRepository(Tournament);
const TournamentParticipantsRepository = getRepository(
TournamentParticipant,
);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentKickedParticipants = await TournamentParticipantsRepository.find(
{
where: { tournament, user_kicked: true },
},
);
if (!tournamentKickedParticipants) {
throw new AppError('Tournament does not have participants.');
}
let tournamentKickedParticipantsAsUsers: User[] = [];
tournamentKickedParticipants.map(element => {
tournamentKickedParticipantsAsUsers.push(element.user);
});
return tournamentKickedParticipantsAsUsers;
}
}
export default FindKickedParticipantsFromTournamentService;

View File

@@ -0,0 +1,33 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import TournamentParticipants from '../models/TournamentParticipant';
import TournamentParticipant from '../models/TournamentParticipant';
import User from '../models/User';
class FindPendingTournamentInvitesService {
public async execute(id_user: string): Promise<TournamentParticipants[]> {
const usersRepository = getRepository(User);
const tournamentParticipantsRepository = getRepository(
TournamentParticipant,
);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
// TODO, não está filtrando certo
const tournamentParticipants = await tournamentParticipantsRepository.find({
where: { user, invite_refused: false, user_accepted_invite: false },
});
return tournamentParticipants;
}
}
export default FindPendingTournamentInvitesService;

View File

@@ -0,0 +1,33 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import TournamentColumns from '../models/TournamentColumns';
class FindTournamentColumnsService {
public async execute(id_tournament: string): Promise<TournamentColumns> {
const tournamentsRepository = getRepository(Tournament);
const tournamentColumnsRepository = getRepository(TournamentColumns);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentColumns = await tournamentColumnsRepository.findOne({
where: { tournament },
});
if (!tournamentColumns) {
throw new AppError('Tournament does not have columns.');
}
return tournamentColumns;
}
}
export default FindTournamentColumnsService;

View File

@@ -0,0 +1,23 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
class FindTournamentService {
public async execute(id: string): Promise<Tournament> {
const tournamentsRepository = getRepository(Tournament);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament: id },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
return tournament;
}
}
export default FindTournamentService;

View File

@@ -0,0 +1,29 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import User from '../models/User';
class FindTournamentsByUserService {
public async execute(id: string): Promise<Tournament[]> {
const tournamentsRepository = getRepository(Tournament);
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournaments = await tournamentsRepository.find({
where: { user }
})
return tournaments;
}
}
export default FindTournamentsByUserService;

View File

@@ -0,0 +1,33 @@
import { getRepository, Not } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import User from '../models/User';
class FindTournamentService {
public async execute(id: string): Promise<Tournament[]> {
const tournamentsRepository = getRepository(Tournament);
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournaments = await tournamentsRepository.find({
where: {user: Not (user.id_user) }
});
if (!tournaments) {
throw new AppError('Tournament does not exist.');
}
return tournaments;
}
}
export default FindTournamentService;

View File

@@ -0,0 +1,35 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import TournamentParticipant from '../models/TournamentParticipant';
import Tournament from '../models/Tournament';
class FindTournamentsUserIsParticipatingService {
public async execute(id_user: string): Promise<TournamentParticipant[]> {
const tournamentParticipantRepository = getRepository(
TournamentParticipant,
);
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const acceptedTournamentsInvitesOfUser = await tournamentParticipantRepository.find(
{
where: { user, user_accepted_invite: true },
},
);
return acceptedTournamentsInvitesOfUser;
}
}
export default FindTournamentsUserIsParticipatingService;

View File

@@ -0,0 +1,113 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import TournamentParticipant from '../models/TournamentParticipant';
import TournamentColumns from '../models/TournamentColumns';
import Tournament from '../models/Tournament';
interface Colocations {
tournament_id: string;
tournament_name: string;
tournament_game: string;
tournament_description: string;
colocation: 'Participante' | 'Semifinalista' | 'Vencedor';
}
class FindUserColocationsService {
public async execute(id_user: string): Promise<Colocations[]> {
const tournamentParticipantRepository = getRepository(
TournamentParticipant,
);
const usersRepository = getRepository(User);
const tournamentColumnsRepository = getRepository(TournamentColumns);
const tournamentsRepository = getRepository(Tournament);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournamentsUserIsParticipating = await tournamentParticipantRepository.find(
{
where: { user, user_accepted_invite: true },
},
);
if (tournamentsUserIsParticipating.length == 0) {
throw new AppError('User is not in any tournament.', 200);
}
const tournamentsUserIsParticipatingFiltered = tournamentsUserIsParticipating.map(
element => {
return element.tournament;
},
);
let endedTournamentsUserIsParticipating: TournamentColumns[][] = [];
const promises1 = tournamentsUserIsParticipatingFiltered.map(
async tournament => {
return await tournamentColumnsRepository.find({
where: { tournament, tournament_ended: true },
});
},
);
endedTournamentsUserIsParticipating = await Promise.all(promises1);
if (endedTournamentsUserIsParticipating.length == 0) {
throw new AppError('User is not in any tournament that has ended.', 200);
}
let userColocations: Colocations[] = [];
endedTournamentsUserIsParticipating.map(tournamentColumns => {
tournamentColumns.map(tournamentColumns2 => {
if (tournamentColumns2.column3.includes(user.name)) {
userColocations.push({
tournament_id: tournamentColumns2.tournament.id_tournament,
tournament_name: tournamentColumns2.tournament.name,
tournament_game: tournamentColumns2.tournament.game,
tournament_description: tournamentColumns2.tournament.description,
colocation: 'Vencedor',
});
return;
}
if (tournamentColumns2.column2.includes(user.name)) {
userColocations.push({
tournament_id: tournamentColumns2.tournament.id_tournament,
tournament_name: tournamentColumns2.tournament.name,
tournament_game: tournamentColumns2.tournament.game,
tournament_description: tournamentColumns2.tournament.description,
colocation: 'Semifinalista',
});
return;
}
if (tournamentColumns2.column1.includes(user.name)) {
userColocations.push({
tournament_id: tournamentColumns2.tournament.id_tournament,
tournament_name: tournamentColumns2.tournament.name,
tournament_game: tournamentColumns2.tournament.game,
tournament_description: tournamentColumns2.tournament.description,
colocation: 'Participante',
});
return;
}
});
});
return userColocations;
}
}
export default FindUserColocationsService;

View File

@@ -0,0 +1,29 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Follow from '../models/Follow';
import User from '../models/User';
class FindUserFollowersService {
public async execute(id_user: string): Promise<Follow[]> {
const usersRepository = getRepository(User);
const followRepository = getRepository(Follow);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const followers = await followRepository.find({
where: { user_followed: user },
});
return followers;
}
}
export default FindUserFollowersService;

View File

@@ -0,0 +1,23 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
class CreateUserService {
public async execute(id: string): Promise<User> {
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id },
});
if (!user) {
throw new AppError('User does not exist.');
}
return user;
}
}
export default CreateUserService;

View File

@@ -0,0 +1,36 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
class FindUserSocialService {
public async execute(id_user: string): Promise<Social> {
const usersRepository = getRepository(User);
const socialRepository = getRepository(Social);
const user = await usersRepository.findOne({
where: { id_user }
});
if (!user) {
// TODO, fazer no front um tratamento para isso
throw new AppError('User does not exist.');
};
const social = await socialRepository.findOne({
where: { user },
});
if (!social) {
// TODO, lembrar
// muito importate colocar o código HTTP de erro
throw new AppError('User does not have social information.', 200);
};
return social;
}
}
export default FindUserSocialService;

View File

@@ -0,0 +1,56 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Tournament from '../models/Tournament';
import TournamentParticipant from '../models/TournamentParticipant';
interface Request {
id_user: string;
id_tournament: string;
}
class KickTournamentParticipantService {
public async execute({ id_user, id_tournament }: Request): Promise<boolean> {
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const tournamentParticipantsRepository = getRepository(
TournamentParticipant,
);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentParticipants = await tournamentParticipantsRepository.findOne(
{
where: { tournament, user },
},
);
if (!tournamentParticipants) {
throw new AppError('User is not invited to this tournament.');
}
tournamentParticipants.user_kicked = true;
await tournamentParticipantsRepository.save(tournamentParticipants);
return true;
}
}
export default KickTournamentParticipantService;

View File

@@ -0,0 +1,52 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Inventario from '../models/Inventario';
import Item from '../models/Item';
interface Request {
id_user: string;
id_item: number;
}
class UpdateAtivaItemService {
public async execute({ id_user, id_item }: Request): Promise<Inventario> {
const usersRepository = getRepository(User);
const inventarioRepository = getRepository(Inventario);
const ItemRepository = getRepository(Item);
const user = await usersRepository.findOne({
where: { id_user: id_user }
});
if (!user) {
throw new AppError('User does not exist.');
};
const item = await ItemRepository.findOne({
where: { id_item: id_item}
});
if (!item) {
throw new AppError('Item does not exist.');
};
const inventario = await inventarioRepository.findOne({
where: { item: item, user: user}
});
if (!inventario) {
throw new AppError('Inventario não contém esse item.');
};
inventario.ativo = true;
await inventarioRepository.save(inventario);
return inventario;
}
}
export default UpdateAtivaItemService;

View File

@@ -0,0 +1,52 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Inventario from '../models/Inventario';
import Item from '../models/Item';
interface Request {
id_user: string;
id_item: number;
}
class UpdateDesativaItemService {
public async execute({ id_user, id_item }: Request): Promise<Inventario> {
const usersRepository = getRepository(User);
const inventarioRepository = getRepository(Inventario);
const ItemRepository = getRepository(Item);
const user = await usersRepository.findOne({
where: { id_user: id_user }
});
if (!user) {
throw new AppError('User does not exist.');
};
const item = await ItemRepository.findOne({
where: { id_item: id_item}
});
if (!item) {
throw new AppError('Item does not exist.');
};
const inventario = await inventarioRepository.findOne({
where: { item: item, user: user}
});
if (!inventario) {
throw new AppError('Inventario não contém esse item.');
};
inventario.ativo = false;
await inventarioRepository.save(inventario);
return inventario;
}
}
export default UpdateDesativaItemService;

View File

@@ -0,0 +1,37 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Follow from '../models/Follow';
import User from '../models/User';
interface Request {
id_user: string;
}
class UpdateFollowCounterService {
public async execute({ id_user }: Request): Promise<User> {
const followRepository = getRepository(Follow);
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const followCount = await followRepository.count({
where: { user_followed: user },
});
user.followers = followCount.toString();
await usersRepository.save(user);
return user;
}
}
export default UpdateFollowCounterService;

View File

@@ -0,0 +1,41 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import TournamentColumns from '../models/TournamentColumns';
interface Request {
id_tournament: string;
}
class UpdateTournamentAsEndedService {
public async execute({ id_tournament }: Request): Promise<Tournament> {
const tournamentsRepository = getRepository(Tournament);
const tournamentsColumnsRepository = getRepository(TournamentColumns);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentColumns = await tournamentsColumnsRepository.findOne({
where: { tournament },
});
if (!tournamentColumns) {
throw new AppError('Tournament does not have columns.');
}
tournamentColumns.tournament_ended = true;
await tournamentsColumnsRepository.save(tournamentColumns);
return tournament;
}
}
export default UpdateTournamentAsEndedService;

View File

@@ -0,0 +1,48 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import TournamentColumns from '../models/TournamentColumns';
interface Columns {
column1: string;
column2: string;
column3: string;
column4: string;
}
class UpdateTournamentColumnsInitializedFlagService {
public async execute(
id_tournament: string,
flag: string,
): Promise<TournamentColumns> {
const tournamentsRepository = getRepository(Tournament);
const tournamentColumnsRepository = getRepository(TournamentColumns);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentColumns = await tournamentColumnsRepository.findOne({
where: { tournament },
});
if (!tournamentColumns) {
throw new AppError('Tournament does not have columns.');
}
if (flag) tournamentColumns.tournament_initialized = true;
else tournamentColumns.tournament_initialized = false;
await tournamentColumnsRepository.save(tournamentColumns);
return tournamentColumns;
}
}
export default UpdateTournamentColumnsInitializedFlagService;

View File

@@ -0,0 +1,50 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
import TournamentColumns from '../models/TournamentColumns';
interface Columns {
column1: string;
column2: string;
column3: string;
column4: string;
}
class UpdateTournamentColumnsService {
public async execute(
id_tournament: string,
{ column1, column2, column3, column4 }: Columns,
): Promise<TournamentColumns> {
const tournamentsRepository = getRepository(Tournament);
const tournamentColumnsRepository = getRepository(TournamentColumns);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentColumns = await tournamentColumnsRepository.findOne({
where: { tournament },
});
if (!tournamentColumns) {
throw new AppError('Tournament does not have columns.');
}
tournamentColumns.column1 = column1;
tournamentColumns.column2 = column2;
tournamentColumns.column3 = column3;
tournamentColumns.column4 = column4;
await tournamentColumnsRepository.save(tournamentColumns);
return tournamentColumns;
}
}
export default UpdateTournamentColumnsService;

View File

@@ -0,0 +1,44 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import Tournament from '../models/Tournament';
interface Request {
id: string;
name: string;
game: string;
description: string;
password: string;
}
class UpdateTournamentService {
public async execute({
id,
name,
game,
description,
password,
}: Request): Promise<Tournament> {
const tournamentsRepository = getRepository(Tournament);
const tournament = await tournamentsRepository.findOne({
where: { id_tournament: id },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
tournament.name = name;
tournament.game = game;
tournament.description = description;
if (!!password) tournament.password = password;
await tournamentsRepository.save(tournament);
return tournament;
}
}
export default UpdateTournamentService;

View File

@@ -0,0 +1,57 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Tournament from '../models/Tournament';
import TournamentParticipant from '../models/TournamentParticipant';
interface Request {
id_tournament: string;
id_user: string;
}
class UpdateTournamentsInviteUserAcceptedService {
public async execute({
id_tournament,
id_user,
}: Request): Promise<TournamentParticipant> {
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const TournamentParticipantsRepository = getRepository(
TournamentParticipant,
);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentInvite = await TournamentParticipantsRepository.findOne({
where: { tournament, user, user_accepted_invite: false },
});
if (!tournamentInvite) {
throw new AppError('User is not invited to this tournament.');
}
tournamentInvite.user_accepted_invite = true;
await TournamentParticipantsRepository.save(tournamentInvite);
return tournamentInvite;
}
}
export default UpdateTournamentsInviteUserAcceptedService;

View File

@@ -0,0 +1,57 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Tournament from '../models/Tournament';
import TournamentParticipant from '../models/TournamentParticipant';
interface Request {
id_tournament: string;
id_user: string;
}
class UpdateTournamentsInviteUserRefusedService {
public async execute({
id_tournament,
id_user,
}: Request): Promise<TournamentParticipant> {
const usersRepository = getRepository(User);
const tournamentsRepository = getRepository(Tournament);
const TournamentParticipantsRepository = getRepository(
TournamentParticipant,
);
const user = await usersRepository.findOne({
where: { id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const tournament = await tournamentsRepository.findOne({
where: { id_tournament },
});
if (!tournament) {
throw new AppError('Tournament does not exist.');
}
const tournamentInvite = await TournamentParticipantsRepository.findOne({
where: { tournament, user, user_accepted_invite: false },
});
if (!tournamentInvite) {
throw new AppError('User is not invited to this tournament.');
}
tournamentInvite.invite_refused = true;
await TournamentParticipantsRepository.save(tournamentInvite);
return tournamentInvite;
}
}
export default UpdateTournamentsInviteUserRefusedService;

View File

@@ -0,0 +1,34 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
id_user: string;
avatar_image: string;
}
class UpdateUserAvatarService {
public async execute({ id_user, avatar_image }: Request): Promise<User> {
const usersRepository = getRepository(User);
const socialRepository = getRepository(Social);
const user = await usersRepository.findOne({
where: { id_user: id_user }
});
if (!user) {
throw new AppError('User does not exist.');
};
user.avatar_image = avatar_image;
await usersRepository.save(user);
return user;
}
}
export default UpdateUserAvatarService;

View File

@@ -0,0 +1,34 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
id_user: string;
background_image: string;
}
class UpdateUserBackgroundService {
public async execute({ id_user, background_image }: Request): Promise<User> {
const usersRepository = getRepository(User);
const socialRepository = getRepository(Social);
const user = await usersRepository.findOne({
where: { id_user: id_user }
});
if (!user) {
throw new AppError('User does not exist.');
};
user.background_image = background_image;
await usersRepository.save(user);
return user;
}
}
export default UpdateUserBackgroundService;

View File

@@ -0,0 +1,43 @@
import { getRepository } from 'typeorm';
import { hash, compare } from 'bcryptjs';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
id_user: string;
quantity: number;
operation: 'add' | 'remove';
}
class UpdateUserCoinsService {
public async execute({
id_user,
quantity,
operation,
}: Request): Promise<User> {
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const userCoinsAsNumber = parseInt(user.coins);
if (operation == 'add')
user.coins = (userCoinsAsNumber + quantity).toString();
else user.coins = (userCoinsAsNumber - quantity).toString();
await usersRepository.save(user);
return user;
}
}
export default UpdateUserCoinsService;

View File

@@ -0,0 +1,44 @@
import { getRepository } from 'typeorm';
import { hash, compare } from 'bcryptjs';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
id_user: string;
password_old: string;
password_new: string;
}
class UpdateUserService {
public async execute({ id_user, password_old, password_new }: Request): Promise<User> {
const usersRepository = getRepository(User);
const user = await usersRepository.findOne({
where: { id_user: id_user }
});
// TODO, notar que isso é necessário
// tentar remover que o TypeScript apontará como erro
if (!user) {
throw new AppError('User does not exist.');
};
// TODO, padronizar mensagens em PT-BR
const passwordMatched = await compare(password_old, user.password);
if (!passwordMatched) throw new AppError("Senha atual incorreta.", 200);
const hashedNewPassword = await hash(password_new, 8);
user.password = hashedNewPassword;
await usersRepository.save(user);
return user;
}
}
export default UpdateUserService;

View File

@@ -0,0 +1,41 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
id_user: string;
name: string;
username: string;
bio: string;
email: string;
birth_date: string;
}
class UpdateUserService {
public async execute({ id_user, name, username, bio, email, birth_date }: Request): Promise<User> {
const usersRepository = getRepository(User);
const socialRepository = getRepository(Social);
const user = await usersRepository.findOne({
where: { id_user: id_user }
});
if (!user) {
throw new AppError('User does not exist.');
};
user.name = name;
user.username = username;
user.bio = bio;
user.birth_date = new Date(birth_date); // TODO, funciona?
await usersRepository.save(user);
return user;
}
}
export default UpdateUserService;

View File

@@ -0,0 +1,61 @@
import { getRepository } from 'typeorm';
import AppError from '../errors/AppError';
import User from '../models/User';
import Social from '../models/Social';
interface Request {
id_user: string;
social_network: string;
username: string;
}
class UpdateUserSocialService {
public async execute({
id_user,
social_network,
username,
}: Request): Promise<Social> {
const usersRepository = getRepository(User);
const socialRepository = getRepository(Social);
const user = await usersRepository.findOne({
where: { id_user: id_user },
});
if (!user) {
throw new AppError('User does not exist.');
}
const social = await socialRepository.findOne({
where: { user: user },
});
if (!social) throw new AppError('User does not exist.');
switch (social_network) {
case 'telegram':
social.telegram = username;
break;
case 'facebook':
social.facebook = username;
break;
case 'twitter':
social.twitter = username;
break;
case 'twitch':
social.twitch = username;
break;
default:
break;
}
await socialRepository.save(social);
return social;
}
}
export default UpdateUserSocialService;

70
tsconfig.json Normal file
View File

@@ -0,0 +1,70 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
"strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}

1652
yarn-error.log Normal file

File diff suppressed because it is too large Load Diff

1594
yarn.lock Normal file

File diff suppressed because it is too large Load Diff