From cc1480f887d629103c30c00eefa8cea9dd6a2d9e Mon Sep 17 00:00:00 2001 From: Filippo Campi Date: Sat, 18 May 2024 15:44:54 +0200 Subject: [PATCH] pydantic + add model for login endpoint --- setup.py | 1 + src/plone/restapi/services/auth/login.py | 34 +++++++++++------------- src/plone/restapi/services/auth/model.py | 14 ++++++++++ 3 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 src/plone/restapi/services/auth/model.py diff --git a/setup.py b/setup.py index fa0db2def8..49a9a2b615 100644 --- a/setup.py +++ b/setup.py @@ -95,6 +95,7 @@ def read(filename): "PyJWT>=1.7.0", "pytz", "pyyaml", + "pyDantic", ], extras_require={"test": TEST_REQUIRES}, entry_points=""" diff --git a/src/plone/restapi/services/auth/login.py b/src/plone/restapi/services/auth/login.py index 7a792c42a7..9cddb707eb 100644 --- a/src/plone/restapi/services/auth/login.py +++ b/src/plone/restapi/services/auth/login.py @@ -7,6 +7,8 @@ from zope import component from zope.interface import alsoProvides +from .model import LoginData + import plone.protect.interfaces @@ -23,13 +25,7 @@ def __restapi_doc__(cls): "required": True, "content": { "application/json": { - "schema": { - "type": "object", - "properties": { - "login": {"type": "string", "example": "admin"}, - "password": {"type": "string", "example": "admin"}, - }, - } + "schema": LoginData.schema(), } }, }, @@ -79,28 +75,28 @@ def __restapi_doc__(cls): } def reply(self): - data = json_body(self.request) - if "login" not in data or "password" not in data: - self.request.response.setStatus(400) - return dict( - error=dict( - type="Missing credentials", - message="Login and password must be provided in body.", - ) - ) + data = LoginData(**json_body(self.request)) + # if "login" not in data or "password" not in data: + # self.request.response.setStatus(400) + # return dict( + # error=dict( + # type="Missing credentials", + # message="Login and password must be provided in body.", + # ) + # ) # Disable CSRF protection if "IDisableCSRFProtection" in dir(plone.protect.interfaces): alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection) - userid = data["login"] - password = data["password"] + userid = data.login + password = data.password uf = self._find_userfolder(userid) # Also put the password in __ac_password on the request. # The post-login code in PlonePAS expects to find it there # when it calls the PAS updateCredentials plugin. - self.request.form["__ac_password"] = data["password"] + self.request.form["__ac_password"] = password if uf is not None: plugins = uf._getOb("plugins") diff --git a/src/plone/restapi/services/auth/model.py b/src/plone/restapi/services/auth/model.py new file mode 100644 index 0000000000..23e8f31113 --- /dev/null +++ b/src/plone/restapi/services/auth/model.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel + + +class LoginData(BaseModel): + login: str + password: str + + +class TokenResponse(BaseModel): + token: str + + +class ErrorResponse(BaseModel): + error: dict