Compare commits
5 commits
7442047d0e
...
1995095627
Author | SHA1 | Date | |
---|---|---|---|
1995095627 | |||
5d15ef9720 | |||
b4d6cfb0ed | |||
f6d0912c03 | |||
639b0de8b1 |
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -5,6 +5,16 @@ All notable changes to WuttJamaican will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## v0.7.0 (2024-07-14)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- add basic "auth" data models: user/role/perm
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- always use 'wutta' prefix for provider entry points
|
||||||
|
|
||||||
## v0.6.1 (2024-07-12)
|
## v0.6.1 (2024-07-12)
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
|
|
6
docs/api/wuttjamaican/auth.rst
Normal file
6
docs/api/wuttjamaican/auth.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wuttjamaican.auth``
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. automodule:: wuttjamaican.auth
|
||||||
|
:members:
|
6
docs/api/wuttjamaican/db.model.auth.rst
Normal file
6
docs/api/wuttjamaican/db.model.auth.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
``wuttjamaican.db.model.auth``
|
||||||
|
==============================
|
||||||
|
|
||||||
|
.. automodule:: wuttjamaican.db.model.auth
|
||||||
|
:members:
|
|
@ -8,10 +8,12 @@
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
app
|
app
|
||||||
|
auth
|
||||||
conf
|
conf
|
||||||
db
|
db
|
||||||
db.conf
|
db.conf
|
||||||
db.model
|
db.model
|
||||||
|
db.model.auth
|
||||||
db.model.base
|
db.model.base
|
||||||
db.sess
|
db.sess
|
||||||
exc
|
exc
|
||||||
|
|
|
@ -55,6 +55,12 @@ Glossary
|
||||||
|
|
||||||
See also the code-friendly :term:`app name`.
|
See also the code-friendly :term:`app name`.
|
||||||
|
|
||||||
|
auth handler
|
||||||
|
A :term:`handler` responsible for user authentication and
|
||||||
|
authorization (login, permissions) and related things.
|
||||||
|
|
||||||
|
See also :class:`~wuttjamaican.auth.AuthHandler`.
|
||||||
|
|
||||||
command
|
command
|
||||||
A top-level command line interface for the app. Note that
|
A top-level command line interface for the app. Note that
|
||||||
top-level commands don't usually "do" anything per se, and are
|
top-level commands don't usually "do" anything per se, and are
|
||||||
|
@ -71,6 +77,9 @@ Glossary
|
||||||
happens is, a config object is created and then extended by each
|
happens is, a config object is created and then extended by each
|
||||||
of the registered config extensions.
|
of the registered config extensions.
|
||||||
|
|
||||||
|
The intention is that all config extensions will have been
|
||||||
|
applied before the :term:`app handler` is created.
|
||||||
|
|
||||||
config file
|
config file
|
||||||
A file which contains :term:`config settings<config setting>`.
|
A file which contains :term:`config settings<config setting>`.
|
||||||
See also :doc:`narr/config/files`.
|
See also :doc:`narr/config/files`.
|
||||||
|
|
|
@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "WuttJamaican"
|
name = "WuttJamaican"
|
||||||
version = "0.6.1"
|
version = "0.7.0"
|
||||||
description = "Base package for Wutta Framework"
|
description = "Base package for Wutta Framework"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
|
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
|
||||||
|
@ -38,9 +38,9 @@ tests = ["pytest-cov", "tox"]
|
||||||
|
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://rattailproject.org/"
|
Homepage = "https://wuttaproject.org/"
|
||||||
Repository = "https://kallithea.rattailproject.org/rattail-project/wuttjamaican"
|
Repository = "https://forgejo.wuttaproject.org/wutta/wuttjamaican"
|
||||||
Changelog = "https://kallithea.rattailproject.org/rattail-project/wuttjamaican/files/master/CHANGELOG.md"
|
Changelog = "https://forgejo.wuttaproject.org/wutta/wuttjamaican/src/branch/master/CHANGELOG.md"
|
||||||
|
|
||||||
|
|
||||||
[tool.commitizen]
|
[tool.commitizen]
|
||||||
|
|
|
@ -105,9 +105,6 @@ class AppHandler:
|
||||||
self.providers = self.get_all_providers()
|
self.providers = self.get_all_providers()
|
||||||
return self.providers
|
return self.providers
|
||||||
|
|
||||||
# if 'providers' not in self.__dict__:
|
|
||||||
# self.__dict__['providers'] = self.get_all_providers()
|
|
||||||
|
|
||||||
for provider in self.providers.values():
|
for provider in self.providers.values():
|
||||||
if hasattr(provider, name):
|
if hasattr(provider, name):
|
||||||
return getattr(provider, name)
|
return getattr(provider, name)
|
||||||
|
@ -121,10 +118,22 @@ class AppHandler:
|
||||||
Note that you do not need to call this directly; instead just
|
Note that you do not need to call this directly; instead just
|
||||||
use :attr:`providers`.
|
use :attr:`providers`.
|
||||||
|
|
||||||
|
The discovery logic is based on :term:`entry points<entry
|
||||||
|
point>` using the ``wutta.app.providers`` group. For instance
|
||||||
|
here is a sample entry point used by WuttaWeb (in its
|
||||||
|
``pyproject.toml``):
|
||||||
|
|
||||||
|
.. code-block:: toml
|
||||||
|
|
||||||
|
[project.entry-points."wutta.app.providers"]
|
||||||
|
wuttaweb = "wuttaweb.app:WebAppProvider"
|
||||||
|
|
||||||
:returns: Dictionary keyed by entry point name; values are
|
:returns: Dictionary keyed by entry point name; values are
|
||||||
:class:`AppProvider` *instances*.
|
:class:`AppProvider` instances.
|
||||||
"""
|
"""
|
||||||
providers = load_entry_points(f'{self.appname}.providers')
|
# nb. must use 'wutta' and not self.appname prefix here, or
|
||||||
|
# else we can't find all providers with custom appname
|
||||||
|
providers = load_entry_points('wutta.app.providers')
|
||||||
for key in list(providers):
|
for key in list(providers):
|
||||||
providers[key] = providers[key](self.config)
|
providers[key] = providers[key](self.config)
|
||||||
return providers
|
return providers
|
||||||
|
@ -278,8 +287,7 @@ class AppProvider:
|
||||||
These can add arbitrary extra functionality to the main :term:`app
|
These can add arbitrary extra functionality to the main :term:`app
|
||||||
handler`. See also :doc:`/narr/providers/app`.
|
handler`. See also :doc:`/narr/providers/app`.
|
||||||
|
|
||||||
:param config: Config object for the app. This should be an
|
:param config: The app :term:`config object`.
|
||||||
instance of :class:`~wuttjamaican.conf.WuttaConfig`.
|
|
||||||
|
|
||||||
Instances have the following attributes:
|
Instances have the following attributes:
|
||||||
|
|
||||||
|
@ -301,7 +309,16 @@ class AppProvider:
|
||||||
config = config.config
|
config = config.config
|
||||||
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.app = config.get_app()
|
self.app = self.config.get_app()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def appname(self):
|
||||||
|
"""
|
||||||
|
The :term:`app name` for the current app.
|
||||||
|
|
||||||
|
See also :attr:`AppHandler.appname`.
|
||||||
|
"""
|
||||||
|
return self.app.appname
|
||||||
|
|
||||||
|
|
||||||
class GenericHandler:
|
class GenericHandler:
|
||||||
|
@ -318,3 +335,12 @@ class GenericHandler:
|
||||||
def __init__(self, config, **kwargs):
|
def __init__(self, config, **kwargs):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.app = self.config.get_app()
|
self.app = self.config.get_app()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def appname(self):
|
||||||
|
"""
|
||||||
|
The :term:`app name` for the current app.
|
||||||
|
|
||||||
|
See also :attr:`AppHandler.appname`.
|
||||||
|
"""
|
||||||
|
return self.app.appname
|
||||||
|
|
44
src/wuttjamaican/auth.py
Normal file
44
src/wuttjamaican/auth.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# WuttJamaican -- Base package for Wutta Framework
|
||||||
|
# Copyright © 2023-2024 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework is free software: you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
# later version.
|
||||||
|
#
|
||||||
|
# Wutta Framework is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Auth Handler
|
||||||
|
|
||||||
|
This defines the default :term:`auth handler`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from wuttjamaican.app import GenericHandler
|
||||||
|
|
||||||
|
|
||||||
|
class AuthHandler(GenericHandler):
|
||||||
|
"""
|
||||||
|
Base class and default implementation for the :term:`auth
|
||||||
|
handler`.
|
||||||
|
|
||||||
|
This is responsible for "authentication and authorization" - for
|
||||||
|
instance:
|
||||||
|
|
||||||
|
* create new users, roles
|
||||||
|
* grant/revoke role permissions
|
||||||
|
* determine which permissions a user has
|
||||||
|
* identify user from login credentials
|
||||||
|
"""
|
|
@ -21,14 +21,21 @@
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
"""
|
"""
|
||||||
WuttJamaican - database model
|
Data Models
|
||||||
|
|
||||||
For convenience, from this ``wuttjamaican.db.model`` namespace you can
|
This is the default :term:`app model` module.
|
||||||
access the following:
|
|
||||||
|
|
||||||
|
The ``wuttjamaican.db.model`` namespace contains the following:
|
||||||
|
|
||||||
|
* :func:`~wuttjamaican.db.model.base.uuid_column()`
|
||||||
|
* :func:`~wuttjamaican.db.model.base.uuid_fk_column()`
|
||||||
* :class:`~wuttjamaican.db.model.base.Base`
|
* :class:`~wuttjamaican.db.model.base.Base`
|
||||||
* :class:`~wuttjamaican.db.model.base.Setting`
|
* :class:`~wuttjamaican.db.model.base.Setting`
|
||||||
* :func:`~wuttjamaican.db.model.base.uuid_column()`
|
* :class:`~wuttjamaican.db.model.auth.Role`
|
||||||
|
* :class:`~wuttjamaican.db.model.auth.Permission`
|
||||||
|
* :class:`~wuttjamaican.db.model.auth.User`
|
||||||
|
* :class:`~wuttjamaican.db.model.auth.UserRole`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .base import Base, uuid_column, Setting
|
from .base import Base, Setting, uuid_column, uuid_fk_column
|
||||||
|
from .auth import Role, Permission, User, UserRole
|
||||||
|
|
229
src/wuttjamaican/db/model/auth.py
Normal file
229
src/wuttjamaican/db/model/auth.py
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# WuttJamaican -- Base package for Wutta Framework
|
||||||
|
# Copyright © 2023-2024 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Wutta Framework.
|
||||||
|
#
|
||||||
|
# Wutta Framework is free software: you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
# later version.
|
||||||
|
#
|
||||||
|
# Wutta Framework is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Auth Models
|
||||||
|
|
||||||
|
The :term:`auth handler` is primarily responsible for managing the
|
||||||
|
data for these models.
|
||||||
|
|
||||||
|
Basic design/structure is as follows:
|
||||||
|
|
||||||
|
* :class:`User` may be assigned to multiple roles
|
||||||
|
* :class:`Role` may contain multiple users (cf. :class:`UserRole`)
|
||||||
|
* :class:`Role` may be granted multiple permissions
|
||||||
|
* :class:`Permission` is a permission granted to a role
|
||||||
|
* roles are not nested/grouped; each is independent
|
||||||
|
* a few roles are built-in, e.g. Administrators
|
||||||
|
|
||||||
|
So a user's permissions are "inherited" from the role(s) to which they
|
||||||
|
belong.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy import orm
|
||||||
|
from sqlalchemy.ext.associationproxy import association_proxy
|
||||||
|
|
||||||
|
from .base import Base, uuid_column, uuid_fk_column
|
||||||
|
|
||||||
|
|
||||||
|
class Role(Base):
|
||||||
|
"""
|
||||||
|
Represents an authentication role within the system; used for
|
||||||
|
permission management.
|
||||||
|
|
||||||
|
.. attribute:: permissions
|
||||||
|
|
||||||
|
List of keys (string names) for permissions granted to this
|
||||||
|
role.
|
||||||
|
|
||||||
|
See also :attr:`permission_refs`.
|
||||||
|
|
||||||
|
.. attribute:: users
|
||||||
|
|
||||||
|
List of :class:`User` instances belonging to this role.
|
||||||
|
|
||||||
|
See also :attr:`user_refs`.
|
||||||
|
"""
|
||||||
|
__tablename__ = 'role'
|
||||||
|
__table_args__ = (
|
||||||
|
sa.UniqueConstraint('name',
|
||||||
|
# TODO
|
||||||
|
# name='role_uq_name',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
uuid = uuid_column()
|
||||||
|
|
||||||
|
name = sa.Column(sa.String(length=100), nullable=False, doc="""
|
||||||
|
Name for the role. Each role must have a name, which must be
|
||||||
|
unique.
|
||||||
|
""")
|
||||||
|
|
||||||
|
notes = sa.Column(sa.Text(), nullable=True, doc="""
|
||||||
|
Arbitrary notes for the role.
|
||||||
|
""")
|
||||||
|
|
||||||
|
permission_refs = orm.relationship(
|
||||||
|
'Permission',
|
||||||
|
back_populates='role',
|
||||||
|
doc="""
|
||||||
|
List of :class:`Permission` references for the role.
|
||||||
|
|
||||||
|
See also :attr:`permissions`.
|
||||||
|
""")
|
||||||
|
|
||||||
|
permissions = association_proxy(
|
||||||
|
'permission_refs', 'permission',
|
||||||
|
creator=lambda p: Permission(permission=p),
|
||||||
|
# TODO
|
||||||
|
# getset_factory=getset_factory,
|
||||||
|
)
|
||||||
|
|
||||||
|
user_refs = orm.relationship(
|
||||||
|
'UserRole',
|
||||||
|
# TODO
|
||||||
|
# cascade='all, delete-orphan',
|
||||||
|
# cascade_backrefs=False,
|
||||||
|
back_populates='role',
|
||||||
|
doc="""
|
||||||
|
List of :class:`UserRole` instances belonging to the role.
|
||||||
|
|
||||||
|
See also :attr:`users`.
|
||||||
|
""")
|
||||||
|
|
||||||
|
users = association_proxy(
|
||||||
|
'user_refs', 'user',
|
||||||
|
creator=lambda u: UserRole(user=u),
|
||||||
|
# TODO
|
||||||
|
# getset_factory=getset_factory,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name or ""
|
||||||
|
|
||||||
|
|
||||||
|
class Permission(Base):
|
||||||
|
"""
|
||||||
|
Represents a permission granted to a role.
|
||||||
|
"""
|
||||||
|
__tablename__ = 'permission'
|
||||||
|
__table_args__ = (
|
||||||
|
sa.ForeignKeyConstraint(['role_uuid'], ['role.uuid'],
|
||||||
|
# TODO
|
||||||
|
# name='permission_fk_role',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
role_uuid = uuid_fk_column(primary_key=True, nullable=False)
|
||||||
|
role = orm.relationship(
|
||||||
|
Role,
|
||||||
|
back_populates='permission_refs',
|
||||||
|
doc="""
|
||||||
|
Reference to the :class:`Role` for which the permission is
|
||||||
|
granted.
|
||||||
|
""")
|
||||||
|
|
||||||
|
permission = sa.Column(sa.String(length=254), primary_key=True, doc="""
|
||||||
|
Key (name) of the permission which is granted.
|
||||||
|
""")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.permission or ""
|
||||||
|
|
||||||
|
|
||||||
|
class User(Base):
|
||||||
|
"""
|
||||||
|
Represents a user of the system.
|
||||||
|
|
||||||
|
This may or may not correspond to a real person, i.e. some users
|
||||||
|
may exist solely for automated tasks.
|
||||||
|
"""
|
||||||
|
__tablename__ = 'user'
|
||||||
|
__table_args__ = (
|
||||||
|
sa.UniqueConstraint('username',
|
||||||
|
# TODO
|
||||||
|
# name='user_uq_username',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
uuid = uuid_column()
|
||||||
|
|
||||||
|
username = sa.Column(sa.String(length=25), nullable=False, doc="""
|
||||||
|
Account username. This is required and must be unique.
|
||||||
|
""")
|
||||||
|
|
||||||
|
password = sa.Column(sa.String(length=60), nullable=True, doc="""
|
||||||
|
Hashed password for login. (The raw password is not stored.)
|
||||||
|
""")
|
||||||
|
|
||||||
|
active = sa.Column(sa.Boolean(), nullable=False, default=True, doc="""
|
||||||
|
Flag indicating whether the user account is "active" - it is
|
||||||
|
``True`` by default.
|
||||||
|
|
||||||
|
The default auth logic will prevent login for "inactive" user accounts.
|
||||||
|
""")
|
||||||
|
|
||||||
|
role_refs = orm.relationship(
|
||||||
|
'UserRole',
|
||||||
|
back_populates='user',
|
||||||
|
doc="""
|
||||||
|
List of :class:`UserRole` records.
|
||||||
|
""")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.username or ""
|
||||||
|
|
||||||
|
|
||||||
|
class UserRole(Base):
|
||||||
|
"""
|
||||||
|
Represents the association between a user and a role.
|
||||||
|
"""
|
||||||
|
__tablename__ = 'user_x_role'
|
||||||
|
__table_args__ = (
|
||||||
|
sa.ForeignKeyConstraint(['user_uuid'], ['user.uuid'],
|
||||||
|
# TODO
|
||||||
|
# name='user_x_role_fk_user',
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(['role_uuid'], ['role.uuid'],
|
||||||
|
# TODO
|
||||||
|
# name='user_x_role_fk_role',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
uuid = uuid_column()
|
||||||
|
|
||||||
|
user_uuid = uuid_fk_column(nullable=False)
|
||||||
|
user = orm.relationship(
|
||||||
|
User,
|
||||||
|
back_populates='role_refs',
|
||||||
|
doc="""
|
||||||
|
Reference to the :class:`User` involved.
|
||||||
|
""")
|
||||||
|
|
||||||
|
role_uuid = uuid_fk_column(nullable=False)
|
||||||
|
role = orm.relationship(
|
||||||
|
Role,
|
||||||
|
back_populates='user_refs',
|
||||||
|
doc="""
|
||||||
|
Reference to the :class:`Role` involved.
|
||||||
|
""")
|
|
@ -21,7 +21,7 @@
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
"""
|
"""
|
||||||
WuttJamaican - base models
|
Base Models
|
||||||
|
|
||||||
.. class:: Base
|
.. class:: Base
|
||||||
|
|
||||||
|
@ -47,6 +47,13 @@ def uuid_column(*args, **kwargs):
|
||||||
return sa.Column(sa.String(length=32), *args, **kwargs)
|
return sa.Column(sa.String(length=32), *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def uuid_fk_column(*args, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns a UUID column for use as a foreign key to another table.
|
||||||
|
"""
|
||||||
|
return sa.Column(sa.String(length=32), *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Setting(Base):
|
class Setting(Base):
|
||||||
"""
|
"""
|
||||||
Represents a :term:`config setting`.
|
Represents a :term:`config setting`.
|
||||||
|
|
2
tasks.py
2
tasks.py
|
@ -30,7 +30,7 @@ def release(c, skip_tests=False):
|
||||||
Release a new version of WuttJamaican
|
Release a new version of WuttJamaican
|
||||||
"""
|
"""
|
||||||
if not skip_tests:
|
if not skip_tests:
|
||||||
c.run('tox')
|
c.run('pytest')
|
||||||
|
|
||||||
# rebuild local tar.gz file for distribution
|
# rebuild local tar.gz file for distribution
|
||||||
if os.path.exists('WuttJamaican.egg-info'):
|
if os.path.exists('WuttJamaican.egg-info'):
|
||||||
|
|
36
tests/db/model/test_auth.py
Normal file
36
tests/db/model/test_auth.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from wuttjamaican.db.model import auth as model
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
|
||||||
|
class TestRole(TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
role = model.Role()
|
||||||
|
self.assertEqual(str(role), "")
|
||||||
|
role.name = "Managers"
|
||||||
|
self.assertEqual(str(role), "Managers")
|
||||||
|
|
||||||
|
|
||||||
|
class TestPermission(TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
perm = model.Permission()
|
||||||
|
self.assertEqual(str(perm), "")
|
||||||
|
perm.permission = 'users.create'
|
||||||
|
self.assertEqual(str(perm), "users.create")
|
||||||
|
|
||||||
|
|
||||||
|
class TestUser(TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
user = model.User()
|
||||||
|
self.assertEqual(str(user), "")
|
||||||
|
user.username = 'barney'
|
||||||
|
self.assertEqual(str(user), "barney")
|
|
@ -14,7 +14,16 @@ else:
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
column = model.uuid_column()
|
column = model.uuid_column()
|
||||||
self.assertIsInstance(column, sa.Column)
|
self.assertIsInstance(column, sa.Column)
|
||||||
|
self.assertIsInstance(column.type, sa.String)
|
||||||
|
self.assertEqual(column.type.length, 32)
|
||||||
|
|
||||||
|
class TestUUIDFKColumn(TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
column = model.uuid_column()
|
||||||
|
self.assertIsInstance(column, sa.Column)
|
||||||
|
self.assertIsInstance(column.type, sa.String)
|
||||||
|
self.assertEqual(column.type.length, 32)
|
||||||
|
|
||||||
class TestSetting(TestCase):
|
class TestSetting(TestCase):
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ class TestAppProvider(TestCase):
|
||||||
provider = app.AppProvider(self.config)
|
provider = app.AppProvider(self.config)
|
||||||
self.assertIs(provider.config, self.config)
|
self.assertIs(provider.config, self.config)
|
||||||
self.assertIs(provider.app, self.app)
|
self.assertIs(provider.app, self.app)
|
||||||
|
self.assertEqual(provider.appname, 'wuttatest')
|
||||||
|
|
||||||
# but can pass app handler instead
|
# but can pass app handler instead
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
@ -155,7 +156,7 @@ class TestAppProvider(TestCase):
|
||||||
|
|
||||||
# sanity check, we get *instances* back from this
|
# sanity check, we get *instances* back from this
|
||||||
providers = self.app.get_all_providers()
|
providers = self.app.get_all_providers()
|
||||||
load_entry_points.assert_called_once_with('wuttatest.providers')
|
load_entry_points.assert_called_once_with('wutta.app.providers')
|
||||||
self.assertEqual(len(providers), 1)
|
self.assertEqual(len(providers), 1)
|
||||||
self.assertIn('fake', providers)
|
self.assertIn('fake', providers)
|
||||||
self.assertIsInstance(providers['fake'], FakeProvider)
|
self.assertIsInstance(providers['fake'], FakeProvider)
|
||||||
|
@ -212,3 +213,4 @@ class TestGenericHandler(TestCase):
|
||||||
handler = app.GenericHandler(self.config)
|
handler = app.GenericHandler(self.config)
|
||||||
self.assertIs(handler.config, self.config)
|
self.assertIs(handler.config, self.config)
|
||||||
self.assertIs(handler.app, self.app)
|
self.assertIs(handler.app, self.app)
|
||||||
|
self.assertEqual(handler.appname, 'wuttatest')
|
||||||
|
|
17
tests/test_auth.py
Normal file
17
tests/test_auth.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from wuttjamaican import auth as mod
|
||||||
|
from wuttjamaican.conf import WuttaConfig
|
||||||
|
|
||||||
|
|
||||||
|
class TestAuthHandler(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.config = WuttaConfig()
|
||||||
|
self.app = self.config.get_app()
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
handler = mod.AuthHandler(self.config)
|
||||||
|
self.assertIs(handler.app, self.app)
|
Loading…
Reference in a new issue