1313import gitlab .config
1414import gitlab .const
1515import gitlab .exceptions
16- from gitlab import http_backends , utils
16+ from gitlab import http_backends , oauth , utils
1717
1818REDIRECT_MSG = (
1919 "python-gitlab detected a {status_code} ({reason!r}) redirection. You must update "
@@ -42,8 +42,8 @@ class Gitlab:
4242 the value is a string, it is the path to a CA file used for
4343 certificate validation.
4444 timeout: Timeout to use for requests to the GitLab server.
45- http_username: Username for HTTP authentication
46- http_password: Password for HTTP authentication
45+ http_username: Username for OAuth ROPC flow (deprecated, use oauth_credentials)
46+ http_password: Password for OAuth ROPC flow (deprecated, use oauth_credentials)
4747 api_version: Gitlab API version to use (support for 4 only)
4848 pagination: Can be set to 'keyset' to use keyset pagination
4949 order_by: Set order_by globally
@@ -52,6 +52,7 @@ class Gitlab:
5252 or 52x responses. Defaults to False.
5353 keep_base_url: keep user-provided base URL for pagination if it
5454 differs from response headers
55+ oauth_credentials: Password credentials for authenticating via OAuth ROPC flow
5556
5657 Keyward Args:
5758 requests.Session session: Http Requests Session
@@ -75,6 +76,8 @@ def __init__(
7576 user_agent : str = gitlab .const .USER_AGENT ,
7677 retry_transient_errors : bool = False ,
7778 keep_base_url : bool = False ,
79+ * ,
80+ oauth_credentials : Optional [oauth .PasswordCredentials ] = None ,
7881 ** kwargs : Any ,
7982 ) -> None :
8083 self ._api_version = str (api_version )
@@ -97,13 +100,15 @@ def __init__(
97100 self .http_password = http_password
98101 self .oauth_token = oauth_token
99102 self .job_token = job_token
100- self ._set_auth_info ()
103+ self .oauth_credentials = oauth_credentials
101104
102105 #: Create a session object for requests
103106 http_backend : Type [http_backends .DefaultBackend ] = kwargs .pop (
104107 "http_backend" , http_backends .DefaultBackend
105108 )
106109 self .http_backend = http_backend (** kwargs )
110+
111+ self ._set_auth_info ()
107112 self .session = self .http_backend .client
108113
109114 self .per_page = per_page
@@ -513,28 +518,53 @@ def _set_auth_info(self) -> None:
513518 "Only one of oauth authentication or http "
514519 "authentication should be defined"
515520 )
516-
517521 self ._http_auth = None
518522 if self .private_token :
519523 self .headers .pop ("Authorization" , None )
520524 self .headers ["PRIVATE-TOKEN" ] = self .private_token
521525 self .headers .pop ("JOB-TOKEN" , None )
526+ return
527+
528+ if not self .oauth_credentials and (self .http_username and self .http_password ):
529+ utils .warn (
530+ "Passing http_username and http_password is deprecated and will be "
531+ "removed in a future version.\n Please use the OAuth ROPC flow with"
532+ "(gitlab.oauth.PasswordCredentials) if you need password-based"
533+ "authentication. See https://docs.gitlab.com/ee/api/oauth2.html"
534+ "#resource-owner-password-credentials-flow for more details." ,
535+ category = DeprecationWarning ,
536+ )
537+ self .oauth_credentials = oauth .PasswordCredentials (
538+ self .http_username , self .http_password
539+ )
540+
541+ if self .oauth_credentials :
542+ post_data = {
543+ "grant_type" : self .oauth_credentials .grant_type ,
544+ "scope" : self .oauth_credentials .scope ,
545+ "username" : self .oauth_credentials .username ,
546+ "password" : self .oauth_credentials .password ,
547+ }
548+ response = self .http_post (
549+ f"{ self ._base_url } /oauth/token" , post_data = post_data
550+ )
551+ if isinstance (response , dict ):
552+ self .oauth_token = response ["access_token" ]
553+ else :
554+ self .oauth_token = response .json ()["access_token" ]
555+ self ._http_auth = self .oauth_credentials .basic_auth
522556
523557 if self .oauth_token :
524558 self .headers ["Authorization" ] = f"Bearer { self .oauth_token } "
525559 self .headers .pop ("PRIVATE-TOKEN" , None )
526560 self .headers .pop ("JOB-TOKEN" , None )
561+ return
527562
528563 if self .job_token :
529564 self .headers .pop ("Authorization" , None )
530565 self .headers .pop ("PRIVATE-TOKEN" , None )
531566 self .headers ["JOB-TOKEN" ] = self .job_token
532567
533- if self .http_username :
534- self ._http_auth = requests .auth .HTTPBasicAuth (
535- self .http_username , self .http_password
536- )
537-
538568 @staticmethod
539569 def enable_debug () -> None :
540570 import logging
0 commit comments