Projekt

Obecné

Profil

Stáhnout (6.96 KB) Statistiky
| Větev: | Tag: | Revize:
1
from fastapi import Depends, APIRouter, Form
2
from fastapi import Request
3
from fastapi.responses import HTMLResponse, RedirectResponse
4
from fastapi.templating import Jinja2Templates
5
from fastapi_jwt_auth import AuthJWT
6
from sqlalchemy.orm import Session
7
from sql_app import crud
8
from passlib.context import CryptContext
9
from pydantic import BaseModel
10
from ..database import SessionLocal, engine
11

    
12
# Path to html templates used in this file
13
templates = Jinja2Templates(directory="templates/auth")
14

    
15
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
16

    
17
# prefix used for all endpoints in this file
18
auth = APIRouter(prefix="")
19

    
20

    
21
# Dependency
22
def get_db():
23
    db = SessionLocal()
24
    try:
25
        yield db
26
    finally:
27
        db.close()
28

    
29

    
30
class Settings(BaseModel):
31
    authjwt_secret_key: str = "secret"
32
    # Configure application to store and get JWT from cookies
33
    authjwt_token_location: set = {"cookies"}
34
    # Disable CSRF Protection for this example. default is True
35
    authjwt_cookie_csrf_protect: bool = False
36

    
37

    
38
@AuthJWT.load_config
39
def get_config():
40
    return Settings()
41

    
42

    
43
# admin username and password
44
fake_users_db = {
45
    "admin": {
46
        "username": "admin",
47
        "password": "admin"
48
    }
49
}
50

    
51

    
52
def verify_password(plain_password, hashed_password):
53
    return pwd_context.verify(plain_password, hashed_password)
54

    
55

    
56
def get_hash_password(password):
57
    return pwd_context.hash(password)
58

    
59

    
60
def auth_user(db, username: str, password: str):
61
    user = crud.find_user(db, username)
62
    if not user:
63
        return None
64
    if not verify_password(password, user.password):
65
        return None
66
    return user
67

    
68

    
69
@auth.get("/signup", response_class=HTMLResponse)
70
async def signup_get(request: Request):
71
    """
72
    return html template for signup
73
    """
74
    return templates.TemplateResponse("signup.html", {"request": request})
75

    
76

    
77
@auth.post("/signup", response_class=HTMLResponse)
78
async def signup(username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db)):
79
    """
80
    Endpoint called form signup template. Creates new user with role guest that can be changed by admin user
81
    """
82
    users = crud.get_users(db, 0, 100)
83
    users_names = []
84
    for u in users:
85
        users_names.append(u.username)
86
    if username not in users_names:
87
        new_user = crud.create_user(db, username, get_hash_password(password), "guest")
88
        if new_user is None:
89
            print("something went wrong")
90
        return """
91
            <html>
92
                <head>
93
                    <title>Signup</title>
94
                </head>
95
                <body>
96
                    <h1>New user created. You can go back to previous page.</h1>
97
                    <form action="/logs-web" method="get">
98
                        <input type="submit" value="Home Page" />
99
                    </form>
100
                </body>
101
            </html>
102
            """
103
    else:
104
        return """
105
                    <html>
106
                        <head>
107
                            <title>Signup</title>
108
                        </head>
109
                        <body>
110
                            <h1>Username taken. Try to choose different username.</h1>
111
                            <form action="/logs-web" method="get">
112
                                <input type="submit" value="Home Page" />
113
                            </form>
114
                        </body>
115
                    </html>
116
                    """
117

    
118
@auth.get("/login", response_class=HTMLResponse)
119
async def login_get(request: Request):
120
    """
121
    return html template for login
122
    """
123
    return templates.TemplateResponse("login.html", {"request": request})
124

    
125

    
126
@auth.post("/login", response_class=HTMLResponse)
127
async def login(username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db),
128
                Authorize: AuthJWT = Depends()):
129
    """
130
    Endpoint called from login template. Checks if given username and password aligns with admin
131
    username and password and returns token for browser according to given username and password
132
    """
133
    user = auth_user(db, username, password)
134
    if user != None:
135
        if user.role == "admin":
136
            access_token = Authorize.create_access_token(subject="admin", expires_time=False)
137
            refresh_token = Authorize.create_refresh_token(subject="admin", expires_time=False)
138
        else:
139
            access_token = Authorize.create_access_token(subject="guest", expires_time=False)
140
            refresh_token = Authorize.create_refresh_token(subject="guest", expires_time=False)
141
    else:
142
        usr = fake_users_db.get(username)
143
        if usr != None:
144
            if usr["username"] == username and usr["password"] == password:
145
                access_token = Authorize.create_access_token(subject="admin", expires_time=False)
146
                refresh_token = Authorize.create_refresh_token(subject="admin", expires_time=False)
147
        else:
148
            return """
149
                <html>
150
                    <head>
151
                        <title>Login</title>
152
                    </head>
153
                    <body>
154
                        <h1>Wrong Username or Password</h1>
155
                        <form action="/login" method="get">
156
                            <input type="submit" value="Log again" />
157
                        </form>
158
                        <form action="/login" method="get">
159
                            <input type="submit" value="Home Page" />
160
                        </form>
161
                    </body>
162
                </html>
163
                """
164

    
165
    # Set the JWT cookies in the response
166
    Authorize.set_access_cookies(access_token)
167
    Authorize.set_refresh_cookies(refresh_token)
168
    return """
169
    <html>
170
        <head>
171
            <title>Login</title>
172
        </head>
173
        <body>
174
            <h1>Now you are logged in, you can continue to previous page.</h1>
175
            <form action="/logs-web" method="get">
176
                <input type="submit" value="Home Page" />
177
            </form>
178
        </body>
179
    </html>
180
    """
181

    
182

    
183
@auth.post('/refresh')
184
def refresh(Authorize: AuthJWT = Depends()):
185
    """
186
    endpoint for refreshing browser token. Not used at the moment since lifetime of given tokens are
187
    unlimited.
188
    """
189
    Authorize.jwt_refresh_token_required()
190
    current_user = Authorize.get_jwt_subject()
191
    new_access_token = Authorize.create_access_token(subject=current_user)
192
    # Set the JWT cookies in the response
193
    Authorize.set_access_cookies(new_access_token)
194
    return {"msg": "The token has been refresh"}
195

    
196

    
197
@auth.get('/logout', response_class=HTMLResponse)
198
def logout(Authorize: AuthJWT = Depends()):
199
    """
200
    Endpoint for deleting cookie token with acces role.
201
    """
202
    Authorize.jwt_optional()
203

    
204
    Authorize.unset_jwt_cookies()
205
    return """
206
        <html>
207
            <head>
208
                <title>Logout</title>
209
            </head>
210
            <body>
211
                <h1>Logged Out</h1>
212
                <form action="/logs-web" method="get">
213
                    <input type="submit" value="Back" />
214
                </form>
215
            </body>
216
        </html>
217
        """
(2-2/15)