From 88e3f0280d366abdc59e436a9643bbdb6b6d28fb Mon Sep 17 00:00:00 2001 From: grimhilt Date: Thu, 14 Sep 2023 23:21:02 +0200 Subject: [PATCH] not push --- README.md | 41 ++++++++++++++++++++++++++++++------ src/api/abl/UserAbl.py | 26 +++++------------------ src/api/controllers/file.py | 2 +- src/api/dao/ParentRoleDao.py | 15 +++++++++++++ src/api/dao/Playlist.py | 2 +- src/api/dao/RolesDao.py | 31 +++++++++++++++++++++++++++ src/api/dao/UsersDao.py | 26 +++++++++++++++++++++++ src/api/models.py | 22 ++++++++++++++++++- src/index.py | 10 ++++++--- src/screen/SlideShow.py | 6 ++++-- 10 files changed, 145 insertions(+), 36 deletions(-) create mode 100644 src/api/dao/ParentRoleDao.py create mode 100644 src/api/dao/RolesDao.py diff --git a/README.md b/README.md index b227c19..3666a5c 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,36 @@ # Deployment (from source) - ``git clone https://github.com/grimhilt/artemio-server.git`` - +- python3 -m venv .venv source .venv/bin/activate python -m pip install -r requirements.txt +sudo apt install libjpeg-dev zlib1g-dev +pip install Pillow + +sudo apt install libmpv-dev + +gunicorn -w 1 -b 0.0.0.0:5500 index:api --access-logfile access.log --error-logfile error.log # Documentation ## API -/api/login -/api/logout +### Permissions + +| Name | Child Of | Description +| --- | --- | --- +CREATE_USER | +CREATE_ROLE | +CREATE_PLAYLIST | +VIEW_PLAYLIST | EDIT_PLAYLIST +OWN_PLAYLIST | +EDIT_PLAYLIST | OWN_PLAYLIST +ACTIVATE_PLAYLIST | + ### Playlists (*/api/playlists*) -The user need to be logged in for every routes +*The user need to be logged in for every routes.* | Method | Endpoint | Permission | Description | --- | --- | --- | --- | @@ -26,13 +42,24 @@ The user need to be logged in for every routes | POST | ``/api/playlists/:id`` | EDIT_PLAYLIST | Add file to playlist | POST | ``/api/playlists/:id/order`` | EDIT_PLAYLIST | Change file order | POST | ``/api/playlists/:id/seconds`` | EDIT_PLAYLIST | Change display time of a file -| POST | ``/api/playlists/:id/remove_file`` | EDIT_PLAYLIST | -| PUT | ``/api/playlists/:id/update`` | OWN_PLAYLIST | +| POST | ``/api/playlists/:id/remove_file`` | EDIT_PLAYLIST | Remove file from the playlist +| PUT | ``/api/playlists/:id/update`` | OWN_PLAYLIST | Update properties of the playlist | POST | ``/api/playlists/:id/activate`` | ACTIVATE_PLAYLIST | | POST | ``/api/playlists/:id/disactivate`` | ACTIVATE_PLAYLIST | ### Users +### Playlists (*/api/playlists*) + +*The user need to be logged in for every routes.* + +| Method | Endpoint | Permission | Description +| --- | --- | --- | --- | +| GET | ``/api/files`` | EDIT_PLAYLIST | List all existing files +| GET | ``/api/files/:id`` | VIEW_PLAYLIST | Return the file +| POST | ``/api/files/upload`` | EDIT_PLAYLIST | Upload one or multiple files +| DELETE | ``/api/files/:id`` | OWN_PLAYLIST | Delete the file + ### Roles -### \ No newline at end of file +### Files diff --git a/src/api/abl/UserAbl.py b/src/api/abl/UserAbl.py index 959febd..ba14bb7 100644 --- a/src/api/abl/UserAbl.py +++ b/src/api/abl/UserAbl.py @@ -1,13 +1,13 @@ from flask import Blueprint, request, jsonify -from werkzeug.security import generate_password_hash, check_password_hash +from werkzeug.security import check_password_hash from flask_login import current_user from ..models import User, Role +from api.dao.UsersDao import UsersDao from .. import db def is_current_admin(): return current_user.as_dict()['roles'][0]['parent_id'] is None - class UserAbl: @staticmethod @@ -27,30 +27,14 @@ class UserAbl: if bit == '1' and bit != user_perms[position]: return jsonify(message="You don't have the permission to give permission(s) you don't have"), 403 - # create the user - new_user = User( - login=login, - password=generate_password_hash(password, method='sha256') - ) - - db.session.add(new_user) - db.session.flush() - - # create the permissions for the user - new_role = Role( - name=login, - user_id=new_user.as_dict()['id'], - parent_id=current_user.as_dict()['roles'][0]['id'], - permissions=permissions) - db.session.add(new_role) - new_user.roles.append(new_role) - db.session.flush() - + # create user + new_user = UsersDao.create(login, password, permissions, current_user) db.session.commit() return jsonify(new_user.as_dict()) @staticmethod def update(user_id, data): + # todo return jsonify() @staticmethod diff --git a/src/api/controllers/file.py b/src/api/controllers/file.py index 4aa6da5..3f6f7f0 100644 --- a/src/api/controllers/file.py +++ b/src/api/controllers/file.py @@ -5,7 +5,7 @@ from ..models import File from .. import db files = Blueprint('files', __name__) -FILE_DIR = './data/' +FILE_DIR = '../data/' @files.route('/files', methods=['POST']) @login_required diff --git a/src/api/dao/ParentRoleDao.py b/src/api/dao/ParentRoleDao.py new file mode 100644 index 0000000..5aa1540 --- /dev/null +++ b/src/api/dao/ParentRoleDao.py @@ -0,0 +1,15 @@ +from .. import db +from ..models import User, Role, Playlist, ParentRole + +class ParentRoleDao: + def get_children(role_id): + children = db.session.query(ParentRole) \ + .filter(ParentRole.parent_id == role_id) \ + .all() + return children + + def get_parents(role_id): + parents = db.session.query(ParentRole) \ + .filter(ParentRole.child_id == role_id) \ + .all() + return parents diff --git a/src/api/dao/Playlist.py b/src/api/dao/Playlist.py index c4a9e6e..efede93 100644 --- a/src/api/dao/Playlist.py +++ b/src/api/dao/Playlist.py @@ -31,7 +31,7 @@ class PlaylistDao: .first() return has_role_to_view - def has_role_view_d(playlist_id, user_id): + def has_role_edit_d(playlist_id, user_id): has_role_to_edit = db.session.query(Playlist) \ .filter( Playlist.edit.any( diff --git a/src/api/dao/RolesDao.py b/src/api/dao/RolesDao.py new file mode 100644 index 0000000..d55d9aa --- /dev/null +++ b/src/api/dao/RolesDao.py @@ -0,0 +1,31 @@ +from .. import db +from ..models import User, Role, Playlist, ParentRole +from .ParentRoleDao import ParentRoleDao + +class RolesDao: + + def create(name, user_id, parent_id, permissions): + new_role = Role( + name=name, + user_id=user_id, + parent_id=parent_id, + permissions=permissions) + db.session.add(new_role) + + # get all parents + parents = ParentRoleDao.get_parents(parent_id) + parent_ids = [parent_id] + for parent in parents: + parent_ids.append(parent.as_dict()['parent_id']) + + # add all parents + for id in parent_ids: + parent_role = ParentRole( + parent_id=id, + child_id=user_id + ) + db.session.add(parent_role) + + db.session.flush() + return new_role + diff --git a/src/api/dao/UsersDao.py b/src/api/dao/UsersDao.py index f966e23..7b6eaf7 100644 --- a/src/api/dao/UsersDao.py +++ b/src/api/dao/UsersDao.py @@ -1,7 +1,32 @@ from .. import db +from werkzeug.security import generate_password_hash, check_password_hash from ..models import User, Role, Playlist +from .RolesDao import RolesDao class UsersDao: + + def create(login, password, permissions, current_user): + # create the user + new_user = User( + login=login, + password=generate_password_hash(password, method='sha256') + ) + + db.session.add(new_user) + db.session.flush() + + # create role for the user + new_role = RolesDao.create( + name=login, + user_id=new_user.as_dict()['id'], + parent_id=current_user.as_dict()['roles'][0]['id'], + permissions=permissions) + + new_user.roles.append(new_role) + db.session.flush() + return new_user + + def has_role_view_q(user_id): has_role_to_view = db.session.query(User) \ .filter(User.id == user_id) \ @@ -23,6 +48,7 @@ class UsersDao: return has_role_to_edit def playlists(user_id): + # todo recursion on user parenting playlists = db.session.query(Playlist) \ .filter( # all playlist where user can view diff --git a/src/api/models.py b/src/api/models.py index 30181eb..408a30f 100644 --- a/src/api/models.py +++ b/src/api/models.py @@ -55,16 +55,36 @@ class UserRole(db.Model): user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) role_id = db.Column(db.Integer, db.ForeignKey('role.id'), primary_key=True) +class ParentRole(db.Model): + __tablename__ = 'ParentRole' + parent_id = db.Column(db.Integer, db.ForeignKey('role.id'), primary_key=True) + child_id = db.Column(db.Integer, db.ForeignKey('role.id'), primary_key=True) + + def as_dict(self): + return {c.name: getattr(self, c.name) for c in self.__table__.columns} + + class Role(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), default=None) permissions = db.Column(db.Integer, default=0) parent_id = db.Column(db.Integer, db.ForeignKey('role.id'), default=None) + children = db.relationship('Role', secondary="ParentRole", + primaryjoin=id == ParentRole.parent_id, + secondaryjoin=id == ParentRole.child_id, + backref='parents') + users = db.relationship('User', secondary='UserRole', back_populates='roles') playlists_view = db.relationship('Playlist', secondary='PlaylistView', back_populates='view') playlists_edit = db.relationship('Playlist', secondary='PlaylistEdit', back_populates='edit') + def as_full_dict(self): + res = self.as_dict() + res['parents'] = [parent.as_dict() for parent in self.parents] + res['children'] = [child.as_dict() for child in self.children] + return res + def as_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} @@ -76,7 +96,7 @@ class User(db.Model, UserMixin): def as_dict(self): res = self.as_dict_unsafe() - res['roles'] = [role.as_dict() for role in self.roles] + res['roles'] = [role.as_full_dict() for role in self.roles] del res['password'] return res diff --git a/src/index.py b/src/index.py index 21e4134..1f7bb3a 100644 --- a/src/index.py +++ b/src/index.py @@ -1,12 +1,16 @@ from api import create_api from screen.ScreenManager import ScreenManager -#api = create_api() -#screen_manager = ScreenManager().getInstance() +api = create_api() +screen_manager = ScreenManager().getInstance() if __name__ == '__main__': #api.run(host="0.0.0.0", port=5500, debug=True) - #api.run(host="0.0.0.0", port=5500) + #api.run() + + api.run(host="0.0.0.0", port=5500) + +def test(): from screen.SlideShow import SlideShow import tkinter as tk import mpv diff --git a/src/screen/SlideShow.py b/src/screen/SlideShow.py index e4e5a11..f558229 100644 --- a/src/screen/SlideShow.py +++ b/src/screen/SlideShow.py @@ -7,6 +7,8 @@ import imageio import vlc import mpv +DATA_DIR = "../data/" + class SlideShow: def __init__(self, root, files): print(files) @@ -62,7 +64,7 @@ class MediaFactory: def image_player(self): print("image player") - path = './data/' + self.file['name'] + path = DATA_DIR + self.file['name'] image = Image.open(path) image = self.parent.resize_full_screen(image) @@ -78,7 +80,7 @@ class VideoPlayer: def __init__(self, parent, file): self.file = file self.parent = parent - self.path = './data/' + self.file['name'] + self.path = DATA_DIR + self.file['name'] #self.mpv_instance = mpv.MPV(wid=str(self.parent.canvas.winfo_id())) instance = vlc.Instance() player = instance.media_player_new()