Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base Class for Authorization required APIs #193

Open
MelihDarcanxyz opened this issue Aug 10, 2022 · 2 comments
Open

Base Class for Authorization required APIs #193

MelihDarcanxyz opened this issue Aug 10, 2022 · 2 comments

Comments

@MelihDarcanxyz
Copy link
Contributor

MelihDarcanxyz commented Aug 10, 2022

Summary

Here I have a suggestion to make. After thinking a while about Disgenet API, I've come to a conclusion. Using classes for authorization required APIs is the best practive since it is the perfect balance between data security and ease of use.

Details

If we store the api key in the storage, it's not a good practice for data security. And if we don't, we have to prompt to user for e-mail and password every time we want to make a query. Of course they can be stored in a variable but classes are more elegant way of doing it. Prompting one time for each session is enough in this approach.

How

This base class is an Abstract Class and has a decorator (wrapper if you prefer) to use queries without the hassle of checking authorization status every time in every query. It also checks if the necessary and unique attributes of each child class is implemented.

Code

from abc import ABC, abstractmethod

class BaseAuthorizedApi(ABC):

    _name = NotImplemented
    _api_url = NotImplemented
    _authorized = False
    _api_key = None

    @abstractmethod
    def authorize(self) -> bool:
        pass

    def __if_authorized(f):
        def wrapper(self, *args, **kwargs):
            if self.authorize():
                return f(self, *args, **kwargs)
            else:
                print('Failure in authorization, check your credentials.')
        return wrapper

    def __init_subclass__(cls, **kwargs):
        for attr in dir(cls):
            try:
                if (getattr(cls, attr) == NotImplemented):
                    raise NotImplementedError(f'\'{attr}\' attribute is not defined in subclass.')
            except AttributeError:
                pass
@deeenes
Copy link
Member

deeenes commented Aug 11, 2022

Hi Melih,

Thanks for coming up with this idea. If I understand correctly, we could do something like this in the new downloader module?

@MelihDarcanxyz
Copy link
Contributor Author

MelihDarcanxyz commented Aug 15, 2022

If I got it right, yes, of course. That way there will be no unnecessary login prompts and this base class will prove useful for child classes. I made a correction to the wrapper by the way. You might want to look at it again.

My initial goal was to create a base class for the inputs module. This way, if a contributor wants to write an api for a database, one will know how to do it with consistence with the code base and ease. They just have to use this as a parent class and the parent class will guide them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants