From 7e393cb8ecadefa3c74f9073b21bb1dae8880761 Mon Sep 17 00:00:00 2001 From: BombinBM Date: Sat, 26 Oct 2024 20:49:57 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=D0=BB=D0=B8=D1=87=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=BA=D0=BE=D1=83=D0=BF=D0=B0=20print.file.send?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В коде добавил опциональность для ввода номера билета, а так же проверку на наличие скоупа внутри имеющихся у юзера. в выводе оставил только имя юзера. --- print_service/routes/user.py | 51 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/print_service/routes/user.py b/print_service/routes/user.py index 7cd7743..4096a1f 100644 --- a/print_service/routes/user.py +++ b/print_service/routes/user.py @@ -46,34 +46,41 @@ class UpdateUserList(BaseModel): ) async def check_union_member( surname: constr(strip_whitespace=True, to_upper=True, min_length=1), - number: constr(strip_whitespace=True, to_upper=True, min_length=1), + number: Optional[str] = constr(strip_whitespace=True, to_upper=True, min_length=1), + # scope: scope = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True)), + user = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True)), v: Optional[str] = __version__, ): """Проверяет наличие пользователя в списке.""" - surname = surname.upper() - user = db.session.query(UnionMember) - if not settings.ALLOW_STUDENT_NUMBER: - user = user.filter(UnionMember.union_number != None) - user: UnionMember = user.filter( - or_( - func.upper(UnionMember.student_number) == number, - func.upper(UnionMember.union_number) == number, - ), - func.upper(UnionMember.surname) == surname, - ).one_or_none() - - if v == '1': - return bool(user) - - if not user: - raise UserNotFound() - else: + if "print.file.send" in [scope["name"] for scope in user.get('session_scopes')]: return { 'surname': user.surname, - 'number': number, - 'student_number': user.student_number, - 'union_number': user.union_number, } + else: + surname = surname.upper() + user = db.session.query(UnionMember) + if not settings.ALLOW_STUDENT_NUMBER: + user = user.filter(UnionMember.union_number != None) + user: UnionMember = user.filter( + or_( + func.upper(UnionMember.student_number) == number, + func.upper(UnionMember.union_number) == number, + ), + func.upper(UnionMember.surname) == surname, + ).one_or_none() + + if v == '1': + return bool(user) + + if not user: + raise UserNotFound() + else: + return { + 'surname': user.surname, + 'number': number, + 'student_number': user.student_number, + 'union_number': user.union_number, + } @router.post('/is_union_member') From 0806500dd081581bbbb57a405654719c33c64dd8 Mon Sep 17 00:00:00 2001 From: BombinBM Date: Sat, 16 Nov 2024 01:47:25 +0300 Subject: [PATCH 2/8] =?UTF-8?q?=D0=92=D0=B5=D1=80=D0=BD=D1=83=D0=BB=20chec?= =?UTF-8?q?k=5Funion=5Fmember=20=D0=B8=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=BB=20file=5Fsend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В POST запросе check_union_member вернул код в состояние до первого комита. Для функции send написал одну дополнительную функцию, чтоб проверять наличие скоупа через Depends, добавил опциональный ввод поля number и проверку его наличия уже в самой функции send --- print_service/routes/file.py | 35 +++++++++++++++++-------- print_service/routes/user.py | 50 ++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 5205e0f..78e77e2 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -4,6 +4,7 @@ import aiofiles import aiofiles.os +from auth_lib.fastapi import UnionAuth from fastapi import APIRouter, File, UploadFile from fastapi.exceptions import HTTPException from fastapi.params import Depends @@ -63,7 +64,8 @@ class SendInput(BaseModel): description='Фамилия', example='Иванов', ) - number: str = Field( + number: str | None = Field( + default=None, description='Номер профсоюзного или студенческого билетов', example='1015000', ) @@ -96,7 +98,8 @@ class ReceiveOutput(BaseModel): # endregion - +def has_send_scope(union_auth: UnionAuth = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True))): + return union_auth is not None # region handlers @router.post( @@ -107,21 +110,33 @@ class ReceiveOutput(BaseModel): }, response_model=SendOutput, ) -async def send(inp: SendInput, settings: Settings = Depends(get_settings)): +async def send(inp: SendInput, + has_send_scope: bool = Depends(has_send_scope), + settings: Settings = Depends(get_settings), +): """Получить пин код для загрузки и скачивания файла. Полученный пин-код можно использовать в методах POST и GET `/file/{pin}`. """ + if not has_send_scope and inp.number is None: + raise HTTPException(status_code=400, detail="Поле number обязательно для пользователей без скоупа print.file.send") + + user = db.session.query(UnionMember) if not settings.ALLOW_STUDENT_NUMBER: user = user.filter(UnionMember.union_number != None) - user = user.filter( - or_( - func.upper(UnionMember.student_number) == inp.number.upper(), - func.upper(UnionMember.union_number) == inp.number.upper(), - ), - func.upper(UnionMember.surname) == inp.surname.upper(), - ).one_or_none() + if inp.number is not None: + user = user.filter( + or_( + func.upper(UnionMember.student_number) == inp.number.upper(), + func.upper(UnionMember.union_number) == inp.number.upper(), + ), + func.upper(UnionMember.surname) == inp.surname.upper(), + ).one_or_none() + else: + user = user.filter( + func.upper(UnionMember.surname) == inp.surname.upper(), + ) if not user: raise NotInUnion() try: diff --git a/print_service/routes/user.py b/print_service/routes/user.py index 4096a1f..9becd3b 100644 --- a/print_service/routes/user.py +++ b/print_service/routes/user.py @@ -47,40 +47,34 @@ class UpdateUserList(BaseModel): async def check_union_member( surname: constr(strip_whitespace=True, to_upper=True, min_length=1), number: Optional[str] = constr(strip_whitespace=True, to_upper=True, min_length=1), - # scope: scope = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True)), - user = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True)), v: Optional[str] = __version__, ): """Проверяет наличие пользователя в списке.""" - if "print.file.send" in [scope["name"] for scope in user.get('session_scopes')]: + + surname = surname.upper() + user = db.session.query(UnionMember) + if not settings.ALLOW_STUDENT_NUMBER: + user = user.filter(UnionMember.union_number != None) + user: UnionMember = user.filter( + or_( + func.upper(UnionMember.student_number) == number, + func.upper(UnionMember.union_number) == number, + ), + func.upper(UnionMember.surname) == surname, + ).one_or_none() + + if v == '1': + return bool(user) + + if not user: + raise UserNotFound() + else: return { 'surname': user.surname, + 'number': number, + 'student_number': user.student_number, + 'union_number': user.union_number, } - else: - surname = surname.upper() - user = db.session.query(UnionMember) - if not settings.ALLOW_STUDENT_NUMBER: - user = user.filter(UnionMember.union_number != None) - user: UnionMember = user.filter( - or_( - func.upper(UnionMember.student_number) == number, - func.upper(UnionMember.union_number) == number, - ), - func.upper(UnionMember.surname) == surname, - ).one_or_none() - - if v == '1': - return bool(user) - - if not user: - raise UserNotFound() - else: - return { - 'surname': user.surname, - 'number': number, - 'student_number': user.student_number, - 'union_number': user.union_number, - } @router.post('/is_union_member') From bddbf23f7a371ee8471cee2f1a9258841bdf0efd Mon Sep 17 00:00:00 2001 From: BombinBM Date: Sat, 16 Nov 2024 02:11:03 +0300 Subject: [PATCH 3/8] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20blac?= =?UTF-8?q?k=20.=20isort=20.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- print_service/routes/file.py | 18 ++++++++++++------ print_service/routes/user.py | 8 ++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 78e77e2..65f341d 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -98,9 +98,12 @@ class ReceiveOutput(BaseModel): # endregion -def has_send_scope(union_auth: UnionAuth = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True))): +def has_send_scope( + union_auth: UnionAuth = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True)) +): return union_auth is not None + # region handlers @router.post( '', @@ -110,17 +113,20 @@ def has_send_scope(union_auth: UnionAuth = Depends(UnionAuth(scopes=["print.file }, response_model=SendOutput, ) -async def send(inp: SendInput, - has_send_scope: bool = Depends(has_send_scope), - settings: Settings = Depends(get_settings), +async def send( + inp: SendInput, + has_send_scope: bool = Depends(has_send_scope), + settings: Settings = Depends(get_settings), ): """Получить пин код для загрузки и скачивания файла. Полученный пин-код можно использовать в методах POST и GET `/file/{pin}`. """ if not has_send_scope and inp.number is None: - raise HTTPException(status_code=400, detail="Поле number обязательно для пользователей без скоупа print.file.send") - + raise HTTPException( + status_code=400, + detail="Поле number обязательно для пользователей без скоупа print.file.send", + ) user = db.session.query(UnionMember) if not settings.ALLOW_STUDENT_NUMBER: diff --git a/print_service/routes/user.py b/print_service/routes/user.py index 9becd3b..cc77810 100644 --- a/print_service/routes/user.py +++ b/print_service/routes/user.py @@ -56,10 +56,10 @@ async def check_union_member( if not settings.ALLOW_STUDENT_NUMBER: user = user.filter(UnionMember.union_number != None) user: UnionMember = user.filter( - or_( - func.upper(UnionMember.student_number) == number, - func.upper(UnionMember.union_number) == number, - ), + or_( + func.upper(UnionMember.student_number) == number, + func.upper(UnionMember.union_number) == number, + ), func.upper(UnionMember.surname) == surname, ).one_or_none() From c176e5bd4a75ad489a2c20ef0e58da6490c30a49 Mon Sep 17 00:00:00 2001 From: Bogdan <164235653+BombinBM@users.noreply.github.com> Date: Sat, 23 Nov 2024 21:31:25 +0300 Subject: [PATCH 4/8] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=BE=D1=88=D0=B8=D0=B1?= =?UTF-8?q?=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- print_service/routes/file.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 65f341d..c65fd90 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -123,10 +123,7 @@ async def send( Полученный пин-код можно использовать в методах POST и GET `/file/{pin}`. """ if not has_send_scope and inp.number is None: - raise HTTPException( - status_code=400, - detail="Поле number обязательно для пользователей без скоупа print.file.send", - ) + raise NotInUnion() user = db.session.query(UnionMember) if not settings.ALLOW_STUDENT_NUMBER: From e10bd4ca6feab1822249f5288268cfb03c9b9c37 Mon Sep 17 00:00:00 2001 From: Bogdan <164235653+BombinBM@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:59:44 +0300 Subject: [PATCH 5/8] Update file.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сделал все для ревью --- print_service/routes/file.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index c65fd90..67b844e 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -98,10 +98,6 @@ class ReceiveOutput(BaseModel): # endregion -def has_send_scope( - union_auth: UnionAuth = Depends(UnionAuth(scopes=["print.file.send"], allow_none=True)) -): - return union_auth is not None # region handlers @@ -114,8 +110,8 @@ def has_send_scope( response_model=SendOutput, ) async def send( - inp: SendInput, - has_send_scope: bool = Depends(has_send_scope), + inp: SendInput, + _ = Depends(UnionAuth(scopes=["print.file.send"]), allow_none=True), settings: Settings = Depends(get_settings), ): """Получить пин код для загрузки и скачивания файла. @@ -128,6 +124,7 @@ async def send( user = db.session.query(UnionMember) if not settings.ALLOW_STUDENT_NUMBER: user = user.filter(UnionMember.union_number != None) + if inp.number is not None: user = user.filter( or_( @@ -137,9 +134,9 @@ async def send( func.upper(UnionMember.surname) == inp.surname.upper(), ).one_or_none() else: - user = user.filter( - func.upper(UnionMember.surname) == inp.surname.upper(), - ) + if not "print.file.send" in [scope["name"] for scope in user.get('session_scopes')]: + raise NotInUnion() + if not user: raise NotInUnion() try: From bc7a10195c4500949beb8a7e04eac18f14b118b9 Mon Sep 17 00:00:00 2001 From: BombinBM Date: Wed, 4 Dec 2024 14:06:29 +0300 Subject: [PATCH 6/8] Update file.py --- print_service/routes/file.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 67b844e..dd3492c 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -110,8 +110,8 @@ class ReceiveOutput(BaseModel): response_model=SendOutput, ) async def send( - inp: SendInput, - _ = Depends(UnionAuth(scopes=["print.file.send"]), allow_none=True), + inp: SendInput, + _=Depends(UnionAuth(scopes=["print.file.send"]), allow_none=True), settings: Settings = Depends(get_settings), ): """Получить пин код для загрузки и скачивания файла. @@ -136,7 +136,7 @@ async def send( else: if not "print.file.send" in [scope["name"] for scope in user.get('session_scopes')]: raise NotInUnion() - + if not user: raise NotInUnion() try: From 76d631d9a73b0d02eeef436d236a903bcc52f91c Mon Sep 17 00:00:00 2001 From: BombinBM Date: Thu, 12 Dec 2024 18:43:01 +0300 Subject: [PATCH 7/8] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D0=BE=D1=82=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=87=D0=B5=D0=BD=D0=BD=D0=BE=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Осталось только разобраться с базой данных и тестами --- print_service/routes/file.py | 11 ++++++----- print_service/routes/user.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index dd3492c..35364dc 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -60,7 +60,8 @@ def validate_pages(cls, value: str): class SendInput(BaseModel): - surname: str = Field( + surname: str | None = Field( + default=None, description='Фамилия', example='Иванов', ) @@ -111,7 +112,7 @@ class ReceiveOutput(BaseModel): ) async def send( inp: SendInput, - _=Depends(UnionAuth(scopes=["print.file.send"]), allow_none=True), + user_auth=Depends(UnionAuth(scopes=["print.file.send"])), settings: Settings = Depends(get_settings), ): """Получить пин код для загрузки и скачивания файла. @@ -125,7 +126,7 @@ async def send( if not settings.ALLOW_STUDENT_NUMBER: user = user.filter(UnionMember.union_number != None) - if inp.number is not None: + if inp.number is not None and inp.surname is not None: user = user.filter( or_( func.upper(UnionMember.student_number) == inp.number.upper(), @@ -134,10 +135,10 @@ async def send( func.upper(UnionMember.surname) == inp.surname.upper(), ).one_or_none() else: - if not "print.file.send" in [scope["name"] for scope in user.get('session_scopes')]: + if not "print.file.send" in [scope["name"] for scope in user_auth.get('session_scopes')]: raise NotInUnion() - if not user: + if user is None: raise NotInUnion() try: pin = generate_pin(db.session) diff --git a/print_service/routes/user.py b/print_service/routes/user.py index cc77810..34a3a3c 100644 --- a/print_service/routes/user.py +++ b/print_service/routes/user.py @@ -46,7 +46,7 @@ class UpdateUserList(BaseModel): ) async def check_union_member( surname: constr(strip_whitespace=True, to_upper=True, min_length=1), - number: Optional[str] = constr(strip_whitespace=True, to_upper=True, min_length=1), + number: constr(strip_whitespace=True, to_upper=True, min_length=1), v: Optional[str] = __version__, ): """Проверяет наличие пользователя в списке.""" From 42764aedae626a79c8e91a542187d4fb78cda67d Mon Sep 17 00:00:00 2001 From: BombinBM Date: Mon, 16 Dec 2024 21:48:35 +0300 Subject: [PATCH 8/8] =?UTF-8?q?=D0=9B=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20+=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D1=83=D0=BF=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сделал локальную проверку на наличие скоупа print.file.send Пришлось вынести user = user.one_or_none() так как при разных условиях возвращаются разные типы данных (запрос в базу или UnionMember), а далее для создания пина нужен именно UnionMember. Изменение в файле __main__.py предложил сделать Стас, чтоб автоматически при обновлениях кода обновлялось и приложение в вебе --- print_service/__main__.py | 4 +--- print_service/routes/file.py | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/print_service/__main__.py b/print_service/__main__.py index c9aaab6..8f9a7e6 100644 --- a/print_service/__main__.py +++ b/print_service/__main__.py @@ -1,7 +1,5 @@ import uvicorn -from print_service.routes.base import app - if __name__ == '__main__': - uvicorn.run(app) + uvicorn.run("print_service.routes.base:app", reload=True) diff --git a/print_service/routes/file.py b/print_service/routes/file.py index 35364dc..21e3570 100644 --- a/print_service/routes/file.py +++ b/print_service/routes/file.py @@ -112,32 +112,32 @@ class ReceiveOutput(BaseModel): ) async def send( inp: SendInput, - user_auth=Depends(UnionAuth(scopes=["print.file.send"])), + user_auth=Depends(UnionAuth(allow_none=True)), settings: Settings = Depends(get_settings), ): """Получить пин код для загрузки и скачивания файла. Полученный пин-код можно использовать в методах POST и GET `/file/{pin}`. """ - if not has_send_scope and inp.number is None: - raise NotInUnion() - user = db.session.query(UnionMember) if not settings.ALLOW_STUDENT_NUMBER: user = user.filter(UnionMember.union_number != None) - if inp.number is not None and inp.surname is not None: + if (inp.number is not None) and (inp.surname is not None): user = user.filter( or_( func.upper(UnionMember.student_number) == inp.number.upper(), func.upper(UnionMember.union_number) == inp.number.upper(), ), func.upper(UnionMember.surname) == inp.surname.upper(), - ).one_or_none() + ) + else: if not "print.file.send" in [scope["name"] for scope in user_auth.get('session_scopes')]: raise NotInUnion() + user = user.one_or_none() + if user is None: raise NotInUnion() try: