Compare commits
2 Commits
ee38e46c12
...
4248825af0
Author | SHA1 | Date |
---|---|---|
Ferdinand Thiessen | 4248825af0 | |
Ferdinand Thiessen | e22e38b304 |
|
@ -25,6 +25,7 @@ def get_enabled_plugins():
|
||||||
class PluginStub:
|
class PluginStub:
|
||||||
def __init__(self, name) -> None:
|
def __init__(self, name) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.version = "?"
|
||||||
|
|
||||||
logger.error("Could not connect to database or database not initialized! No plugins enabled!")
|
logger.error("Could not connect to database or database not initialized! No plugins enabled!")
|
||||||
logger.debug("Can not query enabled plugins", exc_info=True)
|
logger.debug("Can not query enabled plugins", exc_info=True)
|
||||||
|
|
|
@ -11,7 +11,36 @@ from ..database import db
|
||||||
lifetime = 1800
|
lifetime = 1800
|
||||||
|
|
||||||
|
|
||||||
def validate_token(token, user_agent, permission):
|
def __get_user_agent_platform(ua: str):
|
||||||
|
if "Win" in ua:
|
||||||
|
return "Windows"
|
||||||
|
if "Mac" in ua:
|
||||||
|
return "Macintosh"
|
||||||
|
if "Linux" in ua:
|
||||||
|
return "Linux"
|
||||||
|
if "Android" in ua:
|
||||||
|
return "Android"
|
||||||
|
if "like Mac" in ua:
|
||||||
|
return "iOS"
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def __get_user_agent_browser(ua: str):
|
||||||
|
ua_str = ua.lower()
|
||||||
|
if "firefox" in ua_str or "fxios" in ua_str:
|
||||||
|
return "firefox"
|
||||||
|
if "safari" in ua_str:
|
||||||
|
return "safari"
|
||||||
|
if "opr/" in ua_str:
|
||||||
|
return "opera"
|
||||||
|
if "edg" in ua_str:
|
||||||
|
return "edge"
|
||||||
|
if "chrom" in ua_str or "crios" in ua_str:
|
||||||
|
return "chrome"
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def validate_token(token, request_headers, permission):
|
||||||
"""Verify session
|
"""Verify session
|
||||||
|
|
||||||
Verify a Session and Roles so if the User has permission or not.
|
Verify a Session and Roles so if the User has permission or not.
|
||||||
|
@ -19,7 +48,7 @@ def validate_token(token, user_agent, permission):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
token: Token to verify.
|
token: Token to verify.
|
||||||
user_agent: User agent of browser to check
|
request_headers: Headers to validate user agent of browser
|
||||||
permission: Permission needed to access restricted routes
|
permission: Permission needed to access restricted routes
|
||||||
Returns:
|
Returns:
|
||||||
A Session for this given Token
|
A Session for this given Token
|
||||||
|
@ -31,8 +60,16 @@ def validate_token(token, user_agent, permission):
|
||||||
session = Session.query.filter_by(token=token).one_or_none()
|
session = Session.query.filter_by(token=token).one_or_none()
|
||||||
if session:
|
if session:
|
||||||
logger.debug("token found, check if expired or invalid user agent differs")
|
logger.debug("token found, check if expired or invalid user agent differs")
|
||||||
|
|
||||||
|
platform = request_headers.get("Sec-CH-UA-Platform", None) or __get_user_agent_platform(
|
||||||
|
request_headers.get("User-Agent", "")
|
||||||
|
)
|
||||||
|
browser = request_headers.get("Sec-CH-UA", None) or __get_user_agent_browser(
|
||||||
|
request_headers.get("User-Agent", "")
|
||||||
|
)
|
||||||
|
|
||||||
if session.expires >= datetime.now(timezone.utc) and (
|
if session.expires >= datetime.now(timezone.utc) and (
|
||||||
session.browser == user_agent.browser and session.platform == user_agent.platform
|
session.browser == browser and session.platform == platform
|
||||||
):
|
):
|
||||||
if not permission or session.user_.has_permission(permission):
|
if not permission or session.user_.has_permission(permission):
|
||||||
session.refresh()
|
session.refresh()
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import annotations # TODO: Remove if python requirement is >= 3.12 (? PEP 563 is defered)
|
||||||
|
|
||||||
from sqlalchemy import event
|
from sqlalchemy import event
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import annotations # TODO: Remove if python requirement is >= 3.12 (? PEP 563 is defered)
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
@ -14,8 +16,8 @@ class Notification(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
user_id_: int = db.Column("user", Serial, db.ForeignKey("user.id"), nullable=False)
|
user_id_: int = db.Column("user", Serial, db.ForeignKey("user.id"), nullable=False)
|
||||||
plugin_id_: int = db.Column("plugin", Serial, db.ForeignKey("plugin.id"), nullable=False)
|
plugin_id_: int = db.Column("plugin", Serial, db.ForeignKey("plugin.id"), nullable=False)
|
||||||
user_: "User" = db.relationship("User")
|
user_: User = db.relationship("User")
|
||||||
plugin_: "Plugin" = db.relationship(
|
plugin_: Plugin = db.relationship(
|
||||||
"Plugin", backref=db.backref("notifications_", cascade="all, delete, delete-orphan")
|
"Plugin", backref=db.backref("notifications_", cascade="all, delete, delete-orphan")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import annotations # TODO: Remove if python requirement is >= 3.12 (? PEP 563 is defered)
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from ..database import db
|
from ..database import db
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
from __future__ import annotations # TODO: Remove if python requirement is >= 3.12 (? PEP 563 is defered)
|
||||||
|
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from secrets import compare_digest
|
from secrets import compare_digest
|
||||||
|
|
||||||
|
from .. import logger
|
||||||
from ..database import db
|
from ..database import db
|
||||||
from ..database.types import ModelSerializeMixin, UtcDateTime, Serial
|
from ..database.types import ModelSerializeMixin, UtcDateTime, Serial
|
||||||
|
|
||||||
from flaschengeist import logger
|
|
||||||
|
|
||||||
|
|
||||||
class Session(db.Model, ModelSerializeMixin):
|
class Session(db.Model, ModelSerializeMixin):
|
||||||
"""Model for a Session
|
"""Model for a Session
|
||||||
|
@ -20,13 +21,13 @@ class Session(db.Model, ModelSerializeMixin):
|
||||||
expires: datetime = db.Column(UtcDateTime)
|
expires: datetime = db.Column(UtcDateTime)
|
||||||
token: str = db.Column(db.String(32), unique=True)
|
token: str = db.Column(db.String(32), unique=True)
|
||||||
lifetime: int = db.Column(db.Integer)
|
lifetime: int = db.Column(db.Integer)
|
||||||
browser: str = db.Column(db.String(30))
|
browser: str = db.Column(db.String(127))
|
||||||
platform: str = db.Column(db.String(30))
|
platform: str = db.Column(db.String(64))
|
||||||
userid: str = ""
|
userid: str = ""
|
||||||
|
|
||||||
_id = db.Column("id", Serial, primary_key=True)
|
_id = db.Column("id", Serial, primary_key=True)
|
||||||
_user_id = db.Column("user_id", Serial, db.ForeignKey("user.id"))
|
_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
|
@property
|
||||||
def userid(self):
|
def userid(self):
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import annotations # TODO: Remove if python requirement is >= 3.12 (? PEP 563 is defered)
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||||
|
@ -62,10 +64,10 @@ class User(db.Model, ModelSerializeMixin):
|
||||||
# Protected stuff for backend use only
|
# Protected stuff for backend use only
|
||||||
id_ = db.Column("id", Serial, primary_key=True)
|
id_ = db.Column("id", Serial, primary_key=True)
|
||||||
roles_: list[Role] = db.relationship("Role", secondary=association_table, cascade="save-update, merge")
|
roles_: list[Role] = db.relationship("Role", secondary=association_table, cascade="save-update, merge")
|
||||||
sessions_: list["Session"] = db.relationship(
|
sessions_: list[Session] = db.relationship(
|
||||||
"Session", back_populates="user_", cascade="all, delete, delete-orphan"
|
"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")
|
reset_requests_: list["_PasswordReset"] = db.relationship("_PasswordReset", cascade="all, delete, delete-orphan")
|
||||||
|
|
||||||
# Private stuff for internal use
|
# Private stuff for internal use
|
||||||
|
|
|
@ -14,7 +14,7 @@ def extract_session(permission=None):
|
||||||
logger.debug("Missing Authorization header or ill-formed")
|
logger.debug("Missing Authorization header or ill-formed")
|
||||||
raise Unauthorized
|
raise Unauthorized
|
||||||
|
|
||||||
session = sessionController.validate_token(token, request.user_agent, permission)
|
session = sessionController.validate_token(token, request.headers, permission)
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,14 @@ include_package_data = True
|
||||||
python_requires = >=3.10
|
python_requires = >=3.10
|
||||||
packages = find:
|
packages = find:
|
||||||
install_requires =
|
install_requires =
|
||||||
Flask==2.0.3
|
Flask>=2.2.2
|
||||||
Pillow>=9.0
|
Pillow>=9.2
|
||||||
flask_cors
|
flask_cors
|
||||||
flask_migrate>=3.1.0
|
flask_migrate>=3.1.0
|
||||||
flask_sqlalchemy>=2.5.1
|
flask_sqlalchemy>=2.5.1
|
||||||
sqlalchemy>=1.4.39
|
sqlalchemy>=1.4.40
|
||||||
toml
|
toml
|
||||||
werkzeug==2.0.3
|
werkzeug>=2.2.2
|
||||||
|
|
||||||
[options.extras_require]
|
[options.extras_require]
|
||||||
argon = argon2-cffi
|
argon = argon2-cffi
|
||||||
|
|
Loading…
Reference in New Issue