Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAJOR RELEASE #22

Merged
merged 9 commits into from
Dec 11, 2023
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 @@ -78,7 +81,8 @@ async def login_social(user: authSchema.UserSocial, db: Session = Depends(get_db
refresh_token = security.create_refresh_token(data={ "id": existing_user.id })

return JSONResponse(status_code=200, content={ "access_token": access_token, "refresh_token": refresh_token, "token_type": "bearer", "is_new_user": False })


# 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 @@ -96,6 +100,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 @@ -140,21 +145,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
Loading