refactor: Model identifier_attributes are fixed.

This commit is contained in:
Éloi Rivard 2024-04-22 20:04:24 +02:00
parent ee9b49402d
commit 256566df94
No known key found for this signature in database
GPG key ID: 7EDA204EA57DD184
8 changed files with 34 additions and 60 deletions

View file

@ -1,3 +1,7 @@
Changed
^^^^^^^
- Model `identifier_attributes` are fixed.
[0.0.53] - 2024-04-22 [0.0.53] - 2024-04-22
--------------------- ---------------------

View file

@ -6,7 +6,6 @@ import ldap.dn
import ldap.filter import ldap.filter
from ldap.controls.readentry import PostReadControl from ldap.controls.readentry import PostReadControl
from canaille.app import classproperty
from canaille.backends.models import BackendModel from canaille.backends.models import BackendModel
from .backend import Backend from .backend import Backend
@ -136,10 +135,6 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
else "<LDAPOBject>" else "<LDAPOBject>"
) )
@classproperty
def identifier_attribute(cls):
return cls.rdn_attribute
def __eq__(self, other): def __eq__(self, other):
ldap_attributes = self.may() + self.must() ldap_attributes = self.may() + self.must()

View file

@ -43,10 +43,6 @@ class User(canaille.core.models.User, LDAPObject):
return super().match_filter(filter) return super().match_filter(filter)
@property
def identifier(self):
return self.rdn_value
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
group_attr = self.python_attribute_to_ldap("groups") group_attr = self.python_attribute_to_ldap("groups")
if group_attr not in self.changes: if group_attr not in self.changes:
@ -92,10 +88,6 @@ class Group(canaille.core.models.Group, LDAPObject):
"description": "description", "description": "description",
} }
@property
def identifier(self):
return self.rdn_value
class Client(canaille.oidc.models.Client, LDAPObject): class Client(canaille.oidc.models.Client, LDAPObject):
ldap_object_class = ["oauthClient"] ldap_object_class = ["oauthClient"]
@ -139,10 +131,6 @@ class Client(canaille.oidc.models.Client, LDAPObject):
**client_metadata_attributes, **client_metadata_attributes,
} }
@property
def identifier(self):
return self.rdn_value
class AuthorizationCode(canaille.oidc.models.AuthorizationCode, LDAPObject): class AuthorizationCode(canaille.oidc.models.AuthorizationCode, LDAPObject):
ldap_object_class = ["oauthAuthorizationCode"] ldap_object_class = ["oauthAuthorizationCode"]
@ -167,10 +155,6 @@ class AuthorizationCode(canaille.oidc.models.AuthorizationCode, LDAPObject):
"revokation_date": "oauthRevokationDate", "revokation_date": "oauthRevokationDate",
} }
@property
def identifier(self):
return self.rdn_value
class Token(canaille.oidc.models.Token, LDAPObject): class Token(canaille.oidc.models.Token, LDAPObject):
ldap_object_class = ["oauthToken"] ldap_object_class = ["oauthToken"]
@ -193,10 +177,6 @@ class Token(canaille.oidc.models.Token, LDAPObject):
"audience": "oauthAudience", "audience": "oauthAudience",
} }
@property
def identifier(self):
return self.rdn_value
class Consent(canaille.oidc.models.Consent, LDAPObject): class Consent(canaille.oidc.models.Consent, LDAPObject):
ldap_object_class = ["oauthConsent"] ldap_object_class = ["oauthConsent"]
@ -213,7 +193,3 @@ class Consent(canaille.oidc.models.Consent, LDAPObject):
"issue_date": "oauthIssueDate", "issue_date": "oauthIssueDate",
"revokation_date": "oauthRevokationDate", "revokation_date": "oauthRevokationDate",
} }
@property
def identifier(self):
return self.rdn_value

View file

@ -2,7 +2,6 @@ import copy
import datetime import datetime
import typing import typing
import uuid import uuid
from typing import ClassVar
import canaille.core.models import canaille.core.models
import canaille.oidc.models import canaille.oidc.models
@ -235,30 +234,26 @@ class MemoryModel(BackendModel):
else: else:
super().__setattr__(name, value) super().__setattr__(name, value)
@property
def identifier(self):
return getattr(self, self.identifier_attribute)
class User(canaille.core.models.User, MemoryModel): class User(canaille.core.models.User, MemoryModel):
identifier_attribute: ClassVar[str] = "user_name" pass
class Group(canaille.core.models.Group, MemoryModel): class Group(canaille.core.models.Group, MemoryModel):
identifier_attribute: ClassVar[str] = "display_name" pass
class Client(canaille.oidc.models.Client, MemoryModel): class Client(canaille.oidc.models.Client, MemoryModel):
identifier_attribute: ClassVar[str] = "client_id" pass
class AuthorizationCode(canaille.oidc.models.AuthorizationCode, MemoryModel): class AuthorizationCode(canaille.oidc.models.AuthorizationCode, MemoryModel):
identifier_attribute: ClassVar[str] = "authorization_code_id" pass
class Token(canaille.oidc.models.Token, MemoryModel): class Token(canaille.oidc.models.Token, MemoryModel):
identifier_attribute: ClassVar[str] = "token_id" pass
class Consent(canaille.oidc.models.Consent, MemoryModel): class Consent(canaille.oidc.models.Consent, MemoryModel):
identifier_attribute: ClassVar[str] = "consent_id" pass

View file

@ -69,6 +69,16 @@ class Model:
} }
return cls._attributes return cls._attributes
@property
def identifier(self):
"""Returns a unique value that will be used to identify the model
instance.
This value will be used in URLs in canaille, so it should be
unique and short.
"""
return getattr(self, self.identifier_attribute)
class BackendModel: class BackendModel:
"""The backend model abstract class. """The backend model abstract class.
@ -109,16 +119,6 @@ class BackendModel:
return only one element or :py:data:`None` if no item is matching.""" return only one element or :py:data:`None` if no item is matching."""
raise NotImplementedError() raise NotImplementedError()
@property
def identifier(self):
"""Returns a unique value that will be used to identify the model
instance.
This value will be used in URLs in canaille, so it should be
unique and short.
"""
raise NotImplementedError()
def save(self): def save(self):
"""Validates the current modifications in the database.""" """Validates the current modifications in the database."""
raise NotImplementedError() raise NotImplementedError()

View file

@ -95,10 +95,6 @@ class SqlAlchemyModel(BackendModel):
.scalar_one_or_none() .scalar_one_or_none()
) )
@property
def identifier(self):
return getattr(self, self.identifier_attribute)
def save(self): def save(self):
self.last_modified = datetime.datetime.now(datetime.timezone.utc).replace( self.last_modified = datetime.datetime.now(datetime.timezone.utc).replace(
microsecond=0 microsecond=0
@ -127,7 +123,6 @@ membership_association_table = Table(
class User(canaille.core.models.User, Base, SqlAlchemyModel): class User(canaille.core.models.User, Base, SqlAlchemyModel):
__tablename__ = "user" __tablename__ = "user"
identifier_attribute = "user_name"
id: Mapped[str] = mapped_column( id: Mapped[str] = mapped_column(
String, primary_key=True, default=lambda: str(uuid.uuid4()) String, primary_key=True, default=lambda: str(uuid.uuid4())
@ -171,7 +166,6 @@ class User(canaille.core.models.User, Base, SqlAlchemyModel):
class Group(canaille.core.models.Group, Base, SqlAlchemyModel): class Group(canaille.core.models.Group, Base, SqlAlchemyModel):
__tablename__ = "group" __tablename__ = "group"
identifier_attribute = "display_name"
id: Mapped[str] = mapped_column( id: Mapped[str] = mapped_column(
String, primary_key=True, default=lambda: str(uuid.uuid4()) String, primary_key=True, default=lambda: str(uuid.uuid4())
@ -200,7 +194,6 @@ client_audience_association_table = Table(
class Client(canaille.oidc.models.Client, Base, SqlAlchemyModel): class Client(canaille.oidc.models.Client, Base, SqlAlchemyModel):
__tablename__ = "client" __tablename__ = "client"
identifier_attribute = "client_id"
id: Mapped[str] = mapped_column( id: Mapped[str] = mapped_column(
String, primary_key=True, default=lambda: str(uuid.uuid4()) String, primary_key=True, default=lambda: str(uuid.uuid4())
@ -250,7 +243,6 @@ class Client(canaille.oidc.models.Client, Base, SqlAlchemyModel):
class AuthorizationCode(canaille.oidc.models.AuthorizationCode, Base, SqlAlchemyModel): class AuthorizationCode(canaille.oidc.models.AuthorizationCode, Base, SqlAlchemyModel):
__tablename__ = "authorization_code" __tablename__ = "authorization_code"
identifier_attribute = "authorization_code_id"
id: Mapped[str] = mapped_column( id: Mapped[str] = mapped_column(
String, primary_key=True, default=lambda: str(uuid.uuid4()) String, primary_key=True, default=lambda: str(uuid.uuid4())
@ -293,7 +285,6 @@ token_audience_association_table = Table(
class Token(canaille.oidc.models.Token, Base, SqlAlchemyModel): class Token(canaille.oidc.models.Token, Base, SqlAlchemyModel):
__tablename__ = "token" __tablename__ = "token"
identifier_attribute = "token_id"
id: Mapped[str] = mapped_column( id: Mapped[str] = mapped_column(
String, primary_key=True, default=lambda: str(uuid.uuid4()) String, primary_key=True, default=lambda: str(uuid.uuid4())
@ -331,7 +322,6 @@ class Token(canaille.oidc.models.Token, Base, SqlAlchemyModel):
class Consent(canaille.oidc.models.Consent, Base, SqlAlchemyModel): class Consent(canaille.oidc.models.Consent, Base, SqlAlchemyModel):
__tablename__ = "consent" __tablename__ = "consent"
identifier_attribute = "consent_id"
id: Mapped[str] = mapped_column( id: Mapped[str] = mapped_column(
String, primary_key=True, default=lambda: str(uuid.uuid4()) String, primary_key=True, default=lambda: str(uuid.uuid4())

View file

@ -1,5 +1,6 @@
import datetime import datetime
from typing import Annotated from typing import Annotated
from typing import ClassVar
from typing import List from typing import List
from typing import Optional from typing import Optional
@ -23,6 +24,8 @@ class User(Model):
implementation in Canaille. implementation in Canaille.
""" """
identifier_attribute: ClassVar[str] = "user_name"
user_name: str user_name: str
"""A service provider's unique identifier for the user, typically used by """A service provider's unique identifier for the user, typically used by
the user to directly authenticate to the service provider. the user to directly authenticate to the service provider.
@ -325,6 +328,8 @@ class Group(Model):
<https://datatracker.ietf.org/doc/html/rfc7643#section-4.2>`_. <https://datatracker.ietf.org/doc/html/rfc7643#section-4.2>`_.
""" """
identifier_attribute: ClassVar[str] = "display_name"
display_name: str display_name: str
"""A human-readable name for the Group. """A human-readable name for the Group.

View file

@ -1,4 +1,5 @@
import datetime import datetime
from typing import ClassVar
from typing import List from typing import List
from typing import Optional from typing import Optional
@ -16,6 +17,8 @@ class Client(Model):
specifications. specifications.
""" """
identifier_attribute: ClassVar[str] = "client_id"
description: Optional[str] = None description: Optional[str] = None
preconsent: Optional[bool] = False preconsent: Optional[bool] = False
audience: List["Client"] = [] audience: List["Client"] = []
@ -288,6 +291,8 @@ class Client(Model):
class AuthorizationCode(Model): class AuthorizationCode(Model):
"""OpenID Connect temporary authorization code definition.""" """OpenID Connect temporary authorization code definition."""
identifier_attribute: ClassVar[str] = "authorization_code_id"
authorization_code_id: str authorization_code_id: str
code: str code: str
client: "Client" client: "Client"
@ -306,6 +311,8 @@ class AuthorizationCode(Model):
class Token(Model): class Token(Model):
"""OpenID Connect token definition.""" """OpenID Connect token definition."""
identifier_attribute: ClassVar[str] = "token_id"
token_id: str token_id: str
access_token: str access_token: str
client: "Client" client: "Client"
@ -322,6 +329,8 @@ class Token(Model):
class Consent(Model): class Consent(Model):
"""Long-term user consent to an application.""" """Long-term user consent to an application."""
identifier_attribute: ClassVar[str] = "consent_id"
consent_id: str consent_id: str
subject: User subject: User
client: "Client" client: "Client"