A bit rework / refactoring.

This commit is contained in:
Kirill Zhosul 2022-03-16 14:12:44 +04:00
parent 0fa096f9ba
commit 1dc980eef5
5 changed files with 139 additions and 56 deletions

19
examples/simple_auth.py Normal file
View File

@ -0,0 +1,19 @@
from gitflic import Gitflic, GitflicAuth
# Your authentication token.
# See: https://gitflic.ru/settings/oauth/token/create
token = "token_here"
# Creating authorized session with our token.
gf_session = GitflicAuth(token)
gf = Gitflic(gf_session)
def main():
# Call method to get authorized user from API.
user_me = gf.call("/user/me")
print(user_me)
if __name__ == '__main__':
main()

View File

@ -1,5 +1,5 @@
__title__ = "gitflic" __title__ = "gitflic"
__version__ = "0.9" __version__ = "0.10"
__description__ = "GitflicApi wrapper" __description__ = "GitflicApi wrapper"
__author__ = "SantaSpeen" __author__ = "SantaSpeen"
__author_email__ = "dir@sssr.dev" __author_email__ = "dir@sssr.dev"

View File

@ -1,38 +1,61 @@
"""
Main Gitflic API wrapper.
"""
from enum import Enum
from .auth import GitflicAuth from .auth import GitflicAuth
from .exceptions import NotFound, NoRights, GitflicExceptions from .exceptions import (
NotFound, NoRights, GitflicExceptions
)
API_URL = 'https://api.gitflic.ru' API_URL = 'https://api.gitflic.ru'
class GitflicAPIMethods(Enum):
""" Methods that you may use for calling API. """
USER_ME = "/user/me"
USER = "/user"
# There is not all methods, please expand if you need some other method.
class Gitflic: class Gitflic:
"""
Gitflic API wrapper.
"""
def __init__(self, gf_session: GitflicAuth): def __init__(self, gf_session: GitflicAuth):
""" """
:param gf_session: Authorized session from GitflicAuth.
:param gf_session:
""" """
self.session = gf_session.session self.session = gf_session.session
@staticmethod @staticmethod
def _response_handler(response): def _response_handler(response):
"""
Handles HTTP response from Gitflic API.
:param response: HTTP response.
:return: Exception or valid JSON.
"""
code = response.status_code code = response.status_code
if code == 200: if code == 200:
return response.json() return response.json()
url = response.url url = response.url
if code == 403: if code == 403:
raise NoRights(f"No rights for '{url}'") raise NoRights(f"Access denied for '{url}'")
elif code == 404: elif code == 404:
raise NotFound(f"Response '{url}' not found") raise NotFound(f"Location '{url}' not found")
raise GitflicExceptions(f"Gitflic send error: {code}. {response.text}") raise GitflicExceptions(f"Gitflic sent unknown error with HTTP code: {code}. Response: {response.text}")
def call(self, method, *args, **kwargs): def call(self, method: str, *args, **kwargs):
""" """
Calls API method on server side.
:param method: :param method: API method of Gitflic to call.
:param args: :return: Exception or valid JSON.
:param kwargs:
:return:
""" """
response = self.session.get(API_URL + method, *args, **kwargs) response = self.session.get(API_URL + method, *args, **kwargs)
return self._response_handler(response) return self._response_handler(response)

View File

@ -1,17 +1,21 @@
"""
Gitflic authentication wrapper.
"""
from enum import Enum from enum import Enum
import logging
from typing import Union from typing import Union
import webbrowser import logging
import urllib.parse
import requests import requests
from .exceptions import AuthError, GitflicExceptions from .exceptions import AuthError, GitflicExceptions
oauth_url = "https://oauth.gitflic.ru/oauth/authorize?scope={}&clientId={}&redirectUrl={}&state={}"
OAUTH_URL = "https://oauth.gitflic.ru/oauth/authorize?scope={}&clientId={}&redirectUrl={}&state={}"
class GitflicAuthScopes(Enum): class GitflicAuthScopes(Enum):
""" Authentication scopes from Gitflic. """
USER_READ = "USER_READ" USER_READ = "USER_READ"
USER_WRITE = "USER_WRITE" USER_WRITE = "USER_WRITE"
PROJECT_READ = "PROJECT_READ" PROJECT_READ = "PROJECT_READ"
@ -22,6 +26,9 @@ class GitflicAuthScopes(Enum):
class GitflicAuth: class GitflicAuth:
"""
Gitflic authentication wrapper.
"""
# noinspection PyTypeChecker # noinspection PyTypeChecker
def __init__(self, def __init__(self,
@ -31,67 +38,97 @@ class GitflicAuth:
redirect_url: str = None, redirect_url: str = None,
state: str = None): state: str = None):
""" """
:param access_token: Raw token for raw AUTH.
:param access_token: :param scope: OAUTH field.
:param scope: :param client_id: OAUTH field.
:param client_id: :param redirect_url: OAUTH field.
:param redirect_url: :param state: OAUTH field.
""" """
# Logging.
self.log: logging.Logger = logging.getLogger(__name__) self.log: logging.Logger = logging.getLogger(__name__)
# Requests.
self.session: requests.Session = requests.Session() self.session: requests.Session = requests.Session()
# Auth.
# Token fields.
self.access_token: str = access_token self.access_token: str = access_token
# OAUTH fields.
self.scope: str = scope if not isinstance(scope, GitflicAuthScopes) else scope.value self.scope: str = scope if not isinstance(scope, GitflicAuthScopes) else scope.value
self.client_id: str = client_id self.client_id: str = client_id
self.redirect_url: str = redirect_url self.redirect_url: str = redirect_url
self.state = state self.state: str = state
self.refresh_token: str = None self.refresh_token: str = None
if any((access_token, scope, client_id, redirect_url, state)): self._try_login()
if access_token:
pass
elif not (scope and client_id and redirect_url, state):
raise GitflicExceptions(
"Cannot auth without 'scope', 'client_id', 'redirect_url', 'state' parameters. "
"See doc: https://gitflic.ru/help/api/access-token."
)
else:
raise GitflicExceptions(
"Cannot auth without 'token' or 'scope' and 'client_id' and 'redirect_url' and 'state' parameters. "
"See doc: https://gitflic.ru/help/api/access-token."
)
self._login()
def _login(self):
self.log.debug("Trying to login.")
def _try_login(self):
"""
Tries to login user with token or OAUTH.
"""
if self.access_token: if self.access_token:
self.session.headers.update({"Authorization": "token " + self.access_token}) # Raw authorization.
self._token_login()
else: else:
if self.scope and self.client_id and self.redirect_url and self.state:
# OAUTH authorization.
self._oauth_login()
else:
if any(self.scope, self.client_id, self.redirect_url, self.state):
raise GitflicExceptions(
"Not found one of params for OAUTH, you are required to send ALL params from ('scope', 'client_id', 'redirect_url', 'state')!"
"See docs: https://gitflic.ru/help/api/access-token."
)
raise GitflicExceptions(
"Please pass 'token' param for raw auth or ('scope', 'client_id', 'redirect_url', 'state') params for OAUTH "
"See docs: https://gitflic.ru/help/api/access-token."
)
raise GitflicExceptions("Oauth not ready. Use access_token.") def _oauth_login(self):
"""
Tries to login user with OAUTH.
"""
self.log.debug("Trying to login with OAUTH...")
# OAUTH authorization.
raise GitflicExceptions("OAUTH not implemented yet! Use raw access_token authorization.")
# redirect_url = urllib.parse.quote_plus(self.redirect_url) # redirect_url = urllib.parse.quote_plus(self.redirect_url)
# webbrowser.open(oauth_url.format(self.scope, self.client_id, redirect_url, self.state)) # webbrowser.open(OAUTH_URL.format(self.scope, self.client_id, redirect_url, self.state))
# url = input("Paste redirect url: ") # url = input("Paste redirect url: ")
# r = self.session.get("").json() # r = self.session.get("").json()
# print(r) # print(r)
# self.session.headers.update({"Authorization": "token " + "null"}) # self.session.headers.update({"Authorization": "token " + "null"})
# self.check_token()
def _token_login(self):
"""
Tries to login user with given access token.
"""
self.log.debug("Trying to login with token...")
if self.access_token:
self.session.headers.update({
"Authorization": "token " + self.access_token
})
self.check_token() self.check_token()
def check_token(self): def check_token(self):
self.log.debug("Check token.") """
Checks that current auth session token is valid or not (by making request to get current user).
"""
self.log.debug("Checking token....")
r = self.session.get("https://api.gitflic.ru/user/me") r = self.session.get("https://api.gitflic.ru/user/me")
if r.status_code == 403: if r.status_code == 403:
raise AuthError("Authentication failed.") raise AuthError("Authentication failed. Invalid token?")
else: else:
r = r.json() r = r.json()
self.log.debug(f"Logged as {r.get('username')} {r.get('id')}") self.log.debug(f"Successfully logged as {r.get('username')} {r.get('id')}")

View File

@ -1,3 +1,7 @@
"""
All exceptions that may be raised from Gitflic API wrapper.
"""
class GitflicExceptions(Exception): class GitflicExceptions(Exception):
error_code: int = 1 error_code: int = 1
reason: str = None reason: str = None