square-authentication 5.1.5__py3-none-any.whl → 6.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.
@@ -2,6 +2,8 @@ import os
2
2
  import sys
3
3
 
4
4
  from square_commons import ConfigReader
5
+ from square_database_helper import SquareDatabaseHelper
6
+ from square_file_store_helper import SquareFileStoreHelper
5
7
  from square_logger.main import SquareLogger
6
8
 
7
9
  try:
@@ -67,6 +69,20 @@ try:
67
69
  ldict_configuration["SQUARE_DATABASE_HELPER"]["SQUARE_DATABASE_PORT"]
68
70
  )
69
71
  # ===========================================
72
+
73
+ # ===========================================
74
+ # square_file_store_helper
75
+
76
+ config_str_square_file_store_protocol = ldict_configuration[
77
+ "SQUARE_FILE_STORE_HELPER"
78
+ ]["SQUARE_FILE_STORE_PROTOCOL"]
79
+ config_str_square_file_store_ip = ldict_configuration["SQUARE_FILE_STORE_HELPER"][
80
+ "SQUARE_FILE_STORE_IP"
81
+ ]
82
+ config_int_square_file_store_port = int(
83
+ ldict_configuration["SQUARE_FILE_STORE_HELPER"]["SQUARE_FILE_STORE_PORT"]
84
+ )
85
+ # ===========================================
70
86
  # Initialize logger
71
87
  global_object_square_logger = SquareLogger(
72
88
  pstr_log_file_name=config_str_log_file_name,
@@ -74,6 +90,16 @@ try:
74
90
  pstr_log_path=config_str_log_path,
75
91
  pint_log_backup_count=config_int_log_backup_count,
76
92
  )
93
+ global_object_square_database_helper = SquareDatabaseHelper(
94
+ param_str_square_database_ip=config_str_square_database_ip,
95
+ param_int_square_database_port=config_int_square_database_port,
96
+ param_str_square_database_protocol=config_str_square_database_protocol,
97
+ )
98
+ global_object_square_file_store_helper = SquareFileStoreHelper(
99
+ param_str_square_file_store_protocol=config_str_square_file_store_protocol,
100
+ param_str_square_file_store_ip=config_str_square_file_store_ip,
101
+ param_int_square_file_store_port=config_int_square_file_store_port,
102
+ )
77
103
  except Exception as e:
78
104
  print(
79
105
  "\033[91mMissing or incorrect config.ini file.\n"
@@ -39,4 +39,10 @@ LOG_BACKUP_COUNT = 3
39
39
 
40
40
  SQUARE_DATABASE_PROTOCOL = http
41
41
  SQUARE_DATABASE_IP = localhost
42
- SQUARE_DATABASE_PORT = 10010
42
+ SQUARE_DATABASE_PORT = 10010
43
+
44
+ [SQUARE_FILE_STORE_HELPER]
45
+
46
+ SQUARE_FILE_STORE_PROTOCOL = http
47
+ SQUARE_FILE_STORE_IP = localhost
48
+ SQUARE_FILE_STORE_PORT = 10100
@@ -14,7 +14,7 @@ from square_authentication.configuration import (
14
14
  config_str_ssl_key_file_path,
15
15
  config_str_ssl_crt_file_path,
16
16
  )
17
- from square_authentication.routes import core, utility
17
+ from square_authentication.routes import core, utility, profile
18
18
 
19
19
  app = FastAPI()
20
20
 
@@ -28,6 +28,7 @@ app.add_middleware(
28
28
 
29
29
  app.include_router(core.router)
30
30
  app.include_router(utility.router)
31
+ app.include_router(profile.router)
31
32
 
32
33
 
33
34
  @app.get("/")
@@ -14,4 +14,6 @@ messages = {
14
14
  "GENERIC_DELETE_SUCCESSFUL": "your records have been deleted successfully.",
15
15
  "GENERIC_400": "the request is invalid or cannot be processed.",
16
16
  "GENERIC_500": "an internal server error occurred. please try again later.",
17
+ "INVALID_FILE_FORMAT": "the file format is not supported. please upload a valid file.",
18
+ "FILE_SIZE_EXCEEDS_LIMIT": "the file size exceeds the limit. please upload a smaller file.",
17
19
  }
@@ -1,3 +1,4 @@
1
+ import copy
1
2
  from datetime import datetime, timedelta, timezone
2
3
  from typing import Annotated, List
3
4
 
@@ -8,7 +9,6 @@ from fastapi.params import Query
8
9
  from fastapi.responses import JSONResponse
9
10
  from requests import HTTPError
10
11
  from square_commons import get_api_output_in_standard_format
11
- from square_database_helper.main import SquareDatabaseHelper
12
12
  from square_database_helper.pydantic_models import FilterConditionsV0, FiltersV0
13
13
  from square_database_structure.square import global_string_database_name
14
14
  from square_database_structure.square.authentication import global_string_schema_name
@@ -27,12 +27,10 @@ from square_database_structure.square.public.tables import App
27
27
  from square_authentication.configuration import (
28
28
  config_int_access_token_valid_minutes,
29
29
  config_int_refresh_token_valid_minutes,
30
- config_int_square_database_port,
31
30
  config_str_secret_key_for_access_token,
32
31
  config_str_secret_key_for_refresh_token,
33
- config_str_square_database_ip,
34
- config_str_square_database_protocol,
35
32
  global_object_square_logger,
33
+ global_object_square_database_helper,
36
34
  )
37
35
  from square_authentication.messages import messages
38
36
  from square_authentication.pydantic_models.core import (
@@ -49,12 +47,6 @@ router = APIRouter(
49
47
  tags=["core"],
50
48
  )
51
49
 
52
- global_object_square_database_helper = SquareDatabaseHelper(
53
- param_str_square_database_ip=config_str_square_database_ip,
54
- param_int_square_database_port=config_int_square_database_port,
55
- param_str_square_database_protocol=config_str_square_database_protocol,
56
- )
57
-
58
50
 
59
51
  @router.post("/register_username/v0")
60
52
  @global_object_square_logger.auto_logger()
@@ -311,16 +303,14 @@ async def get_user_details_v0(
311
303
  ),
312
304
  )["data"]["main"]
313
305
  )
306
+ user_profile = copy.deepcopy(local_list_response_user_profile[0])
307
+ del user_profile[UserProfile.user_id.name]
314
308
  """
315
309
  return value
316
310
  """
317
311
  return_this = {
318
312
  "user_id": user_id,
319
- "credentials": {
320
- "username": local_list_response_user_profile[0][
321
- UserProfile.user_profile_username.name
322
- ],
323
- },
313
+ "profile": user_profile,
324
314
  "apps": [
325
315
  y[App.app_name.name]
326
316
  for y in local_list_app
@@ -0,0 +1,134 @@
1
+ import os
2
+ from typing import Annotated
3
+
4
+ from fastapi import APIRouter, HTTPException, status, Header, UploadFile
5
+ from fastapi.responses import JSONResponse
6
+ from square_commons import get_api_output_in_standard_format
7
+ from square_database_helper import FiltersV0
8
+ from square_database_helper.pydantic_models import FilterConditionsV0
9
+ from square_database_structure.square import global_string_database_name
10
+ from square_database_structure.square.authentication import global_string_schema_name
11
+ from square_database_structure.square.authentication.tables import UserProfile
12
+
13
+ from square_authentication.configuration import (
14
+ global_object_square_logger,
15
+ config_str_secret_key_for_access_token,
16
+ global_object_square_file_store_helper,
17
+ global_object_square_database_helper,
18
+ )
19
+ from square_authentication.messages import messages
20
+ from square_authentication.utils.token import get_jwt_payload
21
+
22
+ router = APIRouter(
23
+ tags=["profile"],
24
+ )
25
+
26
+
27
+ @router.patch("/update_profile_photo/v0")
28
+ @global_object_square_logger.auto_logger()
29
+ async def update_profile_photo_v0(
30
+ access_token: Annotated[str, Header()],
31
+ profile_photo: UploadFile,
32
+ ):
33
+
34
+ try:
35
+ """
36
+ validation
37
+ """
38
+ # validate access token
39
+ try:
40
+ local_dict_access_token_payload = get_jwt_payload(
41
+ access_token, config_str_secret_key_for_access_token
42
+ )
43
+ except Exception as error:
44
+ output_content = get_api_output_in_standard_format(
45
+ message=messages["INCORRECT_ACCESS_TOKEN"], log=str(error)
46
+ )
47
+ raise HTTPException(
48
+ status_code=status.HTTP_400_BAD_REQUEST,
49
+ detail=output_content,
50
+ )
51
+ user_id = local_dict_access_token_payload["user_id"]
52
+
53
+ # validate file format
54
+ if not profile_photo.filename.endswith((".jpg", ".jpeg", ".png")):
55
+ output_content = get_api_output_in_standard_format(
56
+ message=messages["INVALID_FILE_FORMAT"]
57
+ )
58
+ raise HTTPException(
59
+ status_code=status.HTTP_400_BAD_REQUEST,
60
+ detail=output_content,
61
+ )
62
+
63
+ # validate file size
64
+ file_size_limit_in_mib = 5
65
+ if profile_photo.size > (file_size_limit_in_mib * 1024 * 1024):
66
+ output_content = get_api_output_in_standard_format(
67
+ message=messages["FILE_SIZE_EXCEEDS_LIMIT"]
68
+ )
69
+ raise HTTPException(
70
+ status_code=status.HTTP_400_BAD_REQUEST,
71
+ detail=output_content,
72
+ )
73
+ """
74
+ main process
75
+ """
76
+ # uploading to square file store
77
+ destination_path = f"temp/{user_id}/profile_photo/{profile_photo.filename}"
78
+ os.makedirs(os.path.dirname(destination_path), exist_ok=True)
79
+ with open(destination_path, "wb") as out_file:
80
+ content = await profile_photo.read()
81
+ out_file.write(content)
82
+
83
+ file_upload_response = (
84
+ global_object_square_file_store_helper.upload_file_using_file_path_v0(
85
+ file_path=destination_path,
86
+ system_relative_path="global/users/profile_photos",
87
+ )
88
+ )
89
+ os.remove(destination_path)
90
+
91
+ # adding file storage token to user profile
92
+ profile_update_response = global_object_square_database_helper.edit_rows_v0(
93
+ data={
94
+ UserProfile.user_profile_photo_storage_token.name: file_upload_response[
95
+ "data"
96
+ ]["main"]
97
+ },
98
+ filters=FiltersV0(
99
+ {UserProfile.user_id.name: FilterConditionsV0(eq=user_id)}
100
+ ),
101
+ database_name=global_string_database_name,
102
+ schema_name=global_string_schema_name,
103
+ table_name=UserProfile.__tablename__,
104
+ apply_filters=True,
105
+ )
106
+
107
+ """
108
+ return value
109
+ """
110
+ output_content = get_api_output_in_standard_format(
111
+ data=profile_update_response["data"],
112
+ message=messages["GENERIC_UPDATE_SUCCESSFUL"],
113
+ )
114
+ return JSONResponse(
115
+ status_code=status.HTTP_200_OK,
116
+ content=output_content,
117
+ )
118
+ except HTTPException as http_exception:
119
+ global_object_square_logger.logger.error(http_exception, exc_info=True)
120
+ return JSONResponse(
121
+ status_code=http_exception.status_code, content=http_exception.detail
122
+ )
123
+ except Exception as e:
124
+ """
125
+ rollback logic
126
+ """
127
+ global_object_square_logger.logger.error(e, exc_info=True)
128
+ output_content = get_api_output_in_standard_format(
129
+ message=messages["GENERIC_500"],
130
+ log=str(e),
131
+ )
132
+ return JSONResponse(
133
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=output_content
134
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: square_authentication
3
- Version: 5.1.5
3
+ Version: 6.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
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.9
13
13
  Description-Content-Type: text/markdown
14
14
  Requires-Dist: uvicorn>=0.24.0.post1
15
15
  Requires-Dist: fastapi>=0.104.1
16
+ Requires-Dist: python-multipart>=0.0.6
16
17
  Requires-Dist: pydantic>=2.5.3
17
18
  Requires-Dist: bcrypt>=4.1.2
18
19
  Requires-Dist: pyjwt>=2.8.0
@@ -22,6 +23,7 @@ Requires-Dist: square_commons>=1.0.0
22
23
  Requires-Dist: square_logger>=2.0.0
23
24
  Requires-Dist: square_database_helper>=2.0.0
24
25
  Requires-Dist: square_database_structure>=2.3.1
26
+ Requires-Dist: square_file_store_helper>=2.1.0
25
27
  Requires-Dist: pytest>=8.0.0
26
28
  Requires-Dist: httpx>=0.27.2
27
29
  Dynamic: author
@@ -51,6 +53,22 @@ pip install square_authentication
51
53
 
52
54
  ## changelog
53
55
 
56
+ ### v6.0.0
57
+
58
+ - add profile details in get_user_details_v0 instead of credentials keyword.
59
+
60
+ ### v5.2.0
61
+
62
+ - add temp folder to .gitignore.
63
+ - add square_file_store_helper as a dependency.
64
+ - config
65
+ - add config section for file store helper.
66
+ - initialise file store helper and database helper in config.py
67
+ - add profile router
68
+ - profile
69
+ - add update_profile_photo/v0
70
+ - update messages.
71
+
54
72
  ### v5.1.5
55
73
 
56
74
  - bump square_logger to >=2.0.0.
@@ -1,17 +1,18 @@
1
1
  square_authentication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- square_authentication/configuration.py,sha256=i0uNtNSQd-n1rBxFM6jsIz1Wy3d090RcdTViSqHKc7Y,2973
3
- square_authentication/main.py,sha256=zP8Affuljk1m7fsRSa1WG8KP0xdcVgOvA-62bWlLe4s,1660
4
- square_authentication/messages.py,sha256=BA9KC0vW9UD1ZXT4VneVqVNLlgdbMdsAwAgxhJISLf4,1175
5
- square_authentication/data/config.ini,sha256=_740RvKpL5W2bUDGwZ7ePwuP-mAasr5cXXB81yq_Jv8,906
2
+ square_authentication/configuration.py,sha256=AvwARscNVNFdiblu01zxhqwQ2OuKPasaTU_YqZ7pzyc,4211
3
+ square_authentication/main.py,sha256=zADc2vmV8yDylmbihj4FzLDEs5b-9nItFoB5c4AoKGk,1704
4
+ square_authentication/messages.py,sha256=vhcl4bw8Ar1npiErjGh3kkNPmW1rmDRtf6rKn5JF8W8,1364
5
+ square_authentication/data/config.ini,sha256=xkKVlwqspOE8z55ty15ERbZcNVkMOuxF_rLHluNYzVs,1033
6
6
  square_authentication/pydantic_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  square_authentication/pydantic_models/core.py,sha256=qeNETcJv7mnRKGhATOW2bg0NlHuyzvot1dZ1b1qqhwU,610
8
8
  square_authentication/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- square_authentication/routes/core.py,sha256=nfATWJ3NWQkCe9gmMhJIh1lsdxmiCQ1OL3HoqIhFd88,57195
9
+ square_authentication/routes/core.py,sha256=Ui2kJI3DHK1tsb4_cCle8iurZlU__O_nptk2-YLZ2vg,56778
10
+ square_authentication/routes/profile.py,sha256=YkApDwsSL4KDKdT5uHDqdpSmTEhPgRkJ6bTQkf5sj9Q,4879
10
11
  square_authentication/routes/utility.py,sha256=KDr8KdkT0jAGPjfP-b5XXYG7p49WU7J1FiK6oSIckQI,1779
11
12
  square_authentication/utils/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
12
13
  square_authentication/utils/encryption.py,sha256=WakaiEAgWpTJltxBzqOtv81_DCDKfzJqt60fWSPoNvo,2027
13
14
  square_authentication/utils/token.py,sha256=t-RPBY4cYyT1ro3lkLBTOy2BeRGBfluBVBivL5DLmDg,680
14
- square_authentication-5.1.5.dist-info/METADATA,sha256=0GDaWp1LZIJ1WGH1_r-uf0GhBgfuERwosV8hzZ8wl0s,4258
15
- square_authentication-5.1.5.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
16
- square_authentication-5.1.5.dist-info/top_level.txt,sha256=wDssVJIl9KIEJPj5rR3rv4uRI7yCndMBrvHd_6BGXQA,22
17
- square_authentication-5.1.5.dist-info/RECORD,,
15
+ square_authentication-6.0.0.dist-info/METADATA,sha256=diCuuGBkXdBe3l2ArU7R1M6dB-BwAox2bdzdDb-MC8o,4733
16
+ square_authentication-6.0.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
17
+ square_authentication-6.0.0.dist-info/top_level.txt,sha256=wDssVJIl9KIEJPj5rR3rv4uRI7yCndMBrvHd_6BGXQA,22
18
+ square_authentication-6.0.0.dist-info/RECORD,,