Skip to content

Commit

Permalink
Merge branch 'develop' into fix-login-social
Browse files Browse the repository at this point in the history
  • Loading branch information
castroricardo1 authored Dec 11, 2023
2 parents f10e722 + 1cac684 commit 048d07a
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 11 deletions.
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,52 @@
# 2023.2-UnB-TV-Users
Repositório de Backend
# UnB-TV Users

<div align="center">
<img src="./docs/assets/unb-removebg-preview.png" alt="logo UNBTV"> </div>

## 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 |
| :-----------------------------------------------------------------------------------------------------------------------------: | :-------------------------------: | :----------------: | :----------------------------: | :-------: |
| <img width="100px" style="border-radius:10%" src="https://github.com/DaviMarinho.png" alt="Davi Marinho da Silva Campos"> | Davi Marinho da Silva Campos | @DaviMarinho | [email protected] | 190026600 |
| <img width="100px" style="border-radius:10%" src="https://github.com/Diego-Carlito.png" alt="Diego Carlito Rodrigues de Souza"> | Diego Carlito Rodrigues de Souza | @Diego-Carlito | <[email protected]> | 221007690 |
| <img width="100px" style="border-radius:10%" src="https://github.com/eric-kingu.png" alt="Eric Akio Lages Nishimura"> | Eric Akio Lages Nishimura | @eric-kingu | <[email protected]> | 190105895 |
| <img width="100px" style="border-radius:10%" src="https://github.com/GabrielaTiago.png" alt="Gabriela Tiago de Araujo"> | Gabriela Tiago de Araujo | @GabrielaTiago | <[email protected]> | 190028475 |
| <img width="100px" style="border-radius:10%" src="https://github.com/Gabrielle-Ribeiro.png" alt="Gabrielle Ribeiro Gomes"> | Gabrielle Ribeiro Gomes | @Gabrielle-Ribeiro | [email protected] | 170011020 |
| <img width="100px" style="border-radius:10%" src="https://github.com/geraldovictor.png" alt="Geraldo Victor Alves Barbosa"> | Geraldo Victor Alves Barbosa | @geraldovictor | [email protected] | 170011119 |
| <img width="100px" style="border-radius:10%" src="https://github.com/cansancaojennifer.png" alt="Jennifer Costa Cansanção"> | Jennifer Costa Cansanção | @cansancaojennifer | <[email protected]> | 221007733 |
| <img width="100px" style="border-radius:10%" src="https://github.com/joao15victor08.png" alt="Jennifer Costa Cansanção"> | João Victor de Oliveira Matos | @joao15victor08 | [email protected] | 170013987 |
| <img width="100px" style="border-radius:10%" src="https://github.com/nYCSTs.png" alt="Lucas da Cunha Andrade"> | Lucas da Cunha Andrade | @nYCSTs | [email protected] | 180105256 |
| <img width="100px" style="border-radius:10%" src="https://github.com/Marcosatc147.png" alt="Marcos Antonio Teles de Castilhos"> | Marcos Antonio Teles de Castilhos | @Marcosatc147 | <[email protected]> | 221008300 |
| <img width="100px" style="border-radius:10%" src="https://github.com/RaisSabeAndrade.png" alt="Raissa Andrade Silveira"> | Raissa Andrade Silveira | @RaisSabeAndrade | <[email protected]> | 221035077 |
| <img width="100px" style="border-radius:10%" src="https://github.com/castroricardo1.png" alt="Ricardo de Castro Loureiro"> | Ricardo de Castro Loureiro | @castroricardo1 | [email protected] | 200043111 |
| <img width="100px" style="border-radius:10%" src="https://github.com/savioc2.png" alt="Ana Carolina Rodrigues Leite"> | Sávio Cunha de Carvalho | @savioc2 | [email protected] | 180130889 |
| <img width="100px" style="border-radius:10%" src="https://github.com/vitoriaaquere.png" alt="Vitória Aquere Matos"> | Vitória Aquere Matos | @vitoriaaquere | <[email protected]> | 190096616 |
15 changes: 8 additions & 7 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -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
sonar.python.coverage.reportPaths=coverage.xml
sonar.coverage.exclusions=tests/*.py

sonar.sourceEncoding=UTF-8
14 changes: 12 additions & 2 deletions src/controller/authController.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)

Expand Down
3 changes: 3 additions & 0 deletions src/controller/userController.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)

Expand Down
19 changes: 19 additions & 0 deletions src/repository/userRepository.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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):
Expand All @@ -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,
Expand Down

0 comments on commit 048d07a

Please sign in to comment.