feature/migrations, closes #19 #20
|
@ -9,6 +9,7 @@ from sqlalchemy.exc import OperationalError
|
|||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.models import Plugin
|
||||
from flaschengeist.utils.hook import Hook
|
||||
from flaschengeist.plugins import AuthPlugin
|
||||
from flaschengeist.config import config, configure_app
|
||||
|
|
|
@ -6,7 +6,7 @@ from importlib.metadata import EntryPoint, entry_points
|
|||
|
||||
from flaschengeist.database import db
|
||||
from flaschengeist.config import config
|
||||
from flaschengeist.models.user import Permission
|
||||
from flaschengeist.models import Permission
|
||||
|
||||
|
||||
@click.group()
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
from datetime import date
|
||||
from flask import send_file
|
||||
from pathlib import Path
|
||||
from flask import send_file
|
||||
from PIL import Image as PImage
|
||||
|
||||
from werkzeug.exceptions import NotFound, UnprocessableEntity
|
||||
from werkzeug.datastructures import FileStorage
|
||||
from werkzeug.utils import secure_filename
|
||||
from werkzeug.datastructures import FileStorage
|
||||
from werkzeug.exceptions import NotFound, UnprocessableEntity
|
||||
|
||||
from flaschengeist.models.image import Image
|
||||
from flaschengeist.database import db
|
||||
from flaschengeist.config import config
|
||||
from ..models import Image
|
||||
from ..database import db
|
||||
from ..config import config
|
||||
|
||||
|
||||
def check_mimetype(mime: str):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from flaschengeist.utils.hook import Hook
|
||||
from flaschengeist.models.user import User, Role
|
||||
from flaschengeist.models import User, Role
|
||||
|
||||
|
||||
class Message:
|
||||
|
|
|
@ -4,9 +4,16 @@ Used by plugins for setting and notification functionality.
|
|||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
from typing import Union
|
||||
from flask import current_app
|
||||
from werkzeug.exceptions import NotFound
|
||||
from importlib.metadata import entry_points
|
||||
|
||||
from .. import logger
|
||||
from ..database import db
|
||||
from ..models.setting import _PluginSetting
|
||||
from ..models.notification import Notification
|
||||
from ..utils import Hook
|
||||
from ..models import Plugin, PluginSetting, Notification
|
||||
|
||||
|
||||
def get_setting(plugin_id: str, name: str, **kwargs):
|
||||
|
@ -23,7 +30,7 @@ def get_setting(plugin_id: str, name: str, **kwargs):
|
|||
"""
|
||||
try:
|
||||
setting = (
|
||||
_PluginSetting.query.filter(_PluginSetting.plugin == plugin_id).filter(_PluginSetting.name == name).one()
|
||||
PluginSetting.query.filter(PluginSetting.plugin == plugin_id).filter(PluginSetting.name == name).one()
|
||||
)
|
||||
return setting.value
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
|
@ -42,8 +49,8 @@ def set_setting(plugin_id: str, name: str, value):
|
|||
value: Value to be stored
|
||||
"""
|
||||
setting = (
|
||||
_PluginSetting.query.filter(_PluginSetting.plugin == plugin_id)
|
||||
.filter(_PluginSetting.name == name)
|
||||
PluginSetting.query.filter(PluginSetting.plugin == plugin_id)
|
||||
.filter(PluginSetting.name == name)
|
||||
.one_or_none()
|
||||
)
|
||||
if setting is not None:
|
||||
|
@ -52,7 +59,7 @@ def set_setting(plugin_id: str, name: str, value):
|
|||
else:
|
||||
setting.value = value
|
||||
else:
|
||||
db.session.add(_PluginSetting(plugin=plugin_id, name=name, value=value))
|
||||
db.session.add(PluginSetting(plugin=plugin_id, name=name, value=value))
|
||||
db.session.commit()
|
||||
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ from typing import Union
|
|||
from sqlalchemy.exc import IntegrityError
|
||||
from werkzeug.exceptions import BadRequest, Conflict, NotFound
|
||||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.models.user import Role, Permission
|
||||
from flaschengeist.database import db, case_sensitive
|
||||
from flaschengeist.utils.hook import Hook
|
||||
from .. import logger
|
||||
from ..models import Role, Permission
|
||||
from ..database import db, case_sensitive
|
||||
from ..utils.hook import Hook
|
||||
|
||||
|
||||
def get_all():
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import secrets
|
||||
from flaschengeist.models.session import Session
|
||||
from flaschengeist.database import db
|
||||
from flaschengeist import logger
|
||||
from werkzeug.exceptions import Forbidden, Unauthorized
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from werkzeug.exceptions import Forbidden, Unauthorized
|
||||
|
||||
from .. import logger
|
||||
from ..models import Session
|
||||
from ..database import db
|
||||
|
||||
|
||||
lifetime = 1800
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import secrets
|
||||
import re
|
||||
import secrets
|
||||
|
||||
from io import BytesIO
|
||||
from sqlalchemy import exc
|
||||
from flask import current_app
|
||||
|
@ -7,15 +8,15 @@ from datetime import datetime, timedelta, timezone
|
|||
from flask.helpers import send_file
|
||||
from werkzeug.exceptions import NotFound, BadRequest, Forbidden
|
||||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.config import config
|
||||
from flaschengeist.database import db
|
||||
from flaschengeist.models.notification import Notification
|
||||
from flaschengeist.utils.hook import Hook
|
||||
from flaschengeist.utils.datetime import from_iso_format
|
||||
from flaschengeist.utils.foreign_keys import merge_references
|
||||
from flaschengeist.models.user import User, Role, _PasswordReset
|
||||
from flaschengeist.controller import imageController, messageController, sessionController
|
||||
from .. import logger
|
||||
from ..config import config
|
||||
from ..database import db
|
||||
from ..models import Notification, User, Role
|
||||
from ..models.user import _PasswordReset
|
||||
from ..utils.hook import Hook
|
||||
from ..utils.datetime import from_iso_format
|
||||
from ..utils.foreign_keys import merge_references
|
||||
from ..controller import imageController, messageController, sessionController
|
||||
|
||||
|
||||
def __active_users():
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import sys
|
||||
import datetime
|
||||
|
||||
from sqlalchemy import BigInteger, util
|
||||
from sqlalchemy.dialects import mysql, sqlite
|
||||
from sqlalchemy.types import DateTime, TypeDecorator
|
||||
|
||||
|
||||
class ModelSerializeMixin:
|
||||
"""Mixin class used for models to serialize them automatically
|
||||
Ignores private and protected members as well as members marked as not to publish (name ends with _)
|
||||
"""
|
||||
|
||||
def __is_optional(self, param):
|
||||
if sys.version_info < (3, 8):
|
||||
return False
|
||||
|
||||
import typing
|
||||
|
||||
hint = typing.get_type_hints(self.__class__)[param]
|
||||
if (
|
||||
typing.get_origin(hint) is typing.Union
|
||||
and len(typing.get_args(hint)) == 2
|
||||
and typing.get_args(hint)[1] is type(None)
|
||||
):
|
||||
return getattr(self, param) is None
|
||||
|
||||
def serialize(self):
|
||||
"""Serialize class to dict
|
||||
Returns:
|
||||
Dict of all not private or protected annotated member variables.
|
||||
"""
|
||||
d = {
|
||||
param: getattr(self, param)
|
||||
for param in self.__class__.__annotations__
|
||||
if not param.startswith("_") and not param.endswith("_") and not self.__is_optional(param)
|
||||
}
|
||||
if len(d) == 1:
|
||||
key, value = d.popitem()
|
||||
return value
|
||||
return d
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.serialize().__str__()
|
||||
|
||||
|
||||
class Serial(TypeDecorator):
|
||||
"""Same as MariaDB Serial used for IDs"""
|
||||
|
||||
cache_ok = True
|
||||
impl = BigInteger().with_variant(mysql.BIGINT(unsigned=True), "mysql").with_variant(sqlite.INTEGER(), "sqlite")
|
||||
|
||||
# https://alembic.sqlalchemy.org/en/latest/autogenerate.html?highlight=custom%20column#affecting-the-rendering-of-types-themselves
|
||||
def __repr__(self) -> str:
|
||||
return util.generic_repr(self)
|
||||
|
||||
|
||||
class UtcDateTime(TypeDecorator):
|
||||
"""Almost equivalent to `sqlalchemy.types.DateTime` with
|
||||
``timezone=True`` option, but it differs from that by:
|
||||
|
||||
- Never silently take naive :class:`datetime.datetime`, instead it
|
||||
always raise :exc:`ValueError` unless time zone aware value.
|
||||
- :class:`datetime.datetime` value's :attr:`datetime.datetime.tzinfo`
|
||||
is always converted to UTC.
|
||||
- Unlike SQLAlchemy's built-in :class:`sqlalchemy.types.DateTime`,
|
||||
it never return naive :class:`datetime.datetime`, but time zone
|
||||
aware value, even with SQLite or MySQL.
|
||||
"""
|
||||
|
||||
cache_ok = True
|
||||
impl = DateTime(timezone=True)
|
||||
|
||||
@staticmethod
|
||||
def current_utc():
|
||||
return datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is not None:
|
||||
if not isinstance(value, datetime.datetime):
|
||||
raise TypeError("expected datetime.datetime, not " + repr(value))
|
||||
elif value.tzinfo is None:
|
||||
raise ValueError("naive datetime is disallowed")
|
||||
return value.astimezone(datetime.timezone.utc)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is not None:
|
||||
if value.tzinfo is not None:
|
||||
value = value.astimezone(datetime.timezone.utc)
|
||||
value = value.replace(tzinfo=datetime.timezone.utc)
|
||||
return value
|
||||
|
||||
# https://alembic.sqlalchemy.org/en/latest/autogenerate.html?highlight=custom%20column#affecting-the-rendering-of-types-themselves
|
||||
def __repr__(self) -> str:
|
||||
return util.generic_repr(self)
|
|
@ -1,95 +1,5 @@
|
|||
import sys
|
||||
import datetime
|
||||
|
||||
from sqlalchemy import BigInteger, util
|
||||
from sqlalchemy.dialects import mysql, sqlite
|
||||
from sqlalchemy.types import DateTime, TypeDecorator
|
||||
|
||||
|
||||
class ModelSerializeMixin:
|
||||
"""Mixin class used for models to serialize them automatically
|
||||
Ignores private and protected members as well as members marked as not to publish (name ends with _)
|
||||
"""
|
||||
|
||||
def __is_optional(self, param):
|
||||
if sys.version_info < (3, 8):
|
||||
return False
|
||||
|
||||
import typing
|
||||
|
||||
hint = typing.get_type_hints(self.__class__)[param]
|
||||
if (
|
||||
typing.get_origin(hint) is typing.Union
|
||||
and len(typing.get_args(hint)) == 2
|
||||
and typing.get_args(hint)[1] is type(None)
|
||||
):
|
||||
return getattr(self, param) is None
|
||||
|
||||
def serialize(self):
|
||||
"""Serialize class to dict
|
||||
Returns:
|
||||
Dict of all not private or protected annotated member variables.
|
||||
"""
|
||||
d = {
|
||||
param: getattr(self, param)
|
||||
for param in self.__class__.__annotations__
|
||||
if not param.startswith("_") and not param.endswith("_") and not self.__is_optional(param)
|
||||
}
|
||||
if len(d) == 1:
|
||||
key, value = d.popitem()
|
||||
return value
|
||||
return d
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.serialize().__str__()
|
||||
|
||||
|
||||
class Serial(TypeDecorator):
|
||||
"""Same as MariaDB Serial used for IDs"""
|
||||
|
||||
cache_ok = True
|
||||
impl = BigInteger().with_variant(mysql.BIGINT(unsigned=True), "mysql").with_variant(sqlite.INTEGER(), "sqlite")
|
||||
|
||||
# https://alembic.sqlalchemy.org/en/latest/autogenerate.html?highlight=custom%20column#affecting-the-rendering-of-types-themselves
|
||||
def __repr__(self) -> str:
|
||||
return util.generic_repr(self)
|
||||
|
||||
|
||||
class UtcDateTime(TypeDecorator):
|
||||
"""Almost equivalent to `sqlalchemy.types.DateTime` with
|
||||
``timezone=True`` option, but it differs from that by:
|
||||
|
||||
- Never silently take naive :class:`datetime.datetime`, instead it
|
||||
always raise :exc:`ValueError` unless time zone aware value.
|
||||
- :class:`datetime.datetime` value's :attr:`datetime.datetime.tzinfo`
|
||||
is always converted to UTC.
|
||||
- Unlike SQLAlchemy's built-in :class:`sqlalchemy.types.DateTime`,
|
||||
it never return naive :class:`datetime.datetime`, but time zone
|
||||
aware value, even with SQLite or MySQL.
|
||||
"""
|
||||
|
||||
cache_ok = True
|
||||
impl = DateTime(timezone=True)
|
||||
|
||||
@staticmethod
|
||||
def current_utc():
|
||||
return datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is not None:
|
||||
if not isinstance(value, datetime.datetime):
|
||||
raise TypeError("expected datetime.datetime, not " + repr(value))
|
||||
elif value.tzinfo is None:
|
||||
raise ValueError("naive datetime is disallowed")
|
||||
return value.astimezone(datetime.timezone.utc)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is not None:
|
||||
if value.tzinfo is not None:
|
||||
value = value.astimezone(datetime.timezone.utc)
|
||||
value = value.replace(tzinfo=datetime.timezone.utc)
|
||||
return value
|
||||
|
||||
# https://alembic.sqlalchemy.org/en/latest/autogenerate.html?highlight=custom%20column#affecting-the-rendering-of-types-themselves
|
||||
def __repr__(self) -> str:
|
||||
return util.generic_repr(self)
|
||||
from .session import *
|
||||
from .user import *
|
||||
from .plugin import *
|
||||
from .notification import *
|
||||
from .image import *
|
|
@ -1,8 +1,8 @@
|
|||
from sqlalchemy import event
|
||||
from pathlib import Path
|
||||
|
||||
from . import ModelSerializeMixin, Serial
|
||||
from ..database import db
|
||||
from ..database.types import ModelSerializeMixin, Serial
|
||||
|
||||
|
||||
class Image(db.Model, ModelSerializeMixin):
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from . import Serial, UtcDateTime, ModelSerializeMixin
|
||||
from ..database import db
|
||||
from .user import User
|
||||
from ..database.types import Serial, UtcDateTime, ModelSerializeMixin
|
||||
|
||||
|
||||
class Notification(db.Model, ModelSerializeMixin):
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from typing import Any
|
||||
|
||||
from ..database import db
|
||||
from ..database.types import Serial
|
||||
|
||||
|
||||
class Plugin(db.Model):
|
||||
__tablename__ = "plugin"
|
||||
id: int = db.Column("id", Serial, primary_key=True)
|
||||
name: str = db.Column(db.String(127), nullable=False)
|
||||
version: str = db.Column(db.String(30), nullable=False)
|
||||
"""The latest installed version"""
|
||||
enabled: bool = db.Column(db.Boolean, default=False)
|
||||
|
||||
settings_ = db.relationship("PluginSetting", cascade="all, delete")
|
||||
permissions_ = db.relationship("Permission", cascade="all, delete")
|
||||
|
||||
|
||||
class PluginSetting(db.Model):
|
||||
__tablename__ = "plugin_setting"
|
||||
id = db.Column("id", Serial, primary_key=True)
|
||||
plugin_id: int = db.Column("plugin", Serial, db.ForeignKey("plugin.id"))
|
||||
name: str = db.Column(db.String(127), nullable=False)
|
||||
value: Any = db.Column(db.PickleType(protocol=4))
|
|
@ -1,5 +1,9 @@
|
|||
from datetime import datetime, timedelta, timezone
|
||||
from secrets import compare_digest
|
||||
|
||||
from ..database import db
|
||||
from ..database.types import ModelSerializeMixin, UtcDateTime, Serial
|
||||
|
||||
from flaschengeist import logger
|
||||
|
||||
|
||||
|
@ -22,7 +26,7 @@ class Session(db.Model, ModelSerializeMixin):
|
|||
|
||||
_id = db.Column("id", Serial, primary_key=True)
|
||||
_user_id = db.Column("user_id", Serial, db.ForeignKey("user.id"))
|
||||
user_: User = db.relationship("User", back_populates="sessions_")
|
||||
user_: "User" = db.relationship("User", back_populates="sessions_")
|
||||
|
||||
@property
|
||||
def userid(self):
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
|
||||
from typing import Any
|
||||
|
||||
from . import Serial
|
||||
from ..database import db
|
||||
|
||||
|
||||
class _PluginSetting(db.Model):
|
||||
__tablename__ = "plugin_setting"
|
||||
id = db.Column("id", Serial, primary_key=True)
|
||||
plugin: str = db.Column(db.String(127))
|
||||
name: str = db.Column(db.String(127), nullable=False)
|
||||
value: Any = db.Column(db.PickleType(protocol=4))
|
|
@ -3,9 +3,7 @@ from datetime import date, datetime
|
|||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
|
||||
from ..database import db
|
||||
from . import ModelSerializeMixin, UtcDateTime, Serial
|
||||
from .image import Image
|
||||
|
||||
from ..database.types import ModelSerializeMixin, UtcDateTime, Serial
|
||||
|
||||
association_table = db.Table(
|
||||
"user_x_role",
|
||||
|
@ -19,7 +17,6 @@ role_permission_association_table = db.Table(
|
|||
db.Column("permission_id", Serial, db.ForeignKey("permission.id")),
|
||||
)
|
||||
|
||||
|
||||
class Permission(db.Model, ModelSerializeMixin):
|
||||
__tablename__ = "permission"
|
||||
name: str = db.Column(db.String(30), unique=True)
|
||||
|
@ -66,7 +63,7 @@ class User(db.Model, ModelSerializeMixin):
|
|||
sessions_: list["Session"] = db.relationship(
|
||||
"Session", back_populates="user_", cascade="all, delete, delete-orphan"
|
||||
)
|
||||
avatar_: Optional[Image] = db.relationship("Image", cascade="all, delete, delete-orphan", single_parent=True)
|
||||
avatar_: Optional["Image"] = db.relationship("Image", cascade="all, delete, delete-orphan", single_parent=True)
|
||||
reset_requests_: list["_PasswordReset"] = db.relationship("_PasswordReset", cascade="all, delete, delete-orphan")
|
||||
|
||||
# Private stuff for internal use
|
||||
|
|
|
@ -9,7 +9,8 @@ from importlib.metadata import Distribution, EntryPoint
|
|||
from werkzeug.exceptions import MethodNotAllowed, NotFound
|
||||
from werkzeug.datastructures import FileStorage
|
||||
|
||||
from flaschengeist.models.user import _Avatar, User
|
||||
from flaschengeist.models import User
|
||||
from flaschengeist.models.user import _Avatar
|
||||
from flaschengeist.utils.hook import HookBefore, HookAfter
|
||||
|
||||
__all__ = [
|
||||
|
@ -19,7 +20,7 @@ __all__ = [
|
|||
"before_role_updated",
|
||||
"before_update_user",
|
||||
"after_role_updated",
|
||||
"Plugin",
|
||||
"BasePlugin",
|
||||
"AuthPlugin",
|
||||
]
|
||||
|
||||
|
@ -70,7 +71,7 @@ Passed args:
|
|||
"""
|
||||
|
||||
|
||||
class Plugin:
|
||||
class BasePlugin:
|
||||
"""Base class for all Plugins
|
||||
|
||||
All plugins must derived from this class.
|
||||
|
@ -193,10 +194,10 @@ class Plugin:
|
|||
return {"version": self.version, "permissions": self.permissions}
|
||||
|
||||
|
||||
class AuthPlugin(Plugin):
|
||||
class AuthPlugin(BasePlugin):
|
||||
"""Base class for all authentification plugins
|
||||
|
||||
See also `Plugin`
|
||||
See also `BasePlugin`
|
||||
"""
|
||||
|
||||
def login(self, user, pw):
|
||||
|
|
|
@ -6,13 +6,13 @@ from flask import Blueprint, request, jsonify
|
|||
from werkzeug.exceptions import Forbidden, BadRequest, Unauthorized
|
||||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.plugins import Plugin
|
||||
from flaschengeist.plugins import BasePlugin
|
||||
from flaschengeist.utils.HTTP import no_content, created
|
||||
from flaschengeist.utils.decorators import login_required
|
||||
from flaschengeist.controller import sessionController, userController
|
||||
|
||||
|
||||
class AuthRoutePlugin(Plugin):
|
||||
class AuthRoutePlugin(BasePlugin):
|
||||
blueprint = Blueprint("auth", __name__)
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ from werkzeug.datastructures import FileStorage
|
|||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.controller import userController
|
||||
from flaschengeist.models.user import User, Role, _Avatar
|
||||
from flaschengeist.models import User, Role
|
||||
from flaschengeist.models.user import _Avatar
|
||||
from flaschengeist.plugins import AuthPlugin, before_role_updated
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import hashlib
|
|||
import binascii
|
||||
from werkzeug.exceptions import BadRequest
|
||||
from flaschengeist.plugins import AuthPlugin, plugins_installed
|
||||
from flaschengeist.models.user import User, Role, Permission
|
||||
from flaschengeist.models import User, Role, Permission
|
||||
from flaschengeist.database import db
|
||||
from flaschengeist import logger
|
||||
|
||||
|
|
|
@ -3,15 +3,14 @@ from email.mime.text import MIMEText
|
|||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.models.user import User
|
||||
from flaschengeist.models import User
|
||||
from flaschengeist.plugins import BasePlugin
|
||||
from flaschengeist.utils.hook import HookAfter
|
||||
from flaschengeist.controller import userController
|
||||
from flaschengeist.controller.messageController import Message
|
||||
|
||||
from . import Plugin
|
||||
|
||||
|
||||
class MailMessagePlugin(Plugin):
|
||||
class MailMessagePlugin(BasePlugin):
|
||||
def __init__(self, entry_point, config):
|
||||
super().__init__(entry_point, config)
|
||||
self.server = config["SERVER"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flaschengeist.database import db
|
||||
from flaschengeist.models import ModelSerializeMixin, Serial
|
||||
from flaschengeist.models.image import Image
|
||||
from flaschengeist.database.types import ModelSerializeMixin, Serial
|
||||
from flaschengeist.models import Image
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
|
|
@ -5,17 +5,16 @@ Provides routes used to configure roles and permissions of users / roles.
|
|||
|
||||
from werkzeug.exceptions import BadRequest
|
||||
from flask import Blueprint, request, jsonify
|
||||
from http.client import NO_CONTENT
|
||||
|
||||
from flaschengeist.plugins import Plugin
|
||||
from flaschengeist.utils.decorators import login_required
|
||||
from flaschengeist.plugins import BasePlugin
|
||||
from flaschengeist.controller import roleController
|
||||
from flaschengeist.utils.HTTP import created, no_content
|
||||
from flaschengeist.utils.decorators import login_required
|
||||
|
||||
from . import permissions
|
||||
|
||||
|
||||
class RolesPlugin(Plugin):
|
||||
class RolesPlugin(BasePlugin):
|
||||
blueprint = Blueprint("roles", __name__)
|
||||
permissions = permissions.permissions
|
||||
|
||||
|
|
|
@ -2,10 +2,9 @@ from flask import Blueprint
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.plugins import BasePlugin
|
||||
from flaschengeist.utils.HTTP import no_content
|
||||
|
||||
from . import Plugin
|
||||
|
||||
|
||||
class __Task:
|
||||
def __init__(self, function, **kwags):
|
||||
|
@ -38,7 +37,7 @@ def scheduled(id: str, replace=False, **kwargs):
|
|||
return real_decorator
|
||||
|
||||
|
||||
class SchedulerPlugin(Plugin):
|
||||
class SchedulerPlugin(BasePlugin):
|
||||
def __init__(self, entry_point, config=None):
|
||||
super().__init__(entry_point, config)
|
||||
self.blueprint = Blueprint(self.name, __name__)
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
Provides routes used to manage users
|
||||
"""
|
||||
from http.client import NO_CONTENT, CREATED
|
||||
from http.client import CREATED
|
||||
from flask import Blueprint, request, jsonify, make_response
|
||||
from werkzeug.exceptions import BadRequest, Forbidden, MethodNotAllowed, NotFound
|
||||
from werkzeug.exceptions import BadRequest, Forbidden, MethodNotAllowed
|
||||
|
||||
from . import permissions
|
||||
from flaschengeist import logger
|
||||
from flaschengeist.config import config
|
||||
from flaschengeist.plugins import Plugin
|
||||
from flaschengeist.plugins import BasePlugin
|
||||
from flaschengeist.models.user import User
|
||||
from flaschengeist.utils.decorators import login_required, extract_session, headers
|
||||
from flaschengeist.controller import userController
|
||||
|
@ -17,7 +17,7 @@ from flaschengeist.utils.HTTP import created, no_content
|
|||
from flaschengeist.utils.datetime import from_iso_format
|
||||
|
||||
|
||||
class UsersPlugin(Plugin):
|
||||
class UsersPlugin(BasePlugin):
|
||||
blueprint = Blueprint("users", __name__)
|
||||
permissions = permissions.permissions
|
||||
|
||||
|
|
Loading…
Reference in New Issue