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 forHTTP authentication
46- http_password: Password forHTTP authentication
45+ http_username: Username forOAuth ROPC flow (deprecated, use oauth_credentials)
46+ http_password: Password forOAuth 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__(
7576user_agent :str = gitlab .const .USER_AGENT ,
7677retry_transient_errors :bool = False ,
7778keep_base_url :bool = False ,
79+ * ,
80+ oauth_credentials :Optional [oauth .PasswordCredentials ]= None ,
7881** kwargs :Any ,
7982 )-> None :
8083self ._api_version = str (api_version )
@@ -97,13 +100,15 @@ def __init__(
97100self .http_password = http_password
98101self .oauth_token = oauth_token
99102self .job_token = job_token
100- self ._set_auth_info ()
103+ self .oauth_credentials = oauth_credentials
101104
102105#: Create a session object for requests
103106http_backend :Type [http_backends .DefaultBackend ]= kwargs .pop (
104107"http_backend" ,http_backends .DefaultBackend
105108 )
106109self .http_backend = http_backend (** kwargs )
110+
111+ self ._set_auth_info ()
107112self .session = self .http_backend .client
108113
109114self .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-
517521self ._http_auth = None
518522if self .private_token :
519523self .headers .pop ("Authorization" ,None )
520524self .headers ["PRIVATE-TOKEN" ]= self .private_token
521525self .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
523557if self .oauth_token :
524558self .headers ["Authorization" ]= f"Bearer{ self .oauth_token } "
525559self .headers .pop ("PRIVATE-TOKEN" ,None )
526560self .headers .pop ("JOB-TOKEN" ,None )
561+ return
527562
528563if self .job_token :
529564self .headers .pop ("Authorization" ,None )
530565self .headers .pop ("PRIVATE-TOKEN" ,None )
531566self .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
539569def enable_debug ()-> None :
540570import logging