Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
auth
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Мырзабеков Бекайдар
auth
Commits
40b9bfd1
Commit
40b9bfd1
authored
Dec 26, 2023
by
Мырзабеков Бекайдар
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added authorization
parent
14667cbd
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
122 additions
and
142 deletions
+122
-142
router.py
code/api/router.py
+3
-1
const.py
code/const.py
+7
-0
main.py
code/main.py
+0
-29
routes.py
code/routes.py
+31
-6
schemas.py
code/schemas.py
+14
-0
services.py
code/services.py
+67
-106
No files found.
code/api/router.py
View file @
40b9bfd1
from
fastapi
import
APIRouter
from
routes
import
router
as
user
_route
from
routes
import
user_router
as
user_route
,
auth_router
as
auth
_route
router
=
APIRouter
(
prefix
=
'/api'
,
tags
=
[
'AUTH'
])
router
.
include_router
(
user_route
)
router
.
include_router
(
user_route
)
router
.
include_router
(
auth_route
)
code/const.py
0 → 100644
View file @
40b9bfd1
import
os
SECRET_KEY
=
os
.
getenv
(
'SECRET_KEY'
)
ALGORITHM
=
os
.
getenv
(
'ALGORITHM'
)
ACCESS_TOKEN_EXPIRE_MINUTES
=
int
(
os
.
getenv
(
'ACCESS_TOKEN_EXPIRE_MINUTES'
))
REFRESH_TOKEN_EXPIRE_HOURS
=
int
(
os
.
getenv
(
'REFRESH_TOKEN_EXPIRE_HOURS'
))
code/main.py
View file @
40b9bfd1
from
datetime
import
timedelta
import
fastapi
as
fa
from
fastapi.security
import
OAuth2PasswordRequestForm
from
api.router
import
router
from
db
import
init_db
import
services
def
setup
():
...
...
@@ -20,31 +16,6 @@ app = setup()
init_db
(
app
)
@
router
.
post
(
"/token"
,
response_model
=
services
.
Token
)
async
def
login_for_access_token
(
form_data
:
OAuth2PasswordRequestForm
=
fa
.
Depends
()):
user
=
services
.
authenticate_user
(
services
.
fake_users_db
,
form_data
.
username
,
form_data
.
password
)
if
not
user
:
raise
fa
.
HTTPException
(
status_code
=
fa
.
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
"Incorrect username or password"
,
headers
=
{
"WWW-Authenticate"
:
"Bearer"
},
)
access_token_expires
=
timedelta
(
minutes
=
services
.
ACCESS_TOKEN_EXPIRE_MINUTES
)
access_token
=
services
.
create_access_token
(
data
=
{
"sub"
:
user
.
username
},
expires_delta
=
access_token_expires
)
return
{
"access_token"
:
access_token
,
"token_type"
:
"bearer"
}
@
router
.
get
(
"/users/me/"
,
response_model
=
services
.
User
)
async
def
read_users_me
(
current_user
:
services
.
User
=
fa
.
Depends
(
services
.
get_current_active_user
)):
return
current_user
if
__name__
==
'__main__'
:
import
uvicorn
...
...
code/routes.py
View file @
40b9bfd1
from
uuid
import
UUID
import
fastapi
from
fastapi.security
import
OAuth2PasswordRequestForm
from
schemas
import
(
UserAllOptionalSchema
,
CreateUserSchema
,
CreatedUserResponseSchema
,
UpdateUserSchema
)
from
ctrl
import
UserController
import
services
router
=
fastapi
.
APIRouter
(
prefix
=
'/users'
,
tags
=
[
'AUTH'
])
user_router
=
fastapi
.
APIRouter
(
prefix
=
'/users'
)
auth_router
=
fastapi
.
APIRouter
(
prefix
=
'/auth'
)
ctrl
=
UserController
()
@
router
.
get
(
''
)
@
user_
router
.
get
(
''
)
async
def
get_users
(
query
:
UserAllOptionalSchema
=
fastapi
.
Depends
()):
return
await
ctrl
.
get_list
(
**
query
.
model_dump
(
exclude_none
=
True
))
@
router
.
get
(
'/{id}'
)
@
user_
router
.
get
(
'/{id}'
)
async
def
get_users
(
id
:
UUID
):
return
await
ctrl
.
get
(
id
)
@
router
.
post
(
''
)
@
user_
router
.
post
(
''
)
async
def
create_users
(
body
:
CreateUserSchema
)
->
CreatedUserResponseSchema
:
return
await
ctrl
.
create
(
**
body
.
model_dump
(
exclude_none
=
True
))
@
router
.
patch
(
'/{id}'
)
@
user_
router
.
patch
(
'/{id}'
)
async
def
update_users
(
id
:
UUID
,
body
:
UpdateUserSchema
,
)
->
CreatedUserResponseSchema
:
return
await
ctrl
.
update
(
id
,
**
body
.
model_dump
(
exclude_none
=
True
))
@
router
.
delete
(
'/{id}'
)
@
user_
router
.
delete
(
'/{id}'
)
async
def
delete_users
(
id
:
UUID
,
):
return
await
ctrl
.
delete
(
id
)
@
auth_router
.
post
(
'/login'
)
async
def
login
(
form_data
:
OAuth2PasswordRequestForm
=
fastapi
.
Depends
(),
):
return
await
services
.
auth_service
.
login
(
form_data
)
@
auth_router
.
get
(
'/users/me'
)
async
def
read_user_me
(
user
:
dict
=
fastapi
.
Depends
(
services
.
auth_service
.
get_current_user
)
):
return
user
@
auth_router
.
post
(
'/refresh'
)
async
def
refresh_token
(
data
:
dict
,
user
:
dict
=
fastapi
.
Depends
(
services
.
auth_service
.
get_current_user
)
):
return
services
.
token_service
.
refresh_token
(
data
[
'refresh_token'
])
code/schemas.py
View file @
40b9bfd1
from
dataclasses
import
dataclass
from
uuid
import
UUID
from
datetime
import
datetime
from
pydantic
import
BaseModel
,
EmailStr
...
...
@@ -28,3 +30,15 @@ class UpdateUserSchema(BaseModel):
class
UserAllOptionalSchema
(
BaseModel
):
username
:
None
|
str
=
None
password
:
None
|
str
=
None
@
dataclass
class
TokenData
:
sub
:
int
exp
:
datetime
|
None
=
None
@
dataclass
class
LoginRequestModel
:
username
:
str
password
:
str
code/services.py
View file @
40b9bfd1
import
os
from
datetime
import
datetime
,
timedelta
import
fastapi
as
fa
import
fastapi.security
as
fs
from
jose
import
jwt
,
JWTError
from
passlib.context
import
CryptContext
from
pydantic
import
BaseModel
SECRET_KEY
=
os
.
getenv
(
'SECRET_KEY'
)
ALGORITHM
=
os
.
getenv
(
'ALGORITHM'
)
ACCESS_TOKEN_EXPIRE_MINUTES
=
int
(
os
.
getenv
(
'ACCESS_TOKEN_EXPIRE_MINUTES'
))
fake_users_db
=
{
"johndoe"
:
{
"username"
:
"johndoe"
,
"full_name"
:
"John Doe"
,
"email"
:
"johndoe@example.com"
,
"password"
:
"$2a$12$ITTdvxKhvrBQt/zxKmP6K.F8vPnROkX7VWU7jQmcH1UspVdIguqXa"
,
"disabled"
:
False
,
},
'janedoe'
:
{
"username"
:
"janedoe"
,
"full_name"
:
"Jane Doe"
,
"email"
:
"janedoe@example.com"
,
"password"
:
"$2a$12$4D442S0uyt74hPon/EBP9uZV3z2EUFZ0F9JgmtIK2DyBsdGNWHt1G"
},
}
class
Token
(
BaseModel
):
access_token
:
str
token_type
:
str
class
TokenData
(
BaseModel
):
username
:
str
|
None
=
None
class
User
(
BaseModel
):
username
:
str
email
:
str
|
None
=
None
full_name
:
str
|
None
=
None
disabled
:
bool
|
None
=
None
class
UserInDB
(
User
):
password
:
str
import
schemas
import
const
from
repository
import
UserRepository
pwd_context
=
CryptContext
(
schemes
=
[
'bcrypt'
],
deprecated
=
'auto'
)
oauth2_scheme
=
fs
.
OAuth2PasswordBearer
(
tokenUrl
=
'api/token'
)
app
=
fa
.
FastAPI
()
def
verify_password
(
plain_password
,
hashed_password
):
return
pwd_context
.
verify
(
plain_password
,
hashed_password
)
def
get_password
(
password
:
str
)
->
str
:
return
pwd_context
.
hash
(
password
)
def
get_user
(
db
,
username
:
str
):
if
username
in
db
:
user_dict
=
db
[
username
]
return
UserInDB
(
**
user_dict
)
def
authenticate_user
(
fake_db
,
username
:
str
,
password
:
str
):
user
=
get_user
(
fake_db
,
username
)
if
not
user
:
return
False
if
not
verify_password
(
password
,
user
.
password
):
return
False
return
user
def
create_access_token
(
data
:
dict
,
expires_delta
:
timedelta
|
None
=
None
):
to_encode
=
data
.
copy
()
if
expires_delta
:
expire
=
datetime
.
utcnow
()
+
expires_delta
else
:
expire
=
datetime
.
utcnow
()
+
timedelta
(
minutes
=
15
)
to_encode
.
update
({
"exp"
:
expire
})
oauth2_scheme
=
fs
.
OAuth2PasswordBearer
(
tokenUrl
=
'/api/auth/login'
)
class
TokenService
:
def
create_token
(
self
,
data
:
schemas
.
TokenData
,
expires_delta
:
timedelta
)
->
str
:
payload
=
{
'sub'
:
str
(
data
.
sub
),
'exp'
:
datetime
.
utcnow
()
+
expires_delta
,
}
return
jwt
.
encode
(
payload
,
const
.
SECRET_KEY
,
algorithm
=
const
.
ALGORITHM
)
def
create_tokens
(
self
,
data
:
schemas
.
TokenData
):
access
=
self
.
create_token
(
data
,
expires_delta
=
timedelta
(
minutes
=
const
.
ACCESS_TOKEN_EXPIRE_MINUTES
)
)
refresh
=
self
.
create_token
(
data
,
expires_delta
=
timedelta
(
hours
=
const
.
REFRESH_TOKEN_EXPIRE_HOURS
)
)
return
{
"access_token"
:
access
,
"refresh_token"
:
refresh
}
def
decode_token
(
self
,
token
:
str
)
->
schemas
.
TokenData
:
credentials_exception
=
fa
.
HTTPException
(
status_code
=
fa
.
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
"Could not validate credentials"
,
headers
=
{
"WWW-Authenticate"
:
"Bearer"
},
)
try
:
decoded_token_payload
=
jwt
.
decode
(
token
,
const
.
SECRET_KEY
,
algorithms
=
[
const
.
ALGORITHM
])
user_id
=
decoded_token_payload
.
get
(
'sub'
)
if
user_id
is
None
:
raise
credentials_exception
except
JWTError
:
raise
credentials_exception
encoded_jwt
=
jwt
.
encode
(
to_encode
,
SECRET_KEY
,
algorithm
=
ALGORITHM
)
return
schemas
.
TokenData
(
**
decoded_token_payload
)
return
encoded_jwt
def
refresh_token
(
self
,
refresh_token
:
str
):
token_data
=
self
.
decode_token
(
refresh_token
)
access
=
self
.
create_token
(
token_data
,
timedelta
(
minutes
=
const
.
ACCESS_TOKEN_EXPIRE_MINUTES
))
return
{
'access_token'
:
access
,
'refresh_token'
:
refresh_token
}
async
def
get_current_user
(
token
:
str
=
fa
.
Depends
(
oauth2_scheme
)):
credentials_exception
=
fa
.
HTTPException
(
status_code
=
fa
.
status
.
HTTP_401_UNAUTHORIZED
,
detail
=
"Could not validate credentials"
,
headers
=
{
"WWW-Authenticate"
:
"Bearer"
},
)
token_service
=
TokenService
()
try
:
payload
=
jwt
.
decode
(
token
,
SECRET_KEY
,
algorithms
=
[
ALGORITHM
])
username
:
str
=
payload
.
get
(
"sub"
)
class
AuthService
:
def
__init__
(
self
)
->
None
:
self
.
user_repo
=
UserRepository
()
if
username
is
None
:
raise
credentials_exception
async
def
verify_password
(
self
,
plain_password
:
str
,
hashed_password
:
str
)
->
bool
:
return
pwd_context
.
verify
(
plain_password
,
hashed_password
)
token_data
=
TokenData
(
username
=
username
)
async
def
authenticate_user
(
self
,
username
:
str
,
password
:
str
):
users
=
await
self
.
user_repo
.
get_list
(
username
=
username
)
except
JWTError
:
raise
credentials_exception
if
users
and
self
.
verify_password
(
password
,
users
[
0
]
.
password
)
:
return
users
[
0
]
user
=
get_user
(
fake_users_db
,
username
=
token_data
.
username
)
async
def
login
(
self
,
data
:
schemas
.
LoginRequestModel
):
user
=
await
self
.
authenticate_user
(
username
=
data
.
username
,
password
=
data
.
password
)
if
user
is
None
:
raise
credentials_exception
if
not
user
:
raise
fa
.
HTTPException
(
status_code
=
fa
.
status
.
HTTP_404_NOT_FOUND
,
detail
=
"Incorrect username or password"
,
headers
=
{
"WWW-Authenticate"
:
"Bearer"
},
)
return
user
return
token_service
.
create_tokens
(
schemas
.
TokenData
(
sub
=
user
.
id
))
async
def
get_current_user
(
self
,
token
:
str
=
fa
.
Security
(
oauth2_scheme
)):
token_data
=
token_service
.
decode_token
(
token
)
return
await
self
.
user_repo
.
get
(
id
=
token_data
.
sub
)
async
def
get_current_active_user
(
current_user
:
User
=
fa
.
Depends
(
get_current_user
)):
if
current_user
.
disabled
:
raise
fa
.
HTTPException
(
status_code
=
400
,
detail
=
"Inactive user"
)
return
current_user
auth_service
=
AuthService
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment