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

Feat/custom authentification #93

Merged
merged 28 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d0388a0
feat (login, custom provider) : add authentification class for custom…
jacquesfize Mar 29, 2024
1b9c528
feat (login, custom provider) : include authentification class in the…
jacquesfize Mar 29, 2024
86ed433
add remember option to login_user() call
jacquesfize Jul 3, 2024
3d08a99
clean code
jacquesfize Jul 5, 2024
0bf9040
add default value for auth.login route
jacquesfize Jul 5, 2024
116fd8b
add missing auth manager in the conftest
jacquesfize Jul 5, 2024
576002e
feat(authentication) : replace is_uh by is_external + drop `Authentic…
jacquesfize Jul 12, 2024
9cacb80
remove the configuration_schema method
jacquesfize Jul 12, 2024
5114159
feat(authentication): insert_or_update_role take user info as a dict …
jacquesfize Jul 12, 2024
f8952a8
add missing local provider in conftest
jacquesfize Jul 12, 2024
e3a9f3d
fix: do not add provider if t_providers not in the db
jacquesfize Jul 12, 2024
2c72869
change use of is_external
jacquesfize Jul 12, 2024
a52071c
remove hard coded config key in auth_manager init_app method
jacquesfize Jul 15, 2024
120e3b2
fix uuid integrity test in userhub provider
jacquesfize Jul 15, 2024
19d2ca8
update Readme.md
jacquesfize Jul 15, 2024
7b4078d
fix GN call
TheoLechemia Jul 15, 2024
282b4d1
update test_settings.py
TheoLechemia Jul 15, 2024
855ea09
test and refactor
TheoLechemia Jul 15, 2024
c8433a6
finish README
jacquesfize Jul 16, 2024
eec8ddd
test and refacto
TheoLechemia Jul 16, 2024
37cb112
add xmltodict in requirements
TheoLechemia Jul 16, 2024
8e10a76
fix typing error
TheoLechemia Jul 16, 2024
3e03dd9
doc(readme) : include parameters for each provider
jacquesfize Jul 16, 2024
7e70aca
add some documentation
jacquesfize Jul 16, 2024
1eac742
move login_manager initialisation into auth_manager init_app method
jacquesfize Jul 16, 2024
87fadd2
cleaning code and debug cas inpn
jacquesfize Jul 16, 2024
7e13cca
add missing provider
TheoLechemia Jul 16, 2024
5acccec
update readme
jacquesfize Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# editor
.vscode/

settings_test.py

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
615 changes: 470 additions & 145 deletions README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions requirements-common.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ sqlalchemy>=1.4,<2
flask-marshmallow
marshmallow-sqlalchemy
alembic
xmltodict
# for flask login
7 changes: 7 additions & 0 deletions src/pypnusershub/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from authlib.integrations.flask_client import OAuth

from .auth_manager import *
from .authentication import *


oauth = OAuth()
125 changes: 125 additions & 0 deletions src/pypnusershub/auth/auth_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import importlib

import sqlalchemy as sa
from pypnusershub.db.models import Provider
from pypnusershub.env import db

from .authentication import Authentication
from pypnusershub.login_manager import login_manager


from typing import TypedDict

ProviderType = TypedDict(
"Provider",
{
"id_provider": str,
"module": str,
"label": str,
"group_mapping": dict,
"logo": str,
},
)


class AuthManager:
"""
Manages authentication providers.
"""

def __init__(self) -> None:
"""
Initializes the AuthManager instance.
"""
self.provider_authentication_cls = {}

def __contains__(self, item) -> bool:
"""
Checks if a provider is registered.

Parameters
----------
item : str
The provider name.

Returns
-------
bool
True if the provider is registered, False otherwise.
"""
return item in self.provider_authentication_cls

def add_provider(
self, id_provider: str, provider_authentification: Authentication
) -> None:
"""
Registers a new authentication provider instance.

Parameters
----------
id_instance : str
identifier of the new provider instance
provider : Authentification
The authentication provider class.

Raises
------
AssertionError
If the provider is not an instance of Authentification.
"""
if not isinstance(provider_authentification, Authentication):
raise AssertionError("Provider must be an instance of Authentication")
if id_provider in self.provider_authentication_cls:
raise Exception(
f"Id provider {id_provider} already exist, please check your authentication config"
)
self.provider_authentication_cls[id_provider] = provider_authentification

def init_app(
self, app, prefix: str = "/auth", providers_declaration: list[ProviderType] = []
) -> None:
"""
Initializes the Flask application with the AuthManager. In addition, it registers the authentication module blueprint.

Parameters
----------
app : Flask
The Flask application instance.
prefix : str, optional
The URL prefix for the authentication module blueprint.
providers_declaration : list[ProviderType], optional
List of provider declarations to be used by the AuthManager.

"""
from pypnusershub.routes import routes

app.auth_manager = self
app.register_blueprint(routes, url_prefix=prefix)
for provider_config in providers_declaration:
path_provider = provider_config.get("module")
import_path, class_name = (
".".join(path_provider.split(".")[:-1]),
path_provider.split(".")[-1],
)
module = importlib.import_module(import_path)
class_ = getattr(module, class_name)

with app.app_context():
instance_provider: Authentication = class_()
instance_provider.configure(configuration=provider_config)
self.add_provider(instance_provider.id_provider, instance_provider)
login_manager.init_app(app)

def get_provider(self, instance_name: str) -> Authentication:
"""
Returns the current authentication provider.

Returns
-------
Authentification
The current authentication provider.
"""
return self.provider_authentication_cls[instance_name]


auth_manager = AuthManager()
Loading
Loading