square-authentication 2.0.0__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- square_authentication/messages.py +2 -1
- square_authentication/pydantic_models/__init__.py +0 -0
- square_authentication/pydantic_models/core.py +24 -0
- square_authentication/routes/core.py +484 -185
- {square_authentication-2.0.0.dist-info → square_authentication-3.0.0.dist-info}/METADATA +14 -1
- {square_authentication-2.0.0.dist-info → square_authentication-3.0.0.dist-info}/RECORD +8 -6
- {square_authentication-2.0.0.dist-info → square_authentication-3.0.0.dist-info}/WHEEL +0 -0
- {square_authentication-2.0.0.dist-info → square_authentication-3.0.0.dist-info}/top_level.txt +0 -0
@@ -8,9 +8,10 @@ messages = {
|
|
8
8
|
"USERNAME_ALREADY_EXISTS": "the username you entered is already taken. please choose a different one.",
|
9
9
|
"INCORRECT_ACCESS_TOKEN": "the access token provided is invalid or expired.",
|
10
10
|
"INCORRECT_REFRESH_TOKEN": "the refresh token provided is invalid or expired.",
|
11
|
-
"GENERIC_READ_SUCCESSFUL": "data retrieved successfully.",
|
12
11
|
"GENERIC_CREATION_SUCCESSFUL": "records created successfully.",
|
12
|
+
"GENERIC_READ_SUCCESSFUL": "data retrieved successfully.",
|
13
13
|
"GENERIC_UPDATE_SUCCESSFUL": "your information has been updated successfully.",
|
14
|
+
"GENERIC_DELETE_SUCCESSFUL": "your records have been deleted successfully.",
|
14
15
|
"GENERIC_400": "the request is invalid or cannot be processed.",
|
15
16
|
"GENERIC_500": "an internal server error occurred. please try again later.",
|
16
17
|
}
|
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
|
6
|
+
class RegisterUsernameV0(BaseModel):
|
7
|
+
username: str
|
8
|
+
password: str
|
9
|
+
app_id: Optional[int] = None
|
10
|
+
|
11
|
+
|
12
|
+
class LoginUsernameV0(BaseModel):
|
13
|
+
username: str
|
14
|
+
password: str
|
15
|
+
app_id: int
|
16
|
+
|
17
|
+
|
18
|
+
class DeleteUserV0(BaseModel):
|
19
|
+
password: str
|
20
|
+
|
21
|
+
|
22
|
+
class UpdatePasswordV0(BaseModel):
|
23
|
+
old_password: str
|
24
|
+
new_password: str
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from datetime import datetime, timedelta, timezone
|
2
2
|
from typing import Annotated, List
|
3
|
-
from uuid import UUID
|
4
3
|
|
5
4
|
import bcrypt
|
6
5
|
import jwt
|
@@ -36,6 +35,12 @@ from square_authentication.configuration import (
|
|
36
35
|
config_str_square_database_protocol,
|
37
36
|
)
|
38
37
|
from square_authentication.messages import messages
|
38
|
+
from square_authentication.pydantic_models.core import (
|
39
|
+
RegisterUsernameV0,
|
40
|
+
LoginUsernameV0,
|
41
|
+
DeleteUserV0,
|
42
|
+
UpdatePasswordV0,
|
43
|
+
)
|
39
44
|
from square_authentication.utils.token import get_jwt_payload
|
40
45
|
|
41
46
|
router = APIRouter(
|
@@ -51,8 +56,17 @@ global_object_square_database_helper = SquareDatabaseHelper(
|
|
51
56
|
|
52
57
|
@router.post("/register_username/v0")
|
53
58
|
@global_object_square_logger.async_auto_logger
|
54
|
-
async def register_username_v0(
|
59
|
+
async def register_username_v0(
|
60
|
+
body: RegisterUsernameV0,
|
61
|
+
):
|
62
|
+
username = body.username
|
63
|
+
password = body.password
|
64
|
+
app_id = body.app_id
|
65
|
+
|
55
66
|
local_str_user_id = None
|
67
|
+
local_str_access_token = None
|
68
|
+
local_str_refresh_token = None
|
69
|
+
|
56
70
|
username = username.lower()
|
57
71
|
try:
|
58
72
|
"""
|
@@ -117,13 +131,77 @@ async def register_username_v0(username: str, password: str):
|
|
117
131
|
schema_name=global_string_schema_name,
|
118
132
|
table_name=UserCredential.__tablename__,
|
119
133
|
)
|
134
|
+
if app_id is not None:
|
135
|
+
# assign app to user
|
136
|
+
global_object_square_database_helper.insert_rows_v0(
|
137
|
+
database_name=global_string_database_name,
|
138
|
+
schema_name=global_string_schema_name,
|
139
|
+
table_name=UserApp.__tablename__,
|
140
|
+
data=[
|
141
|
+
{
|
142
|
+
UserApp.user_id.name: local_str_user_id,
|
143
|
+
UserApp.app_id.name: app_id,
|
144
|
+
}
|
145
|
+
],
|
146
|
+
)
|
147
|
+
|
148
|
+
# return new access token and refresh token
|
149
|
+
# create access token
|
150
|
+
local_dict_access_token_payload = {
|
151
|
+
"app_id": app_id,
|
152
|
+
"user_id": local_str_user_id,
|
153
|
+
"exp": datetime.now(timezone.utc)
|
154
|
+
+ timedelta(minutes=config_int_access_token_valid_minutes),
|
155
|
+
}
|
156
|
+
local_str_access_token = jwt.encode(
|
157
|
+
local_dict_access_token_payload,
|
158
|
+
config_str_secret_key_for_access_token,
|
159
|
+
)
|
160
|
+
|
161
|
+
# create refresh token
|
162
|
+
local_object_refresh_token_expiry_time = datetime.now(
|
163
|
+
timezone.utc
|
164
|
+
) + timedelta(minutes=config_int_refresh_token_valid_minutes)
|
120
165
|
|
166
|
+
local_dict_refresh_token_payload = {
|
167
|
+
"app_id": app_id,
|
168
|
+
"user_id": local_str_user_id,
|
169
|
+
"exp": local_object_refresh_token_expiry_time,
|
170
|
+
}
|
171
|
+
local_str_refresh_token = jwt.encode(
|
172
|
+
local_dict_refresh_token_payload,
|
173
|
+
config_str_secret_key_for_refresh_token,
|
174
|
+
)
|
175
|
+
# entry in user session table
|
176
|
+
global_object_square_database_helper.insert_rows_v0(
|
177
|
+
data=[
|
178
|
+
{
|
179
|
+
UserSession.user_id.name: local_str_user_id,
|
180
|
+
UserSession.app_id.name: app_id,
|
181
|
+
UserSession.user_session_refresh_token.name: local_str_refresh_token,
|
182
|
+
UserSession.user_session_expiry_time.name: local_object_refresh_token_expiry_time.strftime(
|
183
|
+
"%Y-%m-%d %H:%M:%S.%f+00"
|
184
|
+
),
|
185
|
+
}
|
186
|
+
],
|
187
|
+
database_name=global_string_database_name,
|
188
|
+
schema_name=global_string_schema_name,
|
189
|
+
table_name=UserSession.__tablename__,
|
190
|
+
)
|
121
191
|
"""
|
122
192
|
return value
|
123
193
|
"""
|
124
194
|
output_content = get_api_output_in_standard_format(
|
125
195
|
message=messages["REGISTRATION_SUCCESSFUL"],
|
126
|
-
data={
|
196
|
+
data={
|
197
|
+
"main": {
|
198
|
+
"user_id": local_str_user_id,
|
199
|
+
"username": username,
|
200
|
+
"app_id": app_id,
|
201
|
+
"access_token": local_str_access_token,
|
202
|
+
"refresh_token": local_str_refresh_token,
|
203
|
+
},
|
204
|
+
},
|
127
205
|
)
|
128
206
|
return JSONResponse(
|
129
207
|
status_code=status.HTTP_201_CREATED,
|
@@ -156,32 +234,29 @@ async def register_username_v0(username: str, password: str):
|
|
156
234
|
)
|
157
235
|
|
158
236
|
|
159
|
-
@router.get("/
|
237
|
+
@router.get("/get_user_details/v0")
|
160
238
|
@global_object_square_logger.async_auto_logger
|
161
|
-
async def
|
239
|
+
async def get_user_details_v0(
|
240
|
+
access_token: Annotated[str, Header()],
|
241
|
+
):
|
162
242
|
try:
|
163
|
-
local_string_user_id = str(user_id)
|
164
243
|
"""
|
165
244
|
validation
|
166
245
|
"""
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
{User.user_id.name: FilterConditionsV0(eq=local_string_user_id)}
|
174
|
-
),
|
175
|
-
)["data"]["main"]
|
176
|
-
if len(local_list_response_user) != 1:
|
246
|
+
# validate access token
|
247
|
+
try:
|
248
|
+
local_dict_access_token_payload = get_jwt_payload(
|
249
|
+
access_token, config_str_secret_key_for_access_token
|
250
|
+
)
|
251
|
+
except Exception as error:
|
177
252
|
output_content = get_api_output_in_standard_format(
|
178
|
-
message=messages["
|
179
|
-
log=f"invalid user_id: {local_string_user_id}",
|
253
|
+
message=messages["INCORRECT_ACCESS_TOKEN"], log=str(error)
|
180
254
|
)
|
181
|
-
|
182
|
-
status_code=status.
|
183
|
-
|
255
|
+
return JSONResponse(
|
256
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
257
|
+
content=output_content,
|
184
258
|
)
|
259
|
+
user_id = local_dict_access_token_payload["user_id"]
|
185
260
|
"""
|
186
261
|
main process
|
187
262
|
"""
|
@@ -189,18 +264,59 @@ async def get_user_app_ids_v0(user_id: UUID):
|
|
189
264
|
database_name=global_string_database_name,
|
190
265
|
schema_name=global_string_schema_name,
|
191
266
|
table_name=UserApp.__tablename__,
|
192
|
-
filters=FiltersV0(
|
193
|
-
{UserApp.user_id.name: FilterConditionsV0(eq=local_string_user_id)}
|
194
|
-
),
|
267
|
+
filters=FiltersV0({UserApp.user_id.name: FilterConditionsV0(eq=user_id)}),
|
195
268
|
)["data"]["main"]
|
269
|
+
local_list_response_user_credentials = (
|
270
|
+
global_object_square_database_helper.get_rows_v0(
|
271
|
+
database_name=global_string_database_name,
|
272
|
+
schema_name=global_string_schema_name,
|
273
|
+
table_name=UserCredential.__tablename__,
|
274
|
+
filters=FiltersV0(
|
275
|
+
{UserCredential.user_id.name: FilterConditionsV0(eq=user_id)}
|
276
|
+
),
|
277
|
+
)["data"]["main"]
|
278
|
+
)
|
279
|
+
# not putting filter for expiry refresh tokens
|
280
|
+
local_list_response_user_sessions = (
|
281
|
+
global_object_square_database_helper.get_rows_v0(
|
282
|
+
database_name=global_string_database_name,
|
283
|
+
schema_name=global_string_schema_name,
|
284
|
+
table_name=UserSession.__tablename__,
|
285
|
+
filters=FiltersV0(
|
286
|
+
{
|
287
|
+
UserSession.user_id.name: FilterConditionsV0(eq=user_id),
|
288
|
+
}
|
289
|
+
),
|
290
|
+
)["data"]["main"]
|
291
|
+
)
|
196
292
|
"""
|
197
293
|
return value
|
198
294
|
"""
|
295
|
+
return_this = {
|
296
|
+
"user_id": user_id,
|
297
|
+
"credentials": {
|
298
|
+
"username": local_list_response_user_credentials[0][
|
299
|
+
UserCredential.user_credential_username.name
|
300
|
+
],
|
301
|
+
},
|
302
|
+
"apps": [x[UserApp.app_id.name] for x in local_list_response_user_app],
|
303
|
+
"sessions": [
|
304
|
+
{
|
305
|
+
"app_id": x[UserApp.app_id.name],
|
306
|
+
"sessions": len(
|
307
|
+
[
|
308
|
+
y
|
309
|
+
for y in local_list_response_user_sessions
|
310
|
+
if y[UserSession.app_id.name] == x[UserApp.app_id.name]
|
311
|
+
]
|
312
|
+
),
|
313
|
+
}
|
314
|
+
for x in local_list_response_user_app
|
315
|
+
],
|
316
|
+
}
|
199
317
|
output_content = get_api_output_in_standard_format(
|
200
318
|
message=messages["GENERIC_READ_SUCCESSFUL"],
|
201
|
-
data={
|
202
|
-
"main": [x[UserApp.app_id.name] for x in local_list_response_user_app]
|
203
|
-
},
|
319
|
+
data={"main": return_this},
|
204
320
|
)
|
205
321
|
return JSONResponse(
|
206
322
|
status_code=status.HTTP_200_OK,
|
@@ -228,15 +344,29 @@ async def get_user_app_ids_v0(user_id: UUID):
|
|
228
344
|
@router.patch("/update_user_app_ids/v0")
|
229
345
|
@global_object_square_logger.async_auto_logger
|
230
346
|
async def update_user_app_ids_v0(
|
231
|
-
|
347
|
+
access_token: Annotated[str, Header()],
|
232
348
|
app_ids_to_add: List[int],
|
233
349
|
app_ids_to_remove: List[int],
|
234
350
|
):
|
235
351
|
try:
|
236
|
-
|
352
|
+
|
237
353
|
"""
|
238
354
|
validation
|
239
355
|
"""
|
356
|
+
# validate access token
|
357
|
+
try:
|
358
|
+
local_dict_access_token_payload = get_jwt_payload(
|
359
|
+
access_token, config_str_secret_key_for_access_token
|
360
|
+
)
|
361
|
+
except Exception as error:
|
362
|
+
output_content = get_api_output_in_standard_format(
|
363
|
+
message=messages["INCORRECT_ACCESS_TOKEN"], log=str(error)
|
364
|
+
)
|
365
|
+
return JSONResponse(
|
366
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
367
|
+
content=output_content,
|
368
|
+
)
|
369
|
+
user_id = local_dict_access_token_payload["user_id"]
|
240
370
|
|
241
371
|
app_ids_to_add = list(set(app_ids_to_add))
|
242
372
|
app_ids_to_remove = list(set(app_ids_to_remove))
|
@@ -252,27 +382,6 @@ async def update_user_app_ids_v0(
|
|
252
382
|
status_code=status.HTTP_400_BAD_REQUEST,
|
253
383
|
detail=output_content,
|
254
384
|
)
|
255
|
-
# validate access token
|
256
|
-
# TBD
|
257
|
-
|
258
|
-
# check if user id is in user table
|
259
|
-
local_list_response_user = global_object_square_database_helper.get_rows_v0(
|
260
|
-
database_name=global_string_database_name,
|
261
|
-
schema_name=global_string_schema_name,
|
262
|
-
table_name=User.__tablename__,
|
263
|
-
filters=FiltersV0(
|
264
|
-
{User.user_id.name: FilterConditionsV0(eq=local_string_user_id)}
|
265
|
-
),
|
266
|
-
)["data"]["main"]
|
267
|
-
if len(local_list_response_user) != 1:
|
268
|
-
output_content = get_api_output_in_standard_format(
|
269
|
-
message=messages["INCORRECT_USER_ID"],
|
270
|
-
log=f"invalid user_id: {local_string_user_id}",
|
271
|
-
)
|
272
|
-
raise HTTPException(
|
273
|
-
status_code=status.HTTP_404_NOT_FOUND,
|
274
|
-
detail=output_content,
|
275
|
-
)
|
276
385
|
|
277
386
|
# check if all app_ids are valid
|
278
387
|
local_list_all_app_ids = [*app_ids_to_add, *app_ids_to_remove]
|
@@ -305,13 +414,11 @@ async def update_user_app_ids_v0(
|
|
305
414
|
database_name=global_string_database_name,
|
306
415
|
schema_name=global_string_schema_name,
|
307
416
|
table_name=UserApp.__tablename__,
|
308
|
-
filters=FiltersV0(
|
309
|
-
{UserApp.user_id.name: FilterConditionsV0(eq=local_string_user_id)}
|
310
|
-
),
|
417
|
+
filters=FiltersV0({UserApp.user_id.name: FilterConditionsV0(eq=user_id)}),
|
311
418
|
)["data"]["main"]
|
312
419
|
local_list_new_app_ids = [
|
313
420
|
{
|
314
|
-
UserApp.user_id.name:
|
421
|
+
UserApp.user_id.name: user_id,
|
315
422
|
UserApp.app_id.name: x,
|
316
423
|
}
|
317
424
|
for x in app_ids_to_add
|
@@ -333,22 +440,19 @@ async def update_user_app_ids_v0(
|
|
333
440
|
table_name=UserApp.__tablename__,
|
334
441
|
filters=FiltersV0(
|
335
442
|
{
|
336
|
-
UserApp.user_id.name: FilterConditionsV0(
|
337
|
-
eq=local_string_user_id
|
338
|
-
),
|
443
|
+
UserApp.user_id.name: FilterConditionsV0(eq=user_id),
|
339
444
|
UserApp.app_id.name: FilterConditionsV0(eq=app_id),
|
340
445
|
}
|
341
446
|
),
|
342
447
|
)
|
448
|
+
# logout user from removed apps
|
343
449
|
global_object_square_database_helper.delete_rows_v0(
|
344
450
|
database_name=global_string_database_name,
|
345
451
|
schema_name=global_string_schema_name,
|
346
452
|
table_name=UserSession.__tablename__,
|
347
453
|
filters=FiltersV0(
|
348
454
|
{
|
349
|
-
UserSession.user_id.name: FilterConditionsV0(
|
350
|
-
eq=local_string_user_id
|
351
|
-
),
|
455
|
+
UserSession.user_id.name: FilterConditionsV0(eq=user_id),
|
352
456
|
UserSession.app_id.name: FilterConditionsV0(eq=app_id),
|
353
457
|
}
|
354
458
|
),
|
@@ -362,9 +466,7 @@ async def update_user_app_ids_v0(
|
|
362
466
|
database_name=global_string_database_name,
|
363
467
|
schema_name=global_string_schema_name,
|
364
468
|
table_name=UserApp.__tablename__,
|
365
|
-
filters=FiltersV0(
|
366
|
-
{UserApp.user_id.name: FilterConditionsV0(eq=local_string_user_id)}
|
367
|
-
),
|
469
|
+
filters=FiltersV0({UserApp.user_id.name: FilterConditionsV0(eq=user_id)}),
|
368
470
|
)["data"]["main"]
|
369
471
|
output_content = get_api_output_in_standard_format(
|
370
472
|
message=messages["GENERIC_UPDATE_SUCCESSFUL"],
|
@@ -397,7 +499,10 @@ async def update_user_app_ids_v0(
|
|
397
499
|
|
398
500
|
@router.get("/login_username/v0")
|
399
501
|
@global_object_square_logger.async_auto_logger
|
400
|
-
async def login_username_v0(
|
502
|
+
async def login_username_v0(body: LoginUsernameV0):
|
503
|
+
username = body.username
|
504
|
+
password = body.password
|
505
|
+
app_id = body.app_id
|
401
506
|
username = username.lower()
|
402
507
|
try:
|
403
508
|
"""
|
@@ -554,54 +659,14 @@ async def login_username_v0(username: str, password: str, app_id: int):
|
|
554
659
|
@router.get("/generate_access_token/v0")
|
555
660
|
@global_object_square_logger.async_auto_logger
|
556
661
|
async def generate_access_token_v0(
|
557
|
-
|
662
|
+
refresh_token: Annotated[str, Header()],
|
558
663
|
):
|
559
664
|
try:
|
560
665
|
"""
|
561
666
|
validation
|
562
667
|
"""
|
563
|
-
# validate user_id
|
564
|
-
local_list_user_response = global_object_square_database_helper.get_rows_v0(
|
565
|
-
database_name=global_string_database_name,
|
566
|
-
schema_name=global_string_schema_name,
|
567
|
-
table_name=User.__tablename__,
|
568
|
-
filters=FiltersV0({User.user_id.name: FilterConditionsV0(eq=user_id)}),
|
569
|
-
)["data"]["main"]
|
570
|
-
|
571
|
-
if len(local_list_user_response) != 1:
|
572
|
-
output_content = get_api_output_in_standard_format(
|
573
|
-
message=messages["INCORRECT_USER_ID"],
|
574
|
-
log=f"incorrect user_id: {user_id}.",
|
575
|
-
)
|
576
|
-
return JSONResponse(
|
577
|
-
status_code=status.HTTP_400_BAD_REQUEST,
|
578
|
-
content=output_content,
|
579
|
-
)
|
580
|
-
# validate if app_id is assigned to user
|
581
|
-
# this will also validate if app_id is valid
|
582
|
-
local_dict_user = local_list_user_response[0]
|
583
|
-
local_str_user_id = local_dict_user[User.user_id.name]
|
584
|
-
local_list_user_app_response = global_object_square_database_helper.get_rows_v0(
|
585
|
-
database_name=global_string_database_name,
|
586
|
-
schema_name=global_string_schema_name,
|
587
|
-
table_name=UserApp.__tablename__,
|
588
|
-
filters=FiltersV0(
|
589
|
-
{
|
590
|
-
UserApp.user_id.name: FilterConditionsV0(eq=local_str_user_id),
|
591
|
-
UserApp.app_id.name: FilterConditionsV0(eq=app_id),
|
592
|
-
}
|
593
|
-
),
|
594
|
-
)["data"]["main"]
|
595
|
-
if len(local_list_user_app_response) != 1:
|
596
|
-
output_content = get_api_output_in_standard_format(
|
597
|
-
message=messages["GENERIC_400"],
|
598
|
-
log=f"user_id {local_str_user_id} not assigned to app {app_id}.",
|
599
|
-
)
|
600
|
-
return JSONResponse(
|
601
|
-
status_code=status.HTTP_400_BAD_REQUEST, content=output_content
|
602
|
-
)
|
603
668
|
# validate refresh token
|
604
|
-
# validating if a session refresh token exists in the database
|
669
|
+
# validating if a session refresh token exists in the database.
|
605
670
|
local_list_user_session_response = (
|
606
671
|
global_object_square_database_helper.get_rows_v0(
|
607
672
|
database_name=global_string_database_name,
|
@@ -609,11 +674,9 @@ async def generate_access_token_v0(
|
|
609
674
|
table_name=UserSession.__tablename__,
|
610
675
|
filters=FiltersV0(
|
611
676
|
{
|
612
|
-
UserSession.user_id.name: FilterConditionsV0(eq=user_id),
|
613
677
|
UserSession.user_session_refresh_token.name: FilterConditionsV0(
|
614
678
|
eq=refresh_token
|
615
679
|
),
|
616
|
-
UserSession.app_id.name: FilterConditionsV0(eq=app_id),
|
617
680
|
}
|
618
681
|
),
|
619
682
|
)["data"]["main"]
|
@@ -622,7 +685,7 @@ async def generate_access_token_v0(
|
|
622
685
|
if len(local_list_user_session_response) != 1:
|
623
686
|
output_content = get_api_output_in_standard_format(
|
624
687
|
message=messages["INCORRECT_REFRESH_TOKEN"],
|
625
|
-
log=f"incorrect refresh token: {refresh_token}
|
688
|
+
log=f"incorrect refresh token: {refresh_token}.",
|
626
689
|
)
|
627
690
|
return JSONResponse(
|
628
691
|
status_code=status.HTTP_400_BAD_REQUEST,
|
@@ -641,32 +704,13 @@ async def generate_access_token_v0(
|
|
641
704
|
status_code=status.HTTP_400_BAD_REQUEST,
|
642
705
|
content=output_content,
|
643
706
|
)
|
644
|
-
|
645
|
-
if local_dict_refresh_token_payload["user_id"] != user_id:
|
646
|
-
output_content = get_api_output_in_standard_format(
|
647
|
-
message=messages["INCORRECT_REFRESH_TOKEN"],
|
648
|
-
log=f"refresh token and user_id mismatch.",
|
649
|
-
)
|
650
|
-
return JSONResponse(
|
651
|
-
status_code=status.HTTP_400_BAD_REQUEST,
|
652
|
-
content=output_content,
|
653
|
-
)
|
654
|
-
if local_dict_refresh_token_payload["app_id"] != app_id:
|
655
|
-
output_content = get_api_output_in_standard_format(
|
656
|
-
message=messages["INCORRECT_REFRESH_TOKEN"],
|
657
|
-
log=f"refresh token and app_id mismatch.",
|
658
|
-
)
|
659
|
-
return JSONResponse(
|
660
|
-
status_code=status.HTTP_400_BAD_REQUEST,
|
661
|
-
content=output_content,
|
662
|
-
)
|
663
707
|
"""
|
664
708
|
main process
|
665
709
|
"""
|
666
710
|
# create and send access token
|
667
711
|
local_dict_access_token_payload = {
|
668
|
-
"app_id": app_id,
|
669
|
-
"user_id": user_id,
|
712
|
+
"app_id": local_dict_refresh_token_payload["app_id"],
|
713
|
+
"user_id": local_dict_refresh_token_payload["user_id"],
|
670
714
|
"exp": datetime.now(timezone.utc)
|
671
715
|
+ timedelta(minutes=config_int_access_token_valid_minutes),
|
672
716
|
}
|
@@ -705,15 +749,121 @@ async def generate_access_token_v0(
|
|
705
749
|
@router.delete("/logout/v0")
|
706
750
|
@global_object_square_logger.async_auto_logger
|
707
751
|
async def logout_v0(
|
708
|
-
user_id: str,
|
709
|
-
app_id: int,
|
710
|
-
access_token: Annotated[str, Header()],
|
711
752
|
refresh_token: Annotated[str, Header()],
|
712
753
|
):
|
713
754
|
try:
|
714
755
|
"""
|
715
756
|
validation
|
716
757
|
"""
|
758
|
+
# validate refresh token
|
759
|
+
# validating if a session refresh token exists in the database.
|
760
|
+
local_list_user_session_response = (
|
761
|
+
global_object_square_database_helper.get_rows_v0(
|
762
|
+
database_name=global_string_database_name,
|
763
|
+
schema_name=global_string_schema_name,
|
764
|
+
table_name=UserSession.__tablename__,
|
765
|
+
filters=FiltersV0(
|
766
|
+
{
|
767
|
+
UserSession.user_session_refresh_token.name: FilterConditionsV0(
|
768
|
+
eq=refresh_token
|
769
|
+
),
|
770
|
+
}
|
771
|
+
),
|
772
|
+
)["data"]["main"]
|
773
|
+
)
|
774
|
+
|
775
|
+
if len(local_list_user_session_response) != 1:
|
776
|
+
output_content = get_api_output_in_standard_format(
|
777
|
+
message=messages["INCORRECT_REFRESH_TOKEN"],
|
778
|
+
log=f"incorrect refresh token: {refresh_token}.",
|
779
|
+
)
|
780
|
+
return JSONResponse(
|
781
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
782
|
+
content=output_content,
|
783
|
+
)
|
784
|
+
# validating if the refresh token is valid, active and of the same user.
|
785
|
+
try:
|
786
|
+
local_dict_refresh_token_payload = get_jwt_payload(
|
787
|
+
refresh_token, config_str_secret_key_for_refresh_token
|
788
|
+
)
|
789
|
+
except Exception as error:
|
790
|
+
output_content = get_api_output_in_standard_format(
|
791
|
+
message=messages["INCORRECT_REFRESH_TOKEN"],
|
792
|
+
log=str(error),
|
793
|
+
)
|
794
|
+
return JSONResponse(
|
795
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
796
|
+
content=output_content,
|
797
|
+
)
|
798
|
+
# ======================================================================================
|
799
|
+
# NOTE: if refresh token has expired no need to delete it during this call
|
800
|
+
# ======================================================================================
|
801
|
+
"""
|
802
|
+
main process
|
803
|
+
"""
|
804
|
+
# delete session for user
|
805
|
+
global_object_square_database_helper.delete_rows_v0(
|
806
|
+
database_name=global_string_database_name,
|
807
|
+
schema_name=global_string_schema_name,
|
808
|
+
table_name=UserSession.__tablename__,
|
809
|
+
filters=FiltersV0(
|
810
|
+
{
|
811
|
+
UserSession.user_session_refresh_token.name: FilterConditionsV0(
|
812
|
+
eq=refresh_token
|
813
|
+
),
|
814
|
+
}
|
815
|
+
),
|
816
|
+
)
|
817
|
+
"""
|
818
|
+
return value
|
819
|
+
"""
|
820
|
+
output_content = get_api_output_in_standard_format(
|
821
|
+
message=messages["LOGOUT_SUCCESSFUL"],
|
822
|
+
)
|
823
|
+
return JSONResponse(status_code=status.HTTP_200_OK, content=output_content)
|
824
|
+
except HTTPException as http_exception:
|
825
|
+
return JSONResponse(
|
826
|
+
status_code=http_exception.status_code, content=http_exception.detail
|
827
|
+
)
|
828
|
+
except Exception as e:
|
829
|
+
"""
|
830
|
+
rollback logic
|
831
|
+
"""
|
832
|
+
global_object_square_logger.logger.error(e, exc_info=True)
|
833
|
+
output_content = get_api_output_in_standard_format(
|
834
|
+
message=messages["GENERIC_500"],
|
835
|
+
log=str(e),
|
836
|
+
)
|
837
|
+
return JSONResponse(
|
838
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=output_content
|
839
|
+
)
|
840
|
+
|
841
|
+
|
842
|
+
@router.patch("/update_username/v0")
|
843
|
+
@global_object_square_logger.async_auto_logger
|
844
|
+
async def update_username_v0(
|
845
|
+
new_username: str,
|
846
|
+
access_token: Annotated[str, Header()],
|
847
|
+
):
|
848
|
+
try:
|
849
|
+
"""
|
850
|
+
validation
|
851
|
+
"""
|
852
|
+
# validate access token
|
853
|
+
try:
|
854
|
+
local_dict_access_token_payload = get_jwt_payload(
|
855
|
+
access_token, config_str_secret_key_for_access_token
|
856
|
+
)
|
857
|
+
except Exception as error:
|
858
|
+
output_content = get_api_output_in_standard_format(
|
859
|
+
message=messages["INCORRECT_ACCESS_TOKEN"], log=str(error)
|
860
|
+
)
|
861
|
+
return JSONResponse(
|
862
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
863
|
+
content=output_content,
|
864
|
+
)
|
865
|
+
user_id = local_dict_access_token_payload["user_id"]
|
866
|
+
|
717
867
|
# validate user_id
|
718
868
|
local_list_user_response = global_object_square_database_helper.get_rows_v0(
|
719
869
|
database_name=global_string_database_name,
|
@@ -736,62 +886,192 @@ async def logout_v0(
|
|
736
886
|
content=output_content,
|
737
887
|
)
|
738
888
|
|
739
|
-
# validate
|
740
|
-
|
741
|
-
local_dict_user = local_list_user_response[0]
|
742
|
-
local_str_user_id = local_dict_user[User.user_id.name]
|
743
|
-
local_list_user_app_response = global_object_square_database_helper.get_rows_v0(
|
889
|
+
# validate new username
|
890
|
+
local_list_user_credentials_response = global_object_square_database_helper.get_rows_v0(
|
744
891
|
database_name=global_string_database_name,
|
745
892
|
schema_name=global_string_schema_name,
|
746
|
-
table_name=
|
893
|
+
table_name=UserCredential.__tablename__,
|
747
894
|
filters=FiltersV0(
|
748
895
|
{
|
749
|
-
|
750
|
-
|
896
|
+
UserCredential.user_credential_username.name: FilterConditionsV0(
|
897
|
+
eq=new_username
|
898
|
+
),
|
751
899
|
}
|
752
900
|
),
|
753
|
-
)[
|
754
|
-
|
901
|
+
)[
|
902
|
+
"data"
|
903
|
+
][
|
904
|
+
"main"
|
905
|
+
]
|
906
|
+
if len(local_list_user_credentials_response) != 0:
|
755
907
|
output_content = get_api_output_in_standard_format(
|
756
|
-
message=messages["
|
757
|
-
log=f"
|
908
|
+
message=messages["USERNAME_ALREADY_EXISTS"],
|
909
|
+
log=f"{new_username} is taken.",
|
758
910
|
)
|
759
911
|
return JSONResponse(
|
760
|
-
status_code=status.
|
912
|
+
status_code=status.HTTP_409_CONFLICT,
|
913
|
+
content=output_content,
|
761
914
|
)
|
915
|
+
"""
|
916
|
+
main process
|
917
|
+
"""
|
918
|
+
# edit the username
|
919
|
+
global_object_square_database_helper.edit_rows_v0(
|
920
|
+
database_name=global_string_database_name,
|
921
|
+
schema_name=global_string_schema_name,
|
922
|
+
table_name=UserCredential.__tablename__,
|
923
|
+
filters=FiltersV0(
|
924
|
+
{
|
925
|
+
UserCredential.user_id.name: FilterConditionsV0(eq=user_id),
|
926
|
+
}
|
927
|
+
),
|
928
|
+
data={
|
929
|
+
UserCredential.user_credential_username.name: new_username,
|
930
|
+
},
|
931
|
+
)
|
932
|
+
"""
|
933
|
+
return value
|
934
|
+
"""
|
935
|
+
output_content = get_api_output_in_standard_format(
|
936
|
+
data={"main": {"user_id": user_id, "username": new_username}},
|
937
|
+
message=messages["GENERIC_UPDATE_SUCCESSFUL"],
|
938
|
+
)
|
939
|
+
return JSONResponse(status_code=status.HTTP_200_OK, content=output_content)
|
940
|
+
except HTTPException as http_exception:
|
941
|
+
return JSONResponse(
|
942
|
+
status_code=http_exception.status_code, content=http_exception.detail
|
943
|
+
)
|
944
|
+
except Exception as e:
|
945
|
+
"""
|
946
|
+
rollback logic
|
947
|
+
"""
|
948
|
+
global_object_square_logger.logger.error(e, exc_info=True)
|
949
|
+
output_content = get_api_output_in_standard_format(
|
950
|
+
message=messages["GENERIC_500"],
|
951
|
+
log=str(e),
|
952
|
+
)
|
953
|
+
return JSONResponse(
|
954
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=output_content
|
955
|
+
)
|
762
956
|
|
763
|
-
|
764
|
-
|
765
|
-
|
957
|
+
|
958
|
+
@router.delete("/delete_user/v0")
|
959
|
+
@global_object_square_logger.async_auto_logger
|
960
|
+
async def delete_user_v0(
|
961
|
+
body: DeleteUserV0,
|
962
|
+
access_token: Annotated[str, Header()],
|
963
|
+
):
|
964
|
+
password = body.password
|
965
|
+
try:
|
966
|
+
"""
|
967
|
+
validation
|
968
|
+
"""
|
969
|
+
# validate access token
|
970
|
+
try:
|
971
|
+
local_dict_access_token_payload = get_jwt_payload(
|
972
|
+
access_token, config_str_secret_key_for_access_token
|
973
|
+
)
|
974
|
+
except Exception as error:
|
975
|
+
output_content = get_api_output_in_standard_format(
|
976
|
+
message=messages["INCORRECT_ACCESS_TOKEN"], log=str(error)
|
977
|
+
)
|
978
|
+
return JSONResponse(
|
979
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
980
|
+
content=output_content,
|
981
|
+
)
|
982
|
+
user_id = local_dict_access_token_payload["user_id"]
|
983
|
+
|
984
|
+
# validate user_id
|
985
|
+
local_list_authentication_user_response = (
|
766
986
|
global_object_square_database_helper.get_rows_v0(
|
767
987
|
database_name=global_string_database_name,
|
768
988
|
schema_name=global_string_schema_name,
|
769
|
-
table_name=
|
989
|
+
table_name=UserCredential.__tablename__,
|
770
990
|
filters=FiltersV0(
|
771
|
-
{
|
772
|
-
UserSession.user_id.name: FilterConditionsV0(eq=user_id),
|
773
|
-
UserSession.user_session_refresh_token.name: FilterConditionsV0(
|
774
|
-
eq=refresh_token
|
775
|
-
),
|
776
|
-
UserSession.app_id.name: FilterConditionsV0(eq=app_id),
|
777
|
-
}
|
991
|
+
{UserCredential.user_id.name: FilterConditionsV0(eq=user_id)}
|
778
992
|
),
|
779
993
|
)["data"]["main"]
|
780
994
|
)
|
995
|
+
if len(local_list_authentication_user_response) != 1:
|
996
|
+
output_content = get_api_output_in_standard_format(
|
997
|
+
message=messages["INCORRECT_USER_ID"],
|
998
|
+
log=f"incorrect user_id: {user_id}.",
|
999
|
+
)
|
1000
|
+
return JSONResponse(
|
1001
|
+
status_code=status.HTTP_400_BAD_REQUEST, content=output_content
|
1002
|
+
)
|
781
1003
|
|
782
|
-
|
1004
|
+
# validate password
|
1005
|
+
local_dict_user = local_list_authentication_user_response[0]
|
1006
|
+
if not (
|
1007
|
+
bcrypt.checkpw(
|
1008
|
+
password.encode("utf-8"),
|
1009
|
+
local_dict_user[
|
1010
|
+
UserCredential.user_credential_hashed_password.name
|
1011
|
+
].encode("utf-8"),
|
1012
|
+
)
|
1013
|
+
):
|
783
1014
|
output_content = get_api_output_in_standard_format(
|
784
|
-
message=messages["
|
785
|
-
log=f"incorrect
|
1015
|
+
message=messages["INCORRECT_PASSWORD"],
|
1016
|
+
log=f"incorrect password for user_id {user_id}.",
|
786
1017
|
)
|
787
1018
|
return JSONResponse(
|
788
1019
|
status_code=status.HTTP_400_BAD_REQUEST,
|
789
1020
|
content=output_content,
|
790
1021
|
)
|
791
|
-
|
1022
|
+
"""
|
1023
|
+
main process
|
1024
|
+
"""
|
1025
|
+
# delete the user.
|
1026
|
+
global_object_square_database_helper.delete_rows_v0(
|
1027
|
+
database_name=global_string_database_name,
|
1028
|
+
schema_name=global_string_schema_name,
|
1029
|
+
table_name=User.__tablename__,
|
1030
|
+
filters=FiltersV0(
|
1031
|
+
{
|
1032
|
+
User.user_id.name: FilterConditionsV0(eq=user_id),
|
1033
|
+
}
|
1034
|
+
),
|
1035
|
+
)
|
1036
|
+
"""
|
1037
|
+
return value
|
1038
|
+
"""
|
1039
|
+
output_content = get_api_output_in_standard_format(
|
1040
|
+
message=messages["GENERIC_DELETE_SUCCESSFUL"],
|
1041
|
+
log=f"user_id: {user_id} deleted successfully.",
|
1042
|
+
)
|
1043
|
+
return JSONResponse(status_code=status.HTTP_200_OK, content=output_content)
|
1044
|
+
except HTTPException as http_exception:
|
1045
|
+
return JSONResponse(
|
1046
|
+
status_code=http_exception.status_code, content=http_exception.detail
|
1047
|
+
)
|
1048
|
+
except Exception as e:
|
1049
|
+
"""
|
1050
|
+
rollback logic
|
1051
|
+
"""
|
1052
|
+
global_object_square_logger.logger.error(e, exc_info=True)
|
1053
|
+
output_content = get_api_output_in_standard_format(
|
1054
|
+
message=messages["GENERIC_500"],
|
1055
|
+
log=str(e),
|
1056
|
+
)
|
1057
|
+
return JSONResponse(
|
1058
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=output_content
|
1059
|
+
)
|
792
1060
|
|
1061
|
+
|
1062
|
+
@router.patch("/update_password/v0")
|
1063
|
+
@global_object_square_logger.async_auto_logger
|
1064
|
+
async def update_password_v0(
|
1065
|
+
body: UpdatePasswordV0,
|
1066
|
+
access_token: Annotated[str, Header()],
|
1067
|
+
):
|
1068
|
+
old_password = body.old_password
|
1069
|
+
new_password = body.new_password
|
1070
|
+
try:
|
1071
|
+
"""
|
1072
|
+
validation
|
1073
|
+
"""
|
793
1074
|
# validate access token
|
794
|
-
# validating if the access token is valid, active, of the same user and of the provided app.
|
795
1075
|
try:
|
796
1076
|
local_dict_access_token_payload = get_jwt_payload(
|
797
1077
|
access_token, config_str_secret_key_for_access_token
|
@@ -804,53 +1084,72 @@ async def logout_v0(
|
|
804
1084
|
status_code=status.HTTP_400_BAD_REQUEST,
|
805
1085
|
content=output_content,
|
806
1086
|
)
|
807
|
-
|
1087
|
+
user_id = local_dict_access_token_payload["user_id"]
|
1088
|
+
|
1089
|
+
# validate user_id
|
1090
|
+
local_list_authentication_user_response = (
|
1091
|
+
global_object_square_database_helper.get_rows_v0(
|
1092
|
+
database_name=global_string_database_name,
|
1093
|
+
schema_name=global_string_schema_name,
|
1094
|
+
table_name=UserCredential.__tablename__,
|
1095
|
+
filters=FiltersV0(
|
1096
|
+
{UserCredential.user_id.name: FilterConditionsV0(eq=user_id)}
|
1097
|
+
),
|
1098
|
+
)["data"]["main"]
|
1099
|
+
)
|
1100
|
+
if len(local_list_authentication_user_response) != 1:
|
808
1101
|
output_content = get_api_output_in_standard_format(
|
809
|
-
message=messages["
|
810
|
-
log=f"
|
1102
|
+
message=messages["INCORRECT_USER_ID"],
|
1103
|
+
log=f"incorrect user_id: {user_id}.",
|
811
1104
|
)
|
812
1105
|
return JSONResponse(
|
813
|
-
status_code=status.HTTP_400_BAD_REQUEST,
|
814
|
-
content=output_content,
|
1106
|
+
status_code=status.HTTP_400_BAD_REQUEST, content=output_content
|
815
1107
|
)
|
816
|
-
|
1108
|
+
|
1109
|
+
# validate password
|
1110
|
+
local_dict_user = local_list_authentication_user_response[0]
|
1111
|
+
if not (
|
1112
|
+
bcrypt.checkpw(
|
1113
|
+
old_password.encode("utf-8"),
|
1114
|
+
local_dict_user[
|
1115
|
+
UserCredential.user_credential_hashed_password.name
|
1116
|
+
].encode("utf-8"),
|
1117
|
+
)
|
1118
|
+
):
|
817
1119
|
output_content = get_api_output_in_standard_format(
|
818
|
-
message=messages["
|
819
|
-
log=f"
|
1120
|
+
message=messages["INCORRECT_PASSWORD"],
|
1121
|
+
log=f"incorrect password for user_id {user_id}.",
|
820
1122
|
)
|
821
1123
|
return JSONResponse(
|
822
1124
|
status_code=status.HTTP_400_BAD_REQUEST,
|
823
1125
|
content=output_content,
|
824
1126
|
)
|
825
|
-
# ======================================================================================
|
826
|
-
|
827
|
-
# NOTE: if both access token and refresh token have expired for a user,
|
828
|
-
# it can be assumed that user session only needs to be removed from the front end.
|
829
|
-
|
830
|
-
# ======================================================================================
|
831
1127
|
"""
|
832
1128
|
main process
|
833
1129
|
"""
|
834
|
-
# delete
|
835
|
-
|
1130
|
+
# delete the user.
|
1131
|
+
local_str_hashed_password = bcrypt.hashpw(
|
1132
|
+
new_password.encode("utf-8"), bcrypt.gensalt()
|
1133
|
+
).decode("utf-8")
|
1134
|
+
global_object_square_database_helper.edit_rows_v0(
|
836
1135
|
database_name=global_string_database_name,
|
837
1136
|
schema_name=global_string_schema_name,
|
838
|
-
table_name=
|
1137
|
+
table_name=UserCredential.__tablename__,
|
839
1138
|
filters=FiltersV0(
|
840
1139
|
{
|
841
|
-
|
842
|
-
UserSession.user_session_refresh_token.name: FilterConditionsV0(
|
843
|
-
eq=refresh_token
|
844
|
-
),
|
845
|
-
UserSession.app_id.name: FilterConditionsV0(eq=app_id),
|
1140
|
+
UserCredential.user_id.name: FilterConditionsV0(eq=user_id),
|
846
1141
|
}
|
847
1142
|
),
|
1143
|
+
data={
|
1144
|
+
UserCredential.user_credential_hashed_password.name: local_str_hashed_password,
|
1145
|
+
},
|
848
1146
|
)
|
849
1147
|
"""
|
850
1148
|
return value
|
851
1149
|
"""
|
852
1150
|
output_content = get_api_output_in_standard_format(
|
853
|
-
message=messages["
|
1151
|
+
message=messages["GENERIC_UPDATE_SUCCESSFUL"],
|
1152
|
+
log=f"password for user_id: {user_id} updated successfully.",
|
854
1153
|
)
|
855
1154
|
return JSONResponse(status_code=status.HTTP_200_OK, content=output_content)
|
856
1155
|
except HTTPException as http_exception:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: square-authentication
|
3
|
-
Version:
|
3
|
+
Version: 3.0.0
|
4
4
|
Summary: authentication layer for my personal server.
|
5
5
|
Home-page: https://github.com/thepmsquare/square_authentication
|
6
6
|
Author: thePmSquare
|
@@ -43,6 +43,19 @@ pip install square_authentication
|
|
43
43
|
|
44
44
|
## changelog
|
45
45
|
|
46
|
+
### v3.0.0
|
47
|
+
|
48
|
+
- added new endpoints
|
49
|
+
- /update_username/v0
|
50
|
+
- /delete_user/v0
|
51
|
+
- /update_password/v0
|
52
|
+
- move data in password related endpoints to request body from params.
|
53
|
+
- /register_username/v0 now takes in app_id as optional parameter to assign user to that app and create session for it.
|
54
|
+
- /generate_access_token/v0 now only needs refresh token (removed validation).
|
55
|
+
- /logout/v0 now only needs refresh token (removed validation).
|
56
|
+
- /update_user_app_ids/v0 now only updates ids for self (user). added access token as input param and removed user_id.
|
57
|
+
- /get_user_app_ids/v0 is now /get_user_details/v0 with access token as the only input param.
|
58
|
+
|
46
59
|
### v2.0.0
|
47
60
|
|
48
61
|
- authentication module needs to be used across applications so
|
@@ -1,15 +1,17 @@
|
|
1
1
|
square_authentication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
square_authentication/configuration.py,sha256=i0uNtNSQd-n1rBxFM6jsIz1Wy3d090RcdTViSqHKc7Y,2973
|
3
3
|
square_authentication/main.py,sha256=JK9KBmN73KL8EpKrXrjrwwf37bmC4AXrFHtfl2roYwQ,1636
|
4
|
-
square_authentication/messages.py,sha256=
|
4
|
+
square_authentication/messages.py,sha256=BA9KC0vW9UD1ZXT4VneVqVNLlgdbMdsAwAgxhJISLf4,1175
|
5
5
|
square_authentication/data/config.ini,sha256=_740RvKpL5W2bUDGwZ7ePwuP-mAasr5cXXB81yq_Jv8,906
|
6
|
+
square_authentication/pydantic_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
square_authentication/pydantic_models/core.py,sha256=Bd6BPFPCV5PPA0KDKXUghIpoQA_w9MCSMY6ldSxM1qw,388
|
6
8
|
square_authentication/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
square_authentication/routes/core.py,sha256=
|
9
|
+
square_authentication/routes/core.py,sha256=ijTmFDi8wg0oFycQRqxpXk4j4t6IqXq0FHffjecAnkQ,43303
|
8
10
|
square_authentication/routes/utility.py,sha256=Kx4S4tZ1GKsPoC8CoZ4fkLEebvr02KeFEPePtTHtpnQ,75
|
9
11
|
square_authentication/utils/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
10
12
|
square_authentication/utils/encryption.py,sha256=T6BShoUr_xeGpbfPgTK-GxTlXPwcjwU4c4KW7KPzrF8,1865
|
11
13
|
square_authentication/utils/token.py,sha256=Y_arg5LegX-aprMj9YweUK8jjNZLGDjLUGgxbUA12w4,560
|
12
|
-
square_authentication-
|
13
|
-
square_authentication-
|
14
|
-
square_authentication-
|
15
|
-
square_authentication-
|
14
|
+
square_authentication-3.0.0.dist-info/METADATA,sha256=6ahIoM0u8VAAGmp48nmRWwNMBj9tnN5X2q8oMr-G3Tc,2622
|
15
|
+
square_authentication-3.0.0.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
16
|
+
square_authentication-3.0.0.dist-info/top_level.txt,sha256=wDssVJIl9KIEJPj5rR3rv4uRI7yCndMBrvHd_6BGXQA,22
|
17
|
+
square_authentication-3.0.0.dist-info/RECORD,,
|
File without changes
|
{square_authentication-2.0.0.dist-info → square_authentication-3.0.0.dist-info}/top_level.txt
RENAMED
File without changes
|