auths.py 5.62 KB
Newer Older
1
from fastapi import Response, Request
2
3
4
5
from fastapi import Depends, FastAPI, HTTPException, status
from datetime import datetime, timedelta
from typing import List, Union

6
from fastapi import APIRouter, status
7
8
9
10
11
12
13
from pydantic import BaseModel
import time
import uuid

from apps.web.models.auths import (
    SigninForm,
    SignupForm,
14
    UpdateProfileForm,
15
    UpdatePasswordForm,
16
17
18
19
20
21
    UserResponse,
    SigninResponse,
    Auths,
)
from apps.web.models.users import Users

Timothy J. Baek's avatar
Timothy J. Baek committed
22
23
24
25
26
27
from utils.utils import (
    get_password_hash,
    get_current_user,
    get_admin_user,
    create_token,
)
28
from utils.misc import get_gravatar_url, validate_email_format
Timothy J. Baek's avatar
Timothy J. Baek committed
29
from constants import ERROR_MESSAGES
30

Timothy J. Baek's avatar
Timothy J. Baek committed
31
32
router = APIRouter()

33
34
35
36
37
############################
# GetSessionUser
############################


38
@router.get("/", response_model=UserResponse)
39
40
41
42
43
44
45
46
async def get_session_user(user=Depends(get_current_user)):
    return {
        "id": user.id,
        "email": user.email,
        "name": user.name,
        "role": user.role,
        "profile_image_url": user.profile_image_url,
    }
47
48


49
############################
50
# Update Profile
51
52
53
54
############################


@router.post("/update/profile", response_model=UserResponse)
55
56
async def update_profile(
    form_data: UpdateProfileForm, session_user=Depends(get_current_user)
57
58
):
    if session_user:
59
60
61
        user = Users.update_user_by_id(
            session_user.id,
            {"profile_image_url": form_data.profile_image_url, "name": form_data.name},
62
63
64
65
66
67
68
69
70
        )
        if user:
            return user
        else:
            raise HTTPException(400, detail=ERROR_MESSAGES.DEFAULT())
    else:
        raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)


71
72
73
74
75
############################
# Update Password
############################


76
@router.post("/update/password", response_model=bool)
77
78
79
async def update_password(
    form_data: UpdatePasswordForm, session_user=Depends(get_current_user)
):
80
81
    if session_user:
        user = Auths.authenticate_user(session_user.email, form_data.password)
82

83
84
        if user:
            hashed = get_password_hash(form_data.new_password)
Timothy J. Baek's avatar
Timothy J. Baek committed
85
            return Auths.update_user_password_by_id(user.id, hashed)
86
87
        else:
            raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_PASSWORD)
88
89
90
91
    else:
        raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)


92
93
94
95
96
97
98
99
100
############################
# SignIn
############################


@router.post("/signin", response_model=SigninResponse)
async def signin(form_data: SigninForm):
    user = Auths.authenticate_user(form_data.email.lower(), form_data.password)
    if user:
101
        token = create_token(data={"id": user.id})
102
103
104
105
106
107
108
109

        return {
            "token": token,
            "token_type": "Bearer",
            "id": user.id,
            "email": user.email,
            "name": user.name,
            "role": user.role,
Timothy J. Baek's avatar
Timothy J. Baek committed
110
            "profile_image_url": user.profile_image_url,
111
112
        }
    else:
Timothy J. Baek's avatar
Timothy J. Baek committed
113
        raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
114
115
116
117
118
119
120
121


############################
# SignUp
############################


@router.post("/signup", response_model=SigninResponse)
122
async def signup(request: Request, form_data: SignupForm):
123
    if not request.app.state.ENABLE_SIGNUP:
Timothy J. Baek's avatar
Timothy J. Baek committed
124
125
126
        raise HTTPException(
            status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED
        )
127

128
    if not validate_email_format(form_data.email.lower()):
Timothy J. Baek's avatar
Timothy J. Baek committed
129
130
131
        raise HTTPException(
            status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.INVALID_EMAIL_FORMAT
        )
132

133
134
    if Users.get_user_by_email(form_data.email.lower()):
        raise HTTPException(400, detail=ERROR_MESSAGES.EMAIL_TAKEN)
135

136
    try:
Timothy J. Baek's avatar
Timothy J. Baek committed
137
138
139
140
141
        role = (
            "admin"
            if Users.get_num_users() == 0
            else request.app.state.DEFAULT_USER_ROLE
        )
142
        hashed = get_password_hash(form_data.password)
143
144
145
        user = Auths.insert_new_auth(
            form_data.email.lower(), hashed, form_data.name, role
        )
146

147
        if user:
148
            token = create_token(data={"id": user.id})
149
150
151
152
153
154
155
156
157
158
159
160
            # response.set_cookie(key='token', value=token, httponly=True)

            return {
                "token": token,
                "token_type": "Bearer",
                "id": user.id,
                "email": user.email,
                "name": user.name,
                "role": user.role,
                "profile_image_url": user.profile_image_url,
            }
        else:
161
            raise HTTPException(500, detail=ERROR_MESSAGES.CREATE_USER_ERROR)
162
    except Exception as err:
163
164
        raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err))

165
166
167
168
169
170
171

############################
# ToggleSignUp
############################


@router.get("/signup/enabled", response_model=bool)
172
173
async def get_sign_up_status(request: Request, user=Depends(get_admin_user)):
    return request.app.state.ENABLE_SIGNUP
174
175
176


@router.get("/signup/enabled/toggle", response_model=bool)
177
178
179
async def toggle_sign_up(request: Request, user=Depends(get_admin_user)):
    request.app.state.ENABLE_SIGNUP = not request.app.state.ENABLE_SIGNUP
    return request.app.state.ENABLE_SIGNUP
Timothy J. Baek's avatar
Timothy J. Baek committed
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202


############################
# Default User Role
############################


@router.get("/signup/user/role")
async def get_default_user_role(request: Request, user=Depends(get_admin_user)):
    return request.app.state.DEFAULT_USER_ROLE


class UpdateRoleForm(BaseModel):
    role: str


@router.post("/signup/user/role")
async def update_default_user_role(
    request: Request, form_data: UpdateRoleForm, user=Depends(get_admin_user)
):
    if form_data.role in ["pending", "user", "admin"]:
        request.app.state.DEFAULT_USER_ROLE = form_data.role
    return request.app.state.DEFAULT_USER_ROLE