From 91ed8caf48e42ab9af5c9f00df542c38aaba8f70 Mon Sep 17 00:00:00 2001 From: Paco Aranda Date: Mon, 18 Nov 2024 15:09:58 +0100 Subject: [PATCH] [REFACTOR] `argilla server`: Remove passlib dependency (#5674) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Closes https://github.com/argilla-io/argilla/issues/5664 **Type of change** - Improvement (change adding some improvement to an existing functionality) **How Has This Been Tested** **Checklist** - I added relevant documentation - I followed the style guidelines of this project - I did a self-review of my code - I made corresponding changes to the documentation - I confirm My changes generate no new warnings - I have added tests that prove my fix is effective or that my feature works - I have added relevant notes to the CHANGELOG.md file (See https://keepachangelog.com/) --------- Co-authored-by: José Francisco Calvo Co-authored-by: José Francisco Calvo Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- argilla-server/pdm.lock | 27 +--------------- argilla-server/pyproject.toml | 2 +- .../src/argilla_server/contexts/accounts.py | 32 +++++++++++++------ 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/argilla-server/pdm.lock b/argilla-server/pdm.lock index b8534d410d..afbb0afb5f 100644 --- a/argilla-server/pdm.lock +++ b/argilla-server/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "postgresql", "test"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:43263bc708af6895a1834c1a3826349b82a643e70dae41abf99d8b6bff2d454e" +content_hash = "sha256:bac5d1141affbb735ae70537eb0534eb8dabf287bd33af762ac7bd877073d282" [[metadata.targets]] requires_python = ">=3.9" @@ -1666,31 +1666,6 @@ files = [ {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, ] -[[package]] -name = "passlib" -version = "1.7.4" -summary = "comprehensive password hashing framework supporting over 30 schemes" -groups = ["default"] -files = [ - {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, - {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, -] - -[[package]] -name = "passlib" -version = "1.7.4" -extras = ["bcrypt"] -summary = "comprehensive password hashing framework supporting over 30 schemes" -groups = ["default"] -dependencies = [ - "bcrypt>=3.1.0", - "passlib==1.7.4", -] -files = [ - {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, - {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, -] - [[package]] name = "pillow" version = "11.0.0" diff --git a/argilla-server/pyproject.toml b/argilla-server/pyproject.toml index 616e369b95..4a43fdc0c6 100644 --- a/argilla-server/pyproject.toml +++ b/argilla-server/pyproject.toml @@ -39,7 +39,7 @@ dependencies = [ "PyYAML >= 5.4.1,< 6.1.0", # security dependencies "python-jose[cryptography] ~= 3.3.0", - "passlib[bcrypt] ~= 1.7.4", + "bcrypt ~= 4.2.0", # required by fastapi "python-multipart ~= 0.0.16", # OAuth2 integration diff --git a/argilla-server/src/argilla_server/contexts/accounts.py b/argilla-server/src/argilla_server/contexts/accounts.py index 01aa1fa8d5..0b65bdc815 100644 --- a/argilla-server/src/argilla_server/contexts/accounts.py +++ b/argilla-server/src/argilla_server/contexts/accounts.py @@ -15,7 +15,7 @@ from typing import Iterable, List, Sequence, Union from uuid import UUID -from passlib.context import CryptContext +import bcrypt from sqlalchemy import exists, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -27,8 +27,6 @@ from argilla_server.security.authentication.jwt import JWT from argilla_server.security.authentication.userinfo import UserInfo -_CRYPT_CONTEXT = CryptContext(schemes=["bcrypt"], deprecated="auto") - async def create_workspace_user(db: AsyncSession, workspace_user_attrs: dict) -> WorkspaceUser: workspace_id = workspace_user_attrs["workspace_id"] @@ -168,19 +166,21 @@ async def authenticate_user(db: AsyncSession, username: str, password: str): elif user: return else: - _CRYPT_CONTEXT.dummy_verify() + _dummy_verify() def hash_password(password: str) -> str: - return _CRYPT_CONTEXT.hash(password) + return bcrypt.hashpw( + bytes(password, encoding="utf-8"), + bcrypt.gensalt(), + ).decode("utf-8") def verify_password(password: str, password_hash: str) -> bool: - return _CRYPT_CONTEXT.verify(password, password_hash) - - -def _generate_random_password() -> str: - return secrets.token_urlsafe() + return bcrypt.checkpw( + bytes(password, encoding="utf-8"), + bytes(password_hash, encoding="utf-8"), + ) def generate_user_token(user: User) -> str: @@ -192,3 +192,15 @@ def generate_user_token(user: User) -> str: role=user.role, ), ) + + +_DUMMY_SECRET = "dummy_secret" +_DUMMY_HASH = hash_password(_DUMMY_SECRET) + + +def _dummy_verify(): + verify_password(_DUMMY_SECRET, _DUMMY_HASH) + + +def _generate_random_password() -> str: + return secrets.token_urlsafe()