Compare commits
1 Commits
e4c552af01
...
12b0bf55f8
Author | SHA1 | Date |
---|---|---|
Ferdinand Thiessen | 12b0bf55f8 |
|
@ -17,3 +17,5 @@ matrix:
|
||||||
PYTHON:
|
PYTHON:
|
||||||
- 3.10
|
- 3.10
|
||||||
- 3.9
|
- 3.9
|
||||||
|
- 3.8
|
||||||
|
- 3.7
|
||||||
|
|
19
README.md
19
README.md
|
@ -7,29 +7,20 @@ This is the backend of the Flaschengeist.
|
||||||
### Requirements
|
### Requirements
|
||||||
- `mysql` or `mariadb`
|
- `mysql` or `mariadb`
|
||||||
- maybe `libmariadb` development files[1]
|
- maybe `libmariadb` development files[1]
|
||||||
- python 3.9+
|
- python 3.7+
|
||||||
- pip 21.0+
|
|
||||||
|
|
||||||
*[1] By default Flaschengeist uses mysql as database backend, if you are on Windows Flaschengeist uses `PyMySQL`, but on
|
[1] By default Flaschengeist uses mysql as database backend, if you are on Windows Flaschengeist uses `PyMySQL`, but on
|
||||||
Linux / Mac the faster `mysqlclient` is used, if it is not already installed installing from pypi requires the
|
Linux / Mac the faster `mysqlclient` is used, if it is not already installed installing from pypi requires the
|
||||||
development files for `libmariadb` to be present on your system.*
|
development files for `libmariadb` to be present on your system.
|
||||||
|
|
||||||
### Install python files
|
### Install python files
|
||||||
It is recommended to upgrade pip to the latest version before installing:
|
pip3 install --user .
|
||||||
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
|
|
||||||
Default installation with *mariadb*/*mysql* support:
|
|
||||||
|
|
||||||
pip3 install --user ".[mysql]"
|
|
||||||
|
|
||||||
or with ldap support
|
or with ldap support
|
||||||
|
|
||||||
pip3 install --user ".[ldap]"
|
pip3 install --user ".[ldap]"
|
||||||
|
|
||||||
or if you want to also run the tests:
|
or if you want to also run the tests:
|
||||||
|
|
||||||
pip3 install --user ".[ldap,tests]"
|
pip3 install --user ".[ldap,test]"
|
||||||
|
|
||||||
You will also need a MySQL driver, recommended drivers are
|
You will also need a MySQL driver, recommended drivers are
|
||||||
- `mysqlclient`
|
- `mysqlclient`
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
"""Controller for Plugin logic
|
|
||||||
|
|
||||||
Used by plugins for setting and notification functionality.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sqlalchemy
|
|
||||||
from ..database import db
|
|
||||||
from ..models.setting import _PluginSetting
|
|
||||||
from ..models.notification import Notification
|
|
||||||
|
|
||||||
|
|
||||||
def get_setting(plugin_id: str, name: str, **kwargs):
|
|
||||||
"""Get plugin setting from database
|
|
||||||
|
|
||||||
Args:
|
|
||||||
plugin_id: ID of the plugin
|
|
||||||
name: string identifying the setting
|
|
||||||
default: Default value
|
|
||||||
Returns:
|
|
||||||
Value stored in database (native python)
|
|
||||||
Raises:
|
|
||||||
`KeyError` if no such setting exists in the database
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
setting = (
|
|
||||||
_PluginSetting.query.filter(_PluginSetting.plugin == plugin_id).filter(_PluginSetting.name == name).one()
|
|
||||||
)
|
|
||||||
return setting.value
|
|
||||||
except sqlalchemy.orm.exc.NoResultFound:
|
|
||||||
if "default" in kwargs:
|
|
||||||
return kwargs["default"]
|
|
||||||
else:
|
|
||||||
raise KeyError
|
|
||||||
|
|
||||||
|
|
||||||
def set_setting(plugin_id: str, name: str, value):
|
|
||||||
"""Save setting in database
|
|
||||||
|
|
||||||
Args:
|
|
||||||
plugin_id: ID of the plugin
|
|
||||||
name: String identifying the setting
|
|
||||||
value: Value to be stored
|
|
||||||
"""
|
|
||||||
setting = (
|
|
||||||
_PluginSetting.query.filter(_PluginSetting.plugin == plugin_id)
|
|
||||||
.filter(_PluginSetting.name == name)
|
|
||||||
.one_or_none()
|
|
||||||
)
|
|
||||||
if setting is not None:
|
|
||||||
if value is None:
|
|
||||||
db.session.delete(setting)
|
|
||||||
else:
|
|
||||||
setting.value = value
|
|
||||||
else:
|
|
||||||
db.session.add(_PluginSetting(plugin=plugin_id, name=name, value=value))
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def notify(plugin_id: str, user, text: str, data=None):
|
|
||||||
"""Create a new notification for an user
|
|
||||||
|
|
||||||
Args:
|
|
||||||
plugin_id: ID of the plugin
|
|
||||||
user: `flaschengeist.models.user.User` to notify
|
|
||||||
text: Visibile notification text
|
|
||||||
data: Optional data passed to the notificaton
|
|
||||||
Returns:
|
|
||||||
ID of the created `flaschengeist.models.notification.Notification`
|
|
||||||
|
|
||||||
Hint: use the data for frontend actions.
|
|
||||||
"""
|
|
||||||
if not user.deleted:
|
|
||||||
n = Notification(text=text, data=data, plugin=plugin_id, user_=user)
|
|
||||||
db.session.add(n)
|
|
||||||
db.session.commit()
|
|
||||||
return n.id
|
|
|
@ -1,9 +1,13 @@
|
||||||
from flask import Blueprint
|
|
||||||
from dataclasses import asdict, dataclass, field
|
from dataclasses import asdict, dataclass, field
|
||||||
|
from flask import Blueprint
|
||||||
from werkzeug.datastructures import FileStorage
|
from werkzeug.datastructures import FileStorage
|
||||||
from werkzeug.exceptions import MethodNotAllowed, NotFound
|
from werkzeug.exceptions import MethodNotAllowed, NotFound
|
||||||
|
|
||||||
|
from flaschengeist.database import db
|
||||||
|
from flaschengeist.controller import imageController
|
||||||
|
from flaschengeist.models.notification import Notification
|
||||||
from flaschengeist.models.user import _Avatar, User
|
from flaschengeist.models.user import _Avatar, User
|
||||||
|
from flaschengeist.models.setting import _PluginSetting
|
||||||
from flaschengeist.utils.hook import HookBefore, HookAfter
|
from flaschengeist.utils.hook import HookBefore, HookAfter
|
||||||
|
|
||||||
plugins_installed = HookAfter("plugins.installed")
|
plugins_installed = HookAfter("plugins.installed")
|
||||||
|
@ -129,9 +133,18 @@ class Plugin(PluginMetadata):
|
||||||
Raises:
|
Raises:
|
||||||
`KeyError` if no such setting exists in the database
|
`KeyError` if no such setting exists in the database
|
||||||
"""
|
"""
|
||||||
from ..controller import pluginController
|
try:
|
||||||
|
setting = (
|
||||||
return pluginController.get_setting(self.id)
|
_PluginSetting.query.filter(_PluginSetting.plugin == self.name)
|
||||||
|
.filter(_PluginSetting.name == name)
|
||||||
|
.one()
|
||||||
|
)
|
||||||
|
return setting.value
|
||||||
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
|
if "default" in kwargs:
|
||||||
|
return kwargs["default"]
|
||||||
|
else:
|
||||||
|
raise KeyError
|
||||||
|
|
||||||
def set_setting(self, name: str, value):
|
def set_setting(self, name: str, value):
|
||||||
"""Save setting in database
|
"""Save setting in database
|
||||||
|
@ -140,9 +153,19 @@ class Plugin(PluginMetadata):
|
||||||
name: String identifying the setting
|
name: String identifying the setting
|
||||||
value: Value to be stored
|
value: Value to be stored
|
||||||
"""
|
"""
|
||||||
from ..controller import pluginController
|
setting = (
|
||||||
|
_PluginSetting.query.filter(_PluginSetting.plugin == self.name)
|
||||||
return pluginController.set_setting(self.id, name, value)
|
.filter(_PluginSetting.name == name)
|
||||||
|
.one_or_none()
|
||||||
|
)
|
||||||
|
if setting is not None:
|
||||||
|
if value is None:
|
||||||
|
db.session.delete(setting)
|
||||||
|
else:
|
||||||
|
setting.value = value
|
||||||
|
else:
|
||||||
|
db.session.add(_PluginSetting(plugin=self.name, name=name, value=value))
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
def notify(self, user, text: str, data=None):
|
def notify(self, user, text: str, data=None):
|
||||||
"""Create a new notification for an user
|
"""Create a new notification for an user
|
||||||
|
@ -156,9 +179,11 @@ class Plugin(PluginMetadata):
|
||||||
|
|
||||||
Hint: use the data for frontend actions.
|
Hint: use the data for frontend actions.
|
||||||
"""
|
"""
|
||||||
from ..controller import pluginController
|
if not user.deleted:
|
||||||
|
n = Notification(text=text, data=data, plugin=self.id, user_=user)
|
||||||
return pluginController.notify(self.id, user, text, data)
|
db.session.add(n)
|
||||||
|
db.session.commit()
|
||||||
|
return n.id
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
"""Serialize a plugin into a dict
|
"""Serialize a plugin into a dict
|
||||||
|
@ -258,10 +283,6 @@ class AuthPlugin(Plugin):
|
||||||
MethodNotAllowed: If not supported by Backend
|
MethodNotAllowed: If not supported by Backend
|
||||||
Any valid HTTP exception
|
Any valid HTTP exception
|
||||||
"""
|
"""
|
||||||
# By default save the image to the avatar,
|
|
||||||
# deleting would happen by unsetting it
|
|
||||||
from ..controller import imageController
|
|
||||||
|
|
||||||
user.avatar_ = imageController.upload_image(file)
|
user.avatar_ = imageController.upload_image(file)
|
||||||
|
|
||||||
def delete_avatar(self, user: User):
|
def delete_avatar(self, user: User):
|
||||||
|
|
Loading…
Reference in New Issue