1212import gitlab .config
1313import gitlab .const
1414import gitlab .exceptions
15- from gitlab import _backends , utils
15+ from gitlab import _backends , oauth , utils
1616
1717REDIRECT_MSG = (
1818 "python-gitlab detected a {status_code} ({reason!r}) redirection. You must update "
@@ -41,8 +41,8 @@ class Gitlab:
4141 the value is a string, it is the path to a CA file used for
4242 certificate validation.
4343 timeout: Timeout to use for requests to the GitLab server.
44- http_username: Username for HTTP authentication
45- http_password: Password for HTTP authentication
44+ http_username: Username for OAuth ROPC flow (deprecated, use oauth_credentials)
45+ http_password: Password for OAuth ROPC flow (deprecated, use oauth_credentials)
4646 api_version: Gitlab API version to use (support for 4 only)
4747 pagination: Can be set to 'keyset' to use keyset pagination
4848 order_by: Set order_by globally
@@ -51,6 +51,7 @@ class Gitlab:
5151 or 52x responses. Defaults to False.
5252 keep_base_url: keep user-provided base URL for pagination if it
5353 differs from response headers
54+ oauth_credentials: Password credentials for authenticating via OAuth ROPC flow
5455
5556 Keyword Args:
5657 requests.Session session: HTTP Requests Session
@@ -74,6 +75,8 @@ def __init__(
7475 user_agent : str = gitlab .const .USER_AGENT ,
7576 retry_transient_errors : bool = False ,
7677 keep_base_url : bool = False ,
78+ * ,
79+ oauth_credentials : Optional [oauth .PasswordCredentials ] = None ,
7780 ** kwargs : Any ,
7881 ) -> None :
7982 self ._api_version = str (api_version )
@@ -96,7 +99,7 @@ def __init__(
9699 self .http_password = http_password
97100 self .oauth_token = oauth_token
98101 self .job_token = job_token
99- self ._set_auth_info ()
102+ self .oauth_credentials = oauth_credentials
100103
101104 #: Create a session object for requests
102105 _backend : Type [_backends .DefaultBackend ] = kwargs .pop (
@@ -105,6 +108,7 @@ def __init__(
105108 self ._backend = _backend (** kwargs )
106109 self .session = self ._backend .client
107110
111+ self ._set_auth_info ()
108112 self .per_page = per_page
109113 self .pagination = pagination
110114 self .order_by = order_by
@@ -496,22 +500,56 @@ def _set_auth_info(self) -> None:
496500 self .headers .pop ("Authorization" , None )
497501 self .headers ["PRIVATE-TOKEN" ] = self .private_token
498502 self .headers .pop ("JOB-TOKEN" , None )
503+ return
504+
505+ if not self .oauth_credentials and (self .http_username and self .http_password ):
506+ utils .warn (
507+ "Passing http_username and http_password is deprecated and will be "
508+ "removed in a future version.\n Please use the OAuth ROPC flow with"
509+ "(gitlab.oauth.PasswordCredentials) if you need password-based"
510+ "authentication. See https://docs.gitlab.com/ee/api/oauth2.html"
511+ "#resource-owner-password-credentials-flow for more details." ,
512+ category = DeprecationWarning ,
513+ )
514+ self .oauth_credentials = oauth .PasswordCredentials (
515+ self .http_username , self .http_password
516+ )
517+
518+ if self .oauth_credentials :
519+ post_data = {
520+ "grant_type" : self .oauth_credentials .grant_type ,
521+ "scope" : self .oauth_credentials .scope ,
522+ "username" : self .oauth_credentials .username ,
523+ "password" : self .oauth_credentials .password ,
524+ }
525+ response = self .http_post (
526+ f"{ self ._base_url } /oauth/token" , post_data = post_data
527+ )
528+ if isinstance (response , dict ):
529+ self .oauth_token = response ["access_token" ]
530+ else :
531+ self .oauth_token = response .json ()["access_token" ]
532+ self ._http_auth = self .oauth_credentials .basic_auth
499533
500534 if self .oauth_token :
501535 self .headers ["Authorization" ] = f"Bearer { self .oauth_token } "
502536 self .headers .pop ("PRIVATE-TOKEN" , None )
503537 self .headers .pop ("JOB-TOKEN" , None )
538+ return
504539
505540 if self .job_token :
506541 self .headers .pop ("Authorization" , None )
507542 self .headers .pop ("PRIVATE-TOKEN" , None )
508543 self .headers ["JOB-TOKEN" ] = self .job_token
509544
545+ < << << << HEAD
510546 if self .http_username and self .http_password :
511547 self ._http_auth = requests .auth .HTTPBasicAuth (
512548 self .http_username , self .http_password
513549 )
514550
551+ == == == =
552+ >> >> >> > be7745dc (feat (client ): replace basic auth with OAuth ROPC flow )
515553 @staticmethod
516554 def enable_debug () - > None :
517555 import logging
0 commit comments