File size: 4,736 Bytes
b39c0ba
 
 
d57efd6
 
b39c0ba
 
 
 
d57efd6
 
 
 
9002555
 
 
 
d57efd6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b39c0ba
 
 
 
 
 
d57efd6
 
 
 
 
 
b39c0ba
d57efd6
 
 
 
 
b39c0ba
d57efd6
 
b39c0ba
d57efd6
 
 
 
 
 
 
 
 
 
b39c0ba
d57efd6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9002555
 
 
d57efd6
 
 
 
 
 
b39c0ba
d57efd6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9002555
 
 
 
d57efd6
9002555
d57efd6
 
 
 
b39c0ba
d57efd6
 
 
 
 
b39c0ba
d57efd6
 
 
 
 
 
b39c0ba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from datetime import timedelta
from typing import Annotated

from fastapi import APIRouter, Depends, status
from fastapi.responses import JSONResponse
from fastapi.security import OAuth2PasswordRequestForm
from passlib.context import CryptContext
from sqlalchemy.orm import Session

from db.models import User
from db.database import get_db
from api.auth import get_current_user, create_access_token
from service.dto import CreateUserRequest, UserVerification, Token


router = APIRouter(tags=["User"])

bcrypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

db_dependency = Annotated[Session, Depends(get_db)]
user_dependency = Annotated[dict, Depends(get_current_user)]

ACCESS_TOKEN_EXPIRE_MINUTES = 43200


@router.post("/login", response_model=Token)
async def login_for_access_token(
    login_data: Annotated[OAuth2PasswordRequestForm, Depends()],
    db: Session = Depends(get_db),
):
    user = db.query(User).filter(User.username == login_data.username).first()

    if not user or not bcrypt_context.verify(login_data.password, user.password_hash):
        return JSONResponse(
            status_code=status.HTTP_401_UNAUTHORIZED,
            content="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )

    try:
        access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
        access_token = create_access_token(
            user.username,
            user.name,
            user.id,
            user.role_id,
            access_token_expires,
            user.email,
        )

        return {"access_token": access_token, "token_type": "bearer"}

    except Exception as e:
        print(e)
        return JSONResponse(status_code=500, content="An error occuring when login")


@router.get("/login", response_model=dict)
async def get_user(user: user_dependency):
    if user is None:
        return JSONResponse(status_code=401, content="Authentication Failed")
    return {
        "username": user.get("username"),
        "name": user.get("name"),
        "id": user.get("id"),
        "email": user.get("email"),
        "role": user.get("role_id"),
    }


@router.get("/users", response_model=list[dict])
async def get_all_users(user: user_dependency, db: Session = Depends(get_db)):
    # Check if the current user has an admin role
    if user.get("role_id") != 1:  # Adjust this check based on how roles are represented
        return JSONResponse(status_code=401, content="Authentication Failed")

    # Query the database to retrieve all users
    users = db.query(
        User
    ).all()  # Assuming you have a User model with an SQLAlchemy session
    return [
        {
            "id": user.id,
            "username": user.username,
            "name": user.name,
            "email": user.email,
            "role": user.role_id,
        }
        for user in users
    ]


@router.post("/register")
async def register_user(db: db_dependency, create_user_request: CreateUserRequest):
    existing_user = (
        db.query(User).filter(User.email == create_user_request.email).first()
    )

    if existing_user:
        return JSONResponse(status_code=400, content="Email is already registered")

    try:
        password_hash = bcrypt_context.hash(create_user_request.password)

        create_user_model = User(
            name=create_user_request.name,
            username=create_user_request.username,
            email=create_user_request.email,
            role_id=create_user_request.role_id,
            password_hash=password_hash,
        )

        db.add(create_user_model)
        db.commit()
        db.refresh(create_user_model)

        return {"message": "User created successfully", "user_id": create_user_model.id}
    except Exception as e:
        print(e)
        return JSONResponse(
            status_code=500, content="An error occuring when register user"
        )


@router.post("/forgot_password")
async def forget_password():
    pass


@router.post("/change_password")
async def change_password(
    user: user_dependency, db: db_dependency, user_verification: UserVerification
):
    if user is None:
        return JSONResponse(status_code=401, content="Authentication Failed")
    user_model = db.query(User).filter(User.id == user.get("id")).first()

    if not bcrypt_context.verify(
        user_verification.password, user_model.hashed_password
    ):
        return JSONResponse(status_code=401, content="Error on password change")

    user_model.hashed_password = bcrypt_context.hash(user_verification.new_password)
    db.add(user_model)
    db.commit()
    db.refresh(user_model)

    return {"message": "User's password successfully changed", "user_id": user_model.id}