diff --git a/README.md b/README.md
index 5353dd5..921a526 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,52 @@
-# 2023.2-UnB-TV-Users
-Repositório de Backend
+# UnB-TV Users
+
+
+
+
+## Sobre
+
+O projeto visa o desenvolvimento de uma aplicação Web e Mobile para a UnB-TV, com o objetivo de centralizar e disponibilizar de forma unificada todo o conteúdo oferecido pela UnB-TV, incluindo vídeos e transmissões ao vivo, sendo desenvolvida no segundo semestre de 2023 pelas disciplinas de EPS e MDS da Universidade de Brasília.
+
+## Ambientes
+
+[Documentação](https://github.com/fga-eps-mds/2023.2-UnB-TV-DOC)
+[Users](https://github.com/fga-eps-mds/2023.2-UnB-TV-Users)
+[Admin](https://github.com/fga-eps-mds/2023.2-UnB-TV-Admin)
+[Video](https://github.com/fga-eps-mds/2023.2-UnB-TV-VideoService)
+[Gateway](https://github.com/fga-eps-mds/2023.2-UnB-TV-API-Gateway)
+[Frontend](https://github.com/fga-eps-mds/2023.2-UnB-TV-Frontend)
+
+## Acessando o repositório localmente
+
+### Requisitos
+
+- docker e docker compose
+
+Primeiro passo é instalar o docker e docker compose, para isso siga os passos de instalação do [docker](https://docs.docker.com/engine/install/) e [docker compose](https://docs.docker.com/compose/install/).
+
+Execute o servidor local:
+
+```
+docker compose up
+```
+
+Acessar o localhost em: http://localhost:8000
+
+## Equipe
+
+| Foto | Nome | Github | Email | Matrícula |
+| :-----------------------------------------------------------------------------------------------------------------------------: | :-------------------------------: | :----------------: | :----------------------------: | :-------: |
+| | Davi Marinho da Silva Campos | @DaviMarinho | davii_marinho@hotmail.com | 190026600 |
+| | Diego Carlito Rodrigues de Souza | @Diego-Carlito | <221007690@aluno.unb.br> | 221007690 |
+| | Eric Akio Lages Nishimura | @eric-kingu | <190105895@aluno.unb.br> | 190105895 |
+| | Gabriela Tiago de Araujo | @GabrielaTiago | <190028475@aluno.unb.br> | 190028475 |
+| | Gabrielle Ribeiro Gomes | @Gabrielle-Ribeiro | gabrielleribeiro2010@gmail.com | 170011020 |
+| | Geraldo Victor Alves Barbosa | @geraldovictor | geraldovictor@outlook.com | 170011119 |
+| | Jennifer Costa Cansanção | @cansancaojennifer | <221007733@aluno.unb.br> | 221007733 |
+| | João Victor de Oliveira Matos | @joao15victor08 | joao15victor08@gmail.com | 170013987 |
+| | Lucas da Cunha Andrade | @nYCSTs | lucascandrade14@hotmail.com | 180105256 |
+| | Marcos Antonio Teles de Castilhos | @Marcosatc147 | <221008300@aluno.unb.br> | 221008300 |
+| | Raissa Andrade Silveira | @RaisSabeAndrade | <221035077@aluno.unb.br> | 221035077 |
+| | Ricardo de Castro Loureiro | @castroricardo1 | ricardoloureiro75@gmail.com | 200043111 |
+| | Sávio Cunha de Carvalho | @savioc2 | saviocunha61@gmail.com | 180130889 |
+| | Vitória Aquere Matos | @vitoriaaquere | <190096616@aluno.unb.br> | 190096616 |
diff --git a/sonar-project.properties b/sonar-project.properties
index fe0902d..9e26314 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -1,13 +1,14 @@
sonar.projectKey=fga-eps-mds_2023.2-UnB-TV-Users
sonar.organization=fga-eps-mds-1
-sonar.sources=src
-sonar.tests=tests
-# sonar.test.inclusions=tests/*.py
-sonar.exclusions=__pycache__, tests
-# sonar.testExecutionReportPaths
-sonar.sourceEncoding=UTF-8
+sonar.host.url=https://sonarcloud.io
+sonar.language=py
+sonar.sources=src
+sonar.exclusions=tests
sonar.python.version=3.11.5
sonar.python.xunit.reportPath=junit.xml
-sonar.python.coverage.reportPaths=coverage.xml
\ No newline at end of file
+sonar.python.coverage.reportPaths=coverage.xml
+sonar.coverage.exclusions=tests/*.py
+
+sonar.sourceEncoding=UTF-8
\ No newline at end of file
diff --git a/src/controller/authController.py b/src/controller/authController.py
index 236fc87..1cc8d7f 100644
--- a/src/controller/authController.py
+++ b/src/controller/authController.py
@@ -15,6 +15,7 @@
prefix="/auth"
)
+ # Retorna conexões disponíveis
@auth.get("/vinculo", response_model=authSchema.Connections)
def get_connection():
connections = [member.value for member in enumeration.UserConnection]
@@ -46,6 +47,7 @@ async def register(data: authSchema.UserCreate, db: Session = Depends(get_db)):
return JSONResponse(status_code=201, content={ "status": "success" })
+ # Recebe os dados de login
@auth.post("/login", response_model=authSchema.Token)
async def login(data: authSchema.UserLogin, db: Session = Depends(get_db)):
user = userRepository.get_user_by_email(db, data.email)
@@ -64,6 +66,7 @@ async def login(data: authSchema.UserLogin, db: Session = Depends(get_db)):
return JSONResponse(status_code=200, content={ "access_token": access_token, "refresh_token": refresh_token, "token_type": "bearer" })
+ # Recebe os dados do usuário provenientes de uma autenticação social
@auth.post("/login/social")
async def login_social(user: authSchema.UserSocial, db: Session = Depends(get_db)):
existing_user = userRepository.get_user_by_email(db, user.email)
@@ -86,7 +89,8 @@ async def login_social(user: authSchema.UserSocial, db: Session = Depends(get_db
"is_new_user": is_new_user,
"user_id": user_id
})
-
+
+ # trata da renovação de tokens de acesso
@auth.post("/refresh", response_model=authSchema.RefreshTokenResponse)
def refresh_token(token: dict = Depends(security.verify_token)):
access_token=security.create_access_token(token)
@@ -104,6 +108,7 @@ async def send_new_code(data: authSchema.SendNewCode, db: Session = Depends(get_
res = await send_mail.send_verification_code(email=data.email, code=user.activation_code)
return JSONResponse(status_code=201, content={ "status": "success" })
+ # Recebe dados de validação de conta
@auth.patch('/activate-account')
async def validate_account(data: authSchema.AccountValidation, db: Session = Depends(get_db)):
user = userRepository.get_user_by_email(db, data.email)
@@ -148,21 +153,26 @@ async def verify_reset_code(data: authSchema.ResetPasswordVerify, db: Session =
return JSONResponse(status_code=200, content={ "status": "success" })
+ # Atualizar senha de um usuário após uma solicitação de redefinição
@auth.patch('/reset-password/change', response_model=userSchema.User)
async def update_user_password(data: authSchema.ResetPasswordUpdate, db: Session = Depends(get_db)):
user = userRepository.get_user_by_email(db, data.email)
if not user:
raise HTTPException(status_code=404, detail=errorMessages.USER_NOT_FOUND)
+ # Valida a senha informada
if data.password and not security.validate_password(data.password):
raise HTTPException(status_code=400, detail=errorMessages.INVALID_PASSWORD)
+ # Verifica se o usuario possui um reset code. Se não possuir, a solicitação é invalida e deve ser bloqueada
if not user.password_reset_code:
raise HTTPException(status_code=401, detail=errorMessages.INVALID_REQUEST)
-
+
+ # Verifica se o código corresponde
if data.code != user.password_reset_code:
raise HTTPException(status_code=400, detail=errorMessages.INVALID_RESET_PASSWORD_CODE)
+ # Faz procedimento de hash da senha e atualiza usuario
hashed_password = security.get_password_hash(data.password)
updated_user = userRepository.update_password(db, user, hashed_password)
diff --git a/src/controller/userController.py b/src/controller/userController.py
index 21756b9..da27673 100644
--- a/src/controller/userController.py
+++ b/src/controller/userController.py
@@ -71,6 +71,8 @@ async def delete_user(user_id: int, db: Session = Depends(get_db), token: dict =
@user.patch("/role/{user_id}", response_model=userSchema.User)
def update_role(user_id: int, db: Session = Depends(get_db), token: dict = Depends(security.verify_token)):
+ # Obtem email do usuario a partir de token.
+ # Verifica se o usuário é ADMIN
user = userRepository.get_user_by_email(db, email=token['email'])
if user.role != enumeration.UserRole.ADMIN.value:
raise HTTPException(status_code=401, detail=errorMessages.NO_PERMISSION)
@@ -81,6 +83,7 @@ def update_role(user_id: int, db: Session = Depends(get_db), token: dict = Depen
if not user:
raise HTTPException(status_code=404, detail=errorMessages.USER_NOT_FOUND)
+ # Obtem o valor da outra role e atribui a outra role para o usuario. Caso ele seja um USER => ADMIN, caso seja ADMIN => USER
new_role = enumeration.UserRole.ADMIN.value if user.role == enumeration.UserRole.USER.value else enumeration.UserRole.USER.value
user = userRepository.update_user_role(db, db_user=user, role=new_role)
diff --git a/src/repository/userRepository.py b/src/repository/userRepository.py
index b6313d9..7422d77 100644
--- a/src/repository/userRepository.py
+++ b/src/repository/userRepository.py
@@ -7,12 +7,25 @@
from domain import userSchema
from model import userModel
+# Obtem usuario a partir do seu ID
def get_user(db: Session, user_id: int):
return db.query(userModel.User).filter(userModel.User.id == user_id).first()
+# Obtem usuario a partir do Email
def get_user_by_email(db: Session, email: str):
return db.query(userModel.User).filter(userModel.User.email == email).first()
+'''
+Obtem lista de usuarios. Possui filtragem:
+Filtros:
+name: filtrar por nome do usuario
+email: filtrar por email do usuario
+name_or_email: filtragem que aceita tanto nome quanto email (OR)
+connection: filtragem pelo vinculo do usuario
+
+Também aceita offset e limit. Para offset pula a quantidade informada,
+para o limit, controla a quantidade de usuarios retornada
+'''
def get_users(db: Session, users_filter: userSchema.UserListFilter):
query = db.query(userModel.User)
@@ -26,15 +39,20 @@ def get_users(db: Session, users_filter: userSchema.UserListFilter):
if (users_filter.connection):
query = query.filter(userModel.User.connection == users_filter.connection)
+ # Realiza o count para retornar para o front para realizar paginação
total_count = query.count()
+ # Ordena a lista de usuarios por ordem alfabetica pelo nome
query = query.order_by(userModel.User.name.asc())
+ # Realiza a delimitação por offset
if (users_filter.offset):
query = query.offset(users_filter.offset)
+ # Realiza a limitação por quantidade retornada
if (users_filter.limit):
query = query.limit(users_filter.limit)
+ # Retorna todos os usuarios filtrados, dentro de eventuais limitações (offset ou limit) e o total (geral)
return { "users": query.all(), "total": total_count }
def create_user(db: Session, name, connection, email, password, activation_code):
@@ -44,6 +62,7 @@ def create_user(db: Session, name, connection, email, password, activation_code)
db.refresh(db_user)
return db_user
+# Cria um usuario por login social. Essa criação é especial pois o usuario criado por rede social não possui SENHA
def create_user_social(db: Session, name, email):
db_user = userModel.User(
name=name,