From 2991106dff40c4cb303e8261cc3eacb571ce6dbd Mon Sep 17 00:00:00 2001 From: Ananias Carvalho Date: Fri, 20 Sep 2024 11:02:05 +0200 Subject: [PATCH 1/3] feat: add possibility to authenticate using access_token --- pyartifactory/models/auth.py | 1 + pyartifactory/objects/object.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pyartifactory/models/auth.py b/pyartifactory/models/auth.py index b9e52e57..11c02641 100644 --- a/pyartifactory/models/auth.py +++ b/pyartifactory/models/auth.py @@ -13,6 +13,7 @@ class AuthModel(BaseModel): url: str auth: Tuple[str, SecretStr] + access_token: Optional[str] = None verify: Union[bool, str] = True cert: Optional[str] = None api_version: int = 1 diff --git a/pyartifactory/objects/object.py b/pyartifactory/objects/object.py index 54b8daad..f830f4e6 100644 --- a/pyartifactory/objects/object.py +++ b/pyartifactory/objects/object.py @@ -18,6 +18,7 @@ def __init__(self, artifactory: AuthModel) -> None: self._artifactory.auth[0], self._artifactory.auth[1].get_secret_value(), ) + self._access_token = self._artifactory.access_token self._api_version = self._artifactory.api_version self._verify = self._artifactory.verify self._cert = self._artifactory.cert @@ -78,10 +79,19 @@ def _generic_http_method_request( :return: An HTTP response """ + if self._access_token is not None: + headers = kwargs.get("headers", {}) + headers["Authorization"] = f"Bearer {self._access_token}" + kwargs["headers"] = headers + + auth = None + else: + auth = self._auth + http_method = getattr(self.session, method) response: Response = http_method( f"{self._artifactory.url}/{route}", - auth=self._auth, + auth=auth, **kwargs, verify=self._verify, cert=self._cert, From d13143c1f3fa15a99777611199f850ac93733187 Mon Sep 17 00:00:00 2001 From: Ananias CARVALHO Date: Fri, 20 Sep 2024 12:14:28 +0200 Subject: [PATCH 2/3] feat: allow anonymous authentication --- README.md | 16 ++++++++++++++++ pyartifactory/models/auth.py | 1 + pyartifactory/objects/object.py | 16 ++++++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e38f1617..8c2e3bd7 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ This library enables you to manage Artifactory resources such as users, groups, - [Install](#install) - [Usage](#usage) * [Authentication](#authentication) + + [Basic authentication](#basic-authentication) + + [Authentication with access token](#authentication-with-access-token) + + [Anonymous authentication](#anonymous-authentication) * [SSL Cert Verification Options](#ssl-cert-verification-options) * [Timeout option](#timeout-option) * [Admin objects](#admin-objects) @@ -69,11 +72,24 @@ pip install pyartifactory Since Artifactory 6.6.0 there is version 2 of the REST API for permission management, in case you have that version or higher, you need to pass api_version=2 to the constructor when you instantiate the class. +#### Basic authentication ```python from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), api_version=1) ``` +#### Authentication with access token +```python +from pyartifactory import Artifactory +art = Artifactory(url="ARTIFACTORY_URL", access_token="your-access-token") +``` + +#### Anonymous authentication +```python +from pyartifactory import Artifactory +art = Artifactory(url="ARTIFACTORY_URL", anonymous_auth=True) +``` + ### SSL Cert Verification Options Specify a local cert to use as client side certificate diff --git a/pyartifactory/models/auth.py b/pyartifactory/models/auth.py index 11c02641..f096863d 100644 --- a/pyartifactory/models/auth.py +++ b/pyartifactory/models/auth.py @@ -14,6 +14,7 @@ class AuthModel(BaseModel): url: str auth: Tuple[str, SecretStr] access_token: Optional[str] = None + anonymous_auth: bool = False verify: Union[bool, str] = True cert: Optional[str] = None api_version: int = 1 diff --git a/pyartifactory/objects/object.py b/pyartifactory/objects/object.py index f830f4e6..695f33d1 100644 --- a/pyartifactory/objects/object.py +++ b/pyartifactory/objects/object.py @@ -19,6 +19,7 @@ def __init__(self, artifactory: AuthModel) -> None: self._artifactory.auth[1].get_secret_value(), ) self._access_token = self._artifactory.access_token + self._anonymous_auth = self._artifactory.anonymous_auth self._api_version = self._artifactory.api_version self._verify = self._artifactory.verify self._cert = self._artifactory.cert @@ -79,14 +80,17 @@ def _generic_http_method_request( :return: An HTTP response """ - if self._access_token is not None: - headers = kwargs.get("headers", {}) - headers["Authorization"] = f"Bearer {self._access_token}" - kwargs["headers"] = headers - + if self._anonymous_auth: auth = None else: - auth = self._auth + if self._access_token is not None: + headers = kwargs.get("headers", {}) + headers["Authorization"] = f"Bearer {self._access_token}" + kwargs["headers"] = headers + + auth = None + else: + auth = self._auth http_method = getattr(self.session, method) response: Response = http_method( From 210e3aac7910cec68a5f4ebfd3f5d30e6ff7a7a8 Mon Sep 17 00:00:00 2001 From: Ananias Carvalho Date: Fri, 20 Sep 2024 14:13:31 +0200 Subject: [PATCH 3/3] feat: allow anonymous authentication --- README.md | 9 +++------ pyartifactory/models/auth.py | 3 +-- pyartifactory/objects/artifactory.py | 4 +++- pyartifactory/objects/object.py | 30 +++++++++++++++------------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 8c2e3bd7..f552af76 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ This library enables you to manage Artifactory resources such as users, groups, * [Authentication](#authentication) + [Basic authentication](#basic-authentication) + [Authentication with access token](#authentication-with-access-token) - + [Anonymous authentication](#anonymous-authentication) * [SSL Cert Verification Options](#ssl-cert-verification-options) * [Timeout option](#timeout-option) * [Admin objects](#admin-objects) @@ -84,11 +83,9 @@ from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", access_token="your-access-token") ``` -#### Anonymous authentication -```python -from pyartifactory import Artifactory -art = Artifactory(url="ARTIFACTORY_URL", anonymous_auth=True) -``` +Note: +* If you set both `access_token` and `auth`, the access_token authentication will be chosen +* If you do not set any authentication method, API calls will be done without authentication (anonymous) ### SSL Cert Verification Options diff --git a/pyartifactory/models/auth.py b/pyartifactory/models/auth.py index f096863d..aafa93ae 100644 --- a/pyartifactory/models/auth.py +++ b/pyartifactory/models/auth.py @@ -12,9 +12,8 @@ class AuthModel(BaseModel): """Models an auth response.""" url: str - auth: Tuple[str, SecretStr] + auth: Optional[Tuple[str, SecretStr]] = None access_token: Optional[str] = None - anonymous_auth: bool = False verify: Union[bool, str] = True cert: Optional[str] = None api_version: int = 1 diff --git a/pyartifactory/objects/artifactory.py b/pyartifactory/objects/artifactory.py index 14111998..dda2788f 100644 --- a/pyartifactory/objects/artifactory.py +++ b/pyartifactory/objects/artifactory.py @@ -20,7 +20,8 @@ class Artifactory: def __init__( self, url: str, - auth: Tuple[str, SecretStr], + auth: Optional[Tuple[str, SecretStr]] = None, + access_token: Optional[str] = None, verify: Union[bool, str] = True, cert: Optional[str] = None, api_version: int = 1, @@ -29,6 +30,7 @@ def __init__( self.artifactory = AuthModel( url=url, auth=auth, + access_token=access_token, verify=verify, cert=cert, api_version=api_version, diff --git a/pyartifactory/objects/object.py b/pyartifactory/objects/object.py index 695f33d1..cb5c9e01 100644 --- a/pyartifactory/objects/object.py +++ b/pyartifactory/objects/object.py @@ -3,6 +3,8 @@ """ from __future__ import annotations +from typing import Optional, Tuple + import requests from requests import Response @@ -14,12 +16,15 @@ class ArtifactoryObject: def __init__(self, artifactory: AuthModel) -> None: self._artifactory = artifactory - self._auth = ( - self._artifactory.auth[0], - self._artifactory.auth[1].get_secret_value(), - ) + self._auth: Optional[Tuple[str, str]] = None + + if self._artifactory.auth is not None: + self._auth = ( + self._artifactory.auth[0], + self._artifactory.auth[1].get_secret_value(), + ) + self._access_token = self._artifactory.access_token - self._anonymous_auth = self._artifactory.anonymous_auth self._api_version = self._artifactory.api_version self._verify = self._artifactory.verify self._cert = self._artifactory.cert @@ -80,17 +85,14 @@ def _generic_http_method_request( :return: An HTTP response """ - if self._anonymous_auth: + if self._access_token is not None: + headers = kwargs.get("headers", {}) + headers["Authorization"] = f"Bearer {self._access_token}" + kwargs["headers"] = headers + auth = None else: - if self._access_token is not None: - headers = kwargs.get("headers", {}) - headers["Authorization"] = f"Bearer {self._access_token}" - kwargs["headers"] = headers - - auth = None - else: - auth = self._auth + auth = self._auth http_method = getattr(self.session, method) response: Response = http_method(