Commit fa42ef17428032c1f5c18a6f0badc1a680220fde
1 parent
834b86d05b
Exists in
master
add k2site compatibility
Showing 43 changed files with 437 additions and 724 deletions Side-by-side Diff
- __pycache__/main.cpython-310.pyc
- __pycache__/routes.cpython-310.pyc
- components/__pycache__/__init__.cpython-310.pyc
- components/k2adm/.gitignore
- components/k2adm/k2adm/languages/en/LC_MESSAGES/messages.mo
- components/k2adm/k2adm/languages/en/LC_MESSAGES/messages.po
- components/k2adm/k2adm/languages/uk/LC_MESSAGES/messages.mo
- components/k2adm/k2adm/languages/uk/LC_MESSAGES/messages.po
- components/k2adm/k2adm/models.py
- components/k2adm/k2adm/views.py
- components/k2adm/requirements.txt
- components/k2adm/setup.py
- components/k2auth/.gitignore
- components/k2auth/README.md
- components/k2auth/k2auth/models.py
- components/k2auth/k2auth/views.py
- components/k2auth/requirements.txt
- components/k2auth/setup.py
- components/k2test/__pycache__/__init__.cpython-310.pyc
- components/k2test/k2test/__pycache__/__init__.cpython-310.pyc
- components/k2test/k2test/__pycache__/views.cpython-310.pyc
- db/database.db
- k2/__pycache__/__init__.cpython-310.pyc
- k2/__pycache__/k2admmenu.cpython-310.pyc
- k2/__pycache__/k2cfg.cpython-310.pyc
- k2/__pycache__/k2comp.cpython-310.pyc
- k2/__pycache__/k2obj.cpython-310.pyc
- k2/__pycache__/k2rout.cpython-310.pyc
- k2/k2cfg.py
- k2/k2rout.py
- languages/en/LC_MESSAGES/messages.mo
- languages/en/LC_MESSAGES/messages.po
- languages/pl/LC_MESSAGES/messages.mo
- languages/pl/LC_MESSAGES/messages.po
- languages/uk/LC_MESSAGES/messages.mo
- languages/uk/LC_MESSAGES/messages.po
- main.py
- routes.py
- templates/base.html
- templates/component-info.html
- templates/dashboard-add.html
- templates/dashboard-list.html
- templates/dashboard.html
__pycache__/main.cpython-310.pyc
No preview for this file type
__pycache__/routes.cpython-310.pyc
No preview for this file type
components/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/k2adm/.gitignore
components/k2adm/k2adm/languages/en/LC_MESSAGES/messages.mo
No preview for this file type
components/k2adm/k2adm/languages/en/LC_MESSAGES/messages.po
| 1 | -msgid "title_menu_items" | |
| 2 | -msgstr "Site administration" | |
| 3 | - | |
| 4 | -msgid "menu_items_child_1" | |
| 5 | -msgstr "Password change" | |
| 6 | - | |
| 7 | -msgid "menu_items_child_2" | |
| 8 | -msgstr "New user" | |
| 9 | - | |
| 10 | -msgid "menu_items_child_3" | |
| 11 | -msgstr "Users" | |
| 12 | - | |
| 13 | - | |
| 14 | -msgid "menu_items_child_4" | |
| 15 | -msgstr "Users are clients" | |
| 16 | - | |
| 17 | - | |
| 18 | -msgid "menu_items_child_5" | |
| 19 | -msgstr "Roles" | |
| 20 | - | |
| 21 | - | |
| 22 | -msgid "menu_items_child_6" | |
| 23 | -msgstr "Access to the menu" |
components/k2adm/k2adm/languages/uk/LC_MESSAGES/messages.mo
No preview for this file type
components/k2adm/k2adm/languages/uk/LC_MESSAGES/messages.po
| 1 | -msgid "title_menu_items" | |
| 2 | -msgstr "Адміністрування сайту" | |
| 3 | - | |
| 4 | - | |
| 5 | -msgid "menu_items_child_1" | |
| 6 | -msgstr "Зміна паролю" | |
| 7 | - | |
| 8 | -msgid "menu_items_child_2" | |
| 9 | -msgstr "Новий користувач" | |
| 10 | - | |
| 11 | -msgid "menu_items_child_3" | |
| 12 | -msgstr "Користувачі" | |
| 13 | - | |
| 14 | - | |
| 15 | -msgid "menu_items_child_4" | |
| 16 | -msgstr "Користувачі кліенти" | |
| 17 | - | |
| 18 | - | |
| 19 | -msgid "menu_items_child_5" | |
| 20 | -msgstr "Ролі" | |
| 21 | - | |
| 22 | - | |
| 23 | -msgid "menu_items_child_6" | |
| 24 | -msgstr "Доступ до меню" |
components/k2adm/k2adm/models.py
| 1 | -import uuid | |
| 2 | -from sqlalchemy import Column, Integer, String | |
| 3 | -from sqlalchemy.ext.declarative import declarative_base | |
| 4 | -from flask_jwt_extended import create_access_token | |
| 5 | -from datetime import timedelta | |
| 6 | -import hashlib | |
| 7 | -from flask import current_app as k2 | |
| 8 | - | |
| 9 | -Base = declarative_base() | |
| 10 | - | |
| 11 | - | |
| 12 | -class k2users(Base): | |
| 13 | - __tablename__ = 'k2users' | |
| 14 | - user_id = Column(Integer, primary_key=True) | |
| 15 | - login = Column(String(70), nullable=False) | |
| 16 | - name = Column(String(50), nullable=False) | |
| 17 | - email = Column(String(150), nullable=False) | |
| 18 | - password = Column(String(150), nullable=False) | |
| 19 | - phone = Column(String(20)) | |
| 20 | - roleid = Column(String(150), nullable=False) | |
| 21 | - | |
| 22 | - def __init__(self, **kwargs): | |
| 23 | - self.user_id = hashlib.md5(str(uuid.uuid4()).encode()).hexdigest() | |
| 24 | - self.login = kwargs.get('login') | |
| 25 | - self.password = hashlib.md5(kwargs.get('password').encode()).hexdigest() | |
| 26 | - self.name = kwargs.get('name') | |
| 27 | - self.email = kwargs.get('email') | |
| 28 | - self.phone = kwargs.get('phone') | |
| 29 | - self.roleid = kwargs.get('roleid') | |
| 30 | - | |
| 31 | - def get_token(self, expire_time=24): | |
| 32 | - expires_delta = timedelta(expire_time) | |
| 33 | - token = create_access_token(identity=self.user_id, expires_delta=expires_delta) | |
| 34 | - | |
| 35 | - db = k2.extensions['sqlalchemy'].db | |
| 36 | - connection = db.engine.connect() | |
| 37 | - result = connection.execute( | |
| 38 | - db.text(f"SELECT rolename FROM k2roles where roleid = '{self.roleid}'")).fetchone() | |
| 39 | - rolename = result[0] if result else None | |
| 40 | - | |
| 41 | - userData = { | |
| 42 | - "avatar": "/src/assets/images/avatars/avatar-4.png", | |
| 43 | - "email": self.email, | |
| 44 | - "fullName": self.name, | |
| 45 | - "id": self.user_id, | |
| 46 | - "role": rolename, | |
| 47 | - "username": self.login | |
| 48 | - } | |
| 49 | - | |
| 50 | - userAbilities = [] | |
| 51 | - query = f""" | |
| 52 | - SELECT menus.namemenu, prava.r, prava.w, prava.i, prava.d, prava.c, | |
| 53 | - prava.exp, prava.imp, prava.settable, prava.cutpast, prava.enable, prava.del | |
| 54 | - FROM k2admin_menus menus | |
| 55 | - JOIN k2admin_menus_prava prava ON menus.menuid = prava.menuid | |
| 56 | - WHERE prava.roleid = {self.roleid} | |
| 57 | - """ | |
| 58 | - menus = connection.execute(db.text(query)).fetchall() | |
| 59 | - | |
| 60 | - for menu in menus: | |
| 61 | - abilities_dict = { | |
| 62 | - "subject": menu[0], | |
| 63 | - "read": menu[1], | |
| 64 | - "write": menu[2], | |
| 65 | - "insert": menu[3], | |
| 66 | - "delete": menu[4], | |
| 67 | - "copy": menu[5], | |
| 68 | - "export": menu[6], | |
| 69 | - "import": menu[7], | |
| 70 | - "settable": menu[8], | |
| 71 | - "cutpast": menu[9], | |
| 72 | - "enable": menu[10], | |
| 73 | - "del": menu[11], | |
| 74 | - } | |
| 75 | - | |
| 76 | - abilities_dict_copy = abilities_dict.copy() | |
| 77 | - for key, value in abilities_dict_copy.items(): | |
| 78 | - if value == 0: | |
| 79 | - del abilities_dict[key] | |
| 80 | - userAbilities.append(abilities_dict) | |
| 81 | - | |
| 82 | - return (token, userData, userAbilities) | |
| 83 | - | |
| 84 | - @classmethod | |
| 85 | - def authenticate(cls, login, password): | |
| 86 | - session = k2.extensions['sqlalchemy'].db.session | |
| 87 | - user = '' | |
| 88 | - try: | |
| 89 | - user = session.query(cls).filter(cls.login == login).filter(cls.password == hashlib.md5(password.encode()).hexdigest()).one() | |
| 90 | - except: | |
| 91 | - user = None | |
| 92 | - return user | |
| 93 | - | |
| 94 | - @classmethod | |
| 95 | - def user_by_login(cls, login): | |
| 96 | - session = k2.extensions['sqlalchemy'].db.session | |
| 97 | - user = session.query(cls).filter(cls.login == login).first() | |
| 98 | - return user |
components/k2adm/k2adm/views.py
| 1 | -import hashlib | |
| 2 | -import uuid | |
| 3 | -from flask import Blueprint, request, jsonify | |
| 4 | -from flask import current_app as k2 | |
| 5 | -from flask_jwt_extended import jwt_required, get_jwt_identity | |
| 6 | -from flask_babel import gettext | |
| 7 | - | |
| 8 | -from .models import k2users | |
| 9 | - | |
| 10 | - | |
| 11 | -k2adm = Blueprint('k2adm', __name__) | |
| 12 | - | |
| 13 | - | |
| 14 | -@k2adm.route('/usersclients', methods=["GET"]) | |
| 15 | -@jwt_required() | |
| 16 | -def users_clients(): | |
| 17 | - return jsonify({"data": "user roles"}) | |
| 18 | - | |
| 19 | - | |
| 20 | -@k2adm.route('/users', methods=["GET"]) | |
| 21 | -@jwt_required() | |
| 22 | -def grid_users(): | |
| 23 | - return jsonify({"data": "users"}) | |
| 24 | - | |
| 25 | - | |
| 26 | -@k2adm.route('/roles', methods=["GET"]) | |
| 27 | -@jwt_required() | |
| 28 | -def grid_roles(): | |
| 29 | - return jsonify({"data": "roles"}) | |
| 30 | - | |
| 31 | - | |
| 32 | - | |
| 33 | -@k2adm.route('/api_get_roles', methods=["GET"]) | |
| 34 | -@jwt_required() | |
| 35 | -def roles(): | |
| 36 | - db = k2.extensions['sqlalchemy'].db | |
| 37 | - connection = db.engine.connect() | |
| 38 | - query = db.text("SELECT roleid, rolename FROM k2roles") | |
| 39 | - result = connection.execute(query).fetchall() | |
| 40 | - roles = [dict(id=res.roleid, role=res.rolename) for res in result] | |
| 41 | - return {'data': roles} | |
| 42 | - | |
| 43 | - | |
| 44 | -@k2adm.route('/newUser', methods=["GET", "POST"]) | |
| 45 | -@jwt_required() | |
| 46 | -def newUser(): | |
| 47 | - session = k2.extensions['sqlalchemy'].db.session | |
| 48 | - exist = k2users.user_by_login(request.json['login']) | |
| 49 | - if not exist: | |
| 50 | - res = k2users( | |
| 51 | - user_id=hashlib.md5(str(uuid.uuid4()).encode()).hexdigest(), | |
| 52 | - login=request.json['login'], | |
| 53 | - name=request.json['name'], | |
| 54 | - email=request.json['email'], | |
| 55 | - password=request.json['password'], | |
| 56 | - phone=request.json['phone'], | |
| 57 | - roleid=request.json['role'] | |
| 58 | - ) | |
| 59 | - | |
| 60 | - if res: | |
| 61 | - session.add(res) | |
| 62 | - session.commit() | |
| 63 | - return jsonify({'status': '200', 'message': 'New user created'}) | |
| 64 | - else: | |
| 65 | - return jsonify({'status': '409', 'message': 'Such user exist'}), 409 | |
| 66 | - | |
| 67 | - | |
| 68 | - | |
| 69 | -@k2adm.route('/changePassword', methods=["POST"]) | |
| 70 | -@jwt_required() | |
| 71 | -def changePassword(): | |
| 72 | - session = k2.extensions['sqlalchemy'].db.session | |
| 73 | - current_user = get_jwt_identity() | |
| 74 | - | |
| 75 | - user = session.query(k2users).filter_by(user_id=current_user['user_id']).first() | |
| 76 | - if user.password == hashlib.md5(request.json['old_password'].encode()).hexdigest(): | |
| 77 | - if request.json['new_password'] == request.json['re_new_password']: | |
| 78 | - user.password = hashlib.md5(request.json['new_password'].encode()).hexdigest() | |
| 79 | - session.commit() | |
| 80 | - else: | |
| 81 | - return jsonify({'status': '400', 'message': 'Пароли не совпвдает'}), 400 | |
| 82 | - else: | |
| 83 | - jsonify({'status': '404', 'message': "Пароль не найден в базе"}), 404 | |
| 84 | - return jsonify({'status': 'ok'}) | |
| 85 | - | |
| 86 | - | |
| 87 | -@k2adm.route('/menu-admin-items') | |
| 88 | -def menu_items(): | |
| 89 | - data = [ | |
| 90 | - { | |
| 91 | - # "title": 'Site administration', | |
| 92 | - "title": f"{gettext('title_menu_items')}", | |
| 93 | - "icon": {"icon": 'mdi-account-circle-outline'}, | |
| 94 | - "children": [ | |
| 95 | - {'title': f"{gettext('menu_items_child_1')}", 'to': 'adm-changePassword'}, | |
| 96 | - {'title': f"{gettext('menu_items_child_2')}", 'to': 'adm-newUser'}, | |
| 97 | - {'title': f"{gettext('menu_items_child_3')}", 'to': 'adm-users'}, | |
| 98 | - {'title': f"{gettext('menu_items_child_4')}", 'to': 'adm-usersclients'}, | |
| 99 | - {'title': f"{gettext('menu_items_child_5')}", 'to': 'adm-roles'}, | |
| 100 | - {'title': f"{gettext('menu_items_child_6')}", 'to': 'adm-menuaaccess'}, | |
| 101 | - ], | |
| 102 | - }] | |
| 103 | - return data |
components/k2adm/requirements.txt
| 1 | -alembic==1.11.1 | |
| 2 | -Babel==2.12.1 | |
| 3 | -bcrypt==4.0.1 | |
| 4 | -bidict==0.22.1 | |
| 5 | -blinker==1.6.2 | |
| 6 | -certifi==2023.5.7 | |
| 7 | -charset-normalizer==3.1.0 | |
| 8 | -click==8.1.3 | |
| 9 | -colorama==0.4.6 | |
| 10 | -dnspython==2.3.0 | |
| 11 | -email-validator==2.0.0.post2 | |
| 12 | -Flask==2.3.2 | |
| 13 | -flask-babel==3.1.0 | |
| 14 | -Flask-Bcrypt==1.0.1 | |
| 15 | -Flask-Cors==3.0.10 | |
| 16 | -Flask-JWT-Extended==4.5.2 | |
| 17 | -Flask-Login==0.6.2 | |
| 18 | -Flask-Migrate==4.0.4 | |
| 19 | -Flask-MySQLdb==1.0.1 | |
| 20 | -Flask-SQLAlchemy==3.0.3 | |
| 21 | -flask-staticdirs==1.0.1 | |
| 22 | -Flask-WTF==1.1.1 | |
| 23 | -greenlet==2.0.2 | |
| 24 | -idna==3.4 | |
| 25 | -itsdangerous==2.1.2 | |
| 26 | -Jinja2==3.1.2 | |
| 27 | -jsonify==0.5 | |
| 28 | -Mako==1.2.4 | |
| 29 | -MarkupSafe==2.1.2 | |
| 30 | -mysql==0.0.3 | |
| 31 | -mysql-connector==2.2.9 | |
| 32 | -mysql-connector-python==8.0.33 | |
| 33 | -mysqlclient==2.1.1 | |
| 34 | -peppercorn==0.6 | |
| 35 | -protobuf==3.20.3 | |
| 36 | -PyJWT==2.7.0 | |
| 37 | -python-engineio==4.4.1 | |
| 38 | -python-socketio==5.8.0 | |
| 39 | -pytz==2023.3 | |
| 40 | -PyYAML==6.0 | |
| 41 | -requests==2.31.0 | |
| 42 | -six==1.16.0 | |
| 43 | -SQLAlchemy==2.0.15 | |
| 44 | -typing_extensions==4.6.2 | |
| 45 | -urllib3==2.0.2 | |
| 46 | -Werkzeug==2.3.4 | |
| 47 | -WTForms==3.0.1 |
components/k2adm/setup.py
| 1 | -from setuptools import setup | |
| 2 | - | |
| 3 | -setup( | |
| 4 | - name='k2adm', | |
| 5 | - version='1.0.1', | |
| 6 | - description='Description of my project', | |
| 7 | - author='k2 cloud', | |
| 8 | - author_email='ys@corp2.eu', | |
| 9 | - keywords="adm, k2", | |
| 10 | - python_requires=">=3.7, <=3.11.2", | |
| 11 | - packages=['adm'], | |
| 12 | - package_data={ # Optional | |
| 13 | - }, | |
| 14 | - install_requires=[""], | |
| 15 | -) |
components/k2auth/.gitignore
components/k2auth/README.md
| 1 | -# main.py | |
| 2 | - | |
| 3 | -from components.adm.adm.views import adm | |
| 4 | -from components.test.test.views import test | |
| 5 | - | |
| 6 | -app.register_blueprint(adm, url_prefix='/adm') | |
| 7 | - | |
| 8 | -cd components/adm | |
| 9 | -pip install -r requirements.txt | |
| 10 | - | |
| 11 | - | |
| 12 | -endpoint "http://127.0.0.1:5000/adm/register" | |
| 13 | -dictionary to register in such way | |
| 14 | -{ | |
| 15 | - "login": "xxx", | |
| 16 | - "password": "xxx", | |
| 17 | - "name": "xxx", | |
| 18 | - "email": "xxx" | |
| 19 | -} | |
| 20 | - | |
| 21 | - | |
| 22 | -endpoint "http://127.0.0.1:5000/adm/login" | |
| 23 | -dictionary to login in such way | |
| 24 | -{ | |
| 25 | - "login":"xxx", | |
| 26 | - "password":"xxx" | |
| 27 | -} | |
| 28 | - | |
| 29 | -endpoint http://127.0.0.1:5000/adm/changePassword | |
| 30 | -dictionary to changePassword in such way | |
| 31 | -{ | |
| 32 | - "old_password":"xxx", | |
| 33 | - "new_password": "xxx", | |
| 34 | - "re_new_password": "xxx" | |
| 35 | -} | |
| 36 | -endpoint http://127.0.0.1:5000/adm/newUser | |
| 37 | -{ | |
| 38 | - "login": "xxx", | |
| 39 | - "password": "xxx", | |
| 40 | - "name": "xxx", | |
| 41 | - "email": "xxx", | |
| 42 | - "phone": "xxx", | |
| 43 | - "repassword": "xxx" | |
| 44 | - | |
| 45 | -} |
components/k2auth/k2auth/models.py
| 1 | - | |
| 2 | -import uuid | |
| 3 | -from sqlalchemy import Column, Integer, String | |
| 4 | -from sqlalchemy.ext.declarative import declarative_base | |
| 5 | -from flask_jwt_extended import create_access_token | |
| 6 | -from datetime import timedelta | |
| 7 | -import hashlib | |
| 8 | -from flask import current_app as k2 | |
| 9 | - | |
| 10 | -Base = declarative_base() | |
| 11 | - | |
| 12 | - | |
| 13 | -class k2users(Base): | |
| 14 | - __tablename__ = 'k2users' | |
| 15 | - user_id = Column(Integer, primary_key=True) | |
| 16 | - login = Column(String(70), nullable=False) | |
| 17 | - name = Column(String(50), nullable=False) | |
| 18 | - email = Column(String(150), nullable=False) | |
| 19 | - password = Column(String(150), nullable=False) | |
| 20 | - phone = Column(String(20)) | |
| 21 | - roleid = Column(String(150), nullable=False) | |
| 22 | - | |
| 23 | - def __init__(self, **kwargs): | |
| 24 | - self.user_id = hashlib.md5(str(uuid.uuid4()).encode()).hexdigest() | |
| 25 | - self.login = kwargs.get('login') | |
| 26 | - self.password = hashlib.md5(kwargs.get('password').encode()).hexdigest() | |
| 27 | - self.name = kwargs.get('name') | |
| 28 | - self.email = kwargs.get('email') | |
| 29 | - self.phone = kwargs.get('phone') | |
| 30 | - self.roleid = kwargs.get('roleid') | |
| 31 | - | |
| 32 | - def get_token(self, expire_time=24): | |
| 33 | - expires_delta = timedelta(expire_time) | |
| 34 | - # token = create_access_token(identity=self.user_id, expires_delta=expires_delta) | |
| 35 | - token = create_access_token(identity={ | |
| 36 | - 'user_id': self.user_id, | |
| 37 | - 'user_role': self.roleid | |
| 38 | - }, expires_delta=expires_delta) | |
| 39 | - | |
| 40 | - db = k2.extensions['sqlalchemy'].db | |
| 41 | - connection = db.engine.connect() | |
| 42 | - result = connection.execute( | |
| 43 | - db.text(f"SELECT rolename FROM k2roles where roleid = '{self.roleid}'")).fetchone() | |
| 44 | - | |
| 45 | - rolename = result[0] if result else None | |
| 46 | - | |
| 47 | - userData = { | |
| 48 | - "avatar": "/src/assets/images/avatars/avatar-4.png", | |
| 49 | - "email": self.email, | |
| 50 | - "fullName": self.name, | |
| 51 | - "id": self.user_id, | |
| 52 | - "role": rolename, | |
| 53 | - "username": self.login | |
| 54 | - } | |
| 55 | - | |
| 56 | - userAbilities = [] | |
| 57 | - from k2.k2comp import Component | |
| 58 | - components = Component.query.filter(Component.installed == 1).all() | |
| 59 | - components_names = [component.name for component in components] | |
| 60 | - | |
| 61 | - | |
| 62 | - | |
| 63 | - abilities_query = f""" | |
| 64 | - SELECT menus.namemenu, | |
| 65 | - prava.r, prava.w, prava.i, prava.d, prava.c, prava.exp, prava.imp, prava.settable, prava.cutpast, | |
| 66 | - prava.enable, prava.del | |
| 67 | - FROM k2admin_menus menus | |
| 68 | - JOIN k2admin_menus_prava prava ON menus.menuid = prava.menuid | |
| 69 | - WHERE prava.roleid = {self.roleid} AND menus.namemenu IN {tuple(components_names)} | |
| 70 | - """ | |
| 71 | - abilities_list = connection.execute(db.text(abilities_query)).fetchall() | |
| 72 | - | |
| 73 | - for ability in abilities_list: | |
| 74 | - abilities_dict = { | |
| 75 | - "subject": ability[0], | |
| 76 | - "read": ability[1], | |
| 77 | - "write": ability[2], | |
| 78 | - "insert": ability[3], | |
| 79 | - "delete": ability[4], | |
| 80 | - "copy": ability[5], | |
| 81 | - "export": ability[6], | |
| 82 | - "import": ability[7], | |
| 83 | - "settable": ability[8], | |
| 84 | - "cutpast": ability[9], | |
| 85 | - "enable": ability[10], | |
| 86 | - "del": ability[11] | |
| 87 | - } | |
| 88 | - | |
| 89 | - abilities_dict_copy = abilities_dict.copy() | |
| 90 | - for key, value in abilities_dict_copy.items(): | |
| 91 | - if value == 0: | |
| 92 | - del abilities_dict[key] | |
| 93 | - userAbilities.append(abilities_dict) | |
| 94 | - | |
| 95 | - return (token, userData, userAbilities) | |
| 96 | - | |
| 97 | - | |
| 98 | - @classmethod | |
| 99 | - def authenticate(cls, login, password): | |
| 100 | - session = k2.extensions['sqlalchemy'].db.session | |
| 101 | - user = '' | |
| 102 | - try: | |
| 103 | - user = session.query(cls).filter(cls.login == login).filter(cls.password == hashlib.md5(password.encode()).hexdigest()).one() | |
| 104 | - except: | |
| 105 | - user = None | |
| 106 | - return user | |
| 107 | - | |
| 108 | - @classmethod | |
| 109 | - def user_by_login(cls, login): | |
| 110 | - session = k2.extensions['sqlalchemy'].db.session | |
| 111 | - user = session.query(cls).filter(cls.login == login).first() | |
| 112 | - return user |
components/k2auth/k2auth/views.py
| 1 | -# import hashlib | |
| 2 | -# import uuid | |
| 3 | -from flask import Blueprint, request, jsonify | |
| 4 | -from flask import current_app as k2 | |
| 5 | -from flask_jwt_extended import jwt_required | |
| 6 | -import re | |
| 7 | -from .models import k2users | |
| 8 | - | |
| 9 | -k2auth = Blueprint('k2auth', __name__, template_folder='templates', static_folder='static', static_url_path='/vue2') | |
| 10 | - | |
| 11 | - | |
| 12 | -class Auth(): | |
| 13 | - def __init__(self): | |
| 14 | - pass | |
| 15 | - | |
| 16 | - def register(self): | |
| 17 | - params = request.json | |
| 18 | - session = k2.extensions['sqlalchemy'].db.session | |
| 19 | - password = params.get('password') | |
| 20 | - login = params.get('login') | |
| 21 | - user_exist = k2users.user_by_login(login) | |
| 22 | - if user_exist: | |
| 23 | - return jsonify({'status': '409', 'message': 'Such user exist'}), 409 | |
| 24 | - | |
| 25 | - if len(password) < 6: | |
| 26 | - return jsonify({'status': '400', 'message': 'password has not 6 simbols'}), 400 | |
| 27 | - if re.search(r'[a-zA-Z]', password) is None or re.search(r'\d', password) is None: | |
| 28 | - return jsonify({'status': '400', 'message': 'Password must contain both letters and numbers'}), 400 | |
| 29 | - | |
| 30 | - try: | |
| 31 | - user = k2users(**params) | |
| 32 | - session.add(user) | |
| 33 | - session.commit() | |
| 34 | - token, userData, userAbilities = user.get_token() | |
| 35 | - print(userAbilities) | |
| 36 | - | |
| 37 | - return {'accessToken': token, "userData": userData, "userAbilities": userAbilities} | |
| 38 | - except: | |
| 39 | - return jsonify({'status': '400', 'message': "Missing required fields"}), 400 | |
| 40 | - | |
| 41 | - | |
| 42 | - | |
| 43 | - def login(self): | |
| 44 | - params = request.json | |
| 45 | - user = k2users.authenticate(**params) | |
| 46 | - if user: | |
| 47 | - token, userData, userAbilities = user.get_token() | |
| 48 | - return {'accessToken': token, "userData": userData, "userAbilities": userAbilities} | |
| 49 | - else: | |
| 50 | - # k2.logger.error(('%s failed to log in ', params.get('login'), params.get('password'))) | |
| 51 | - return jsonify({'status': '401', 'message': 'Unauthorized'}), 401 | |
| 52 | - | |
| 53 | - | |
| 54 | - @jwt_required() | |
| 55 | - def logout(self): | |
| 56 | - response = { | |
| 57 | - 'message': 'Logged out successfully' | |
| 58 | - } | |
| 59 | - return jsonify(response) | |
| 60 | - | |
| 61 | - | |
| 62 | - | |
| 63 | -auth = Auth() | |
| 64 | -k2auth.add_url_rule('/login', methods=['POST'], view_func=auth.login) | |
| 65 | -k2auth.add_url_rule('/logout', methods=['GET'], view_func=auth.logout) | |
| 66 | -k2auth.add_url_rule('/register', methods=['POST'], view_func=auth.register) |
components/k2auth/requirements.txt
| 1 | -alembic==1.11.1 | |
| 2 | -Babel==2.12.1 | |
| 3 | -bcrypt==4.0.1 | |
| 4 | -bidict==0.22.1 | |
| 5 | -blinker==1.6.2 | |
| 6 | -certifi==2023.5.7 | |
| 7 | -charset-normalizer==3.1.0 | |
| 8 | -click==8.1.3 | |
| 9 | -colorama==0.4.6 | |
| 10 | -dnspython==2.3.0 | |
| 11 | -email-validator==2.0.0.post2 | |
| 12 | -Flask==2.3.2 | |
| 13 | -flask-babel==3.1.0 | |
| 14 | -Flask-Bcrypt==1.0.1 | |
| 15 | -Flask-Cors==3.0.10 | |
| 16 | -Flask-JWT-Extended==4.5.2 | |
| 17 | -Flask-Login==0.6.2 | |
| 18 | -Flask-Migrate==4.0.4 | |
| 19 | -Flask-MySQLdb==1.0.1 | |
| 20 | -Flask-SQLAlchemy==3.0.3 | |
| 21 | -flask-staticdirs==1.0.1 | |
| 22 | -Flask-WTF==1.1.1 | |
| 23 | -greenlet==2.0.2 | |
| 24 | -idna==3.4 | |
| 25 | -itsdangerous==2.1.2 | |
| 26 | -Jinja2==3.1.2 | |
| 27 | -jsonify==0.5 | |
| 28 | -Mako==1.2.4 | |
| 29 | -MarkupSafe==2.1.2 | |
| 30 | -mysql==0.0.3 | |
| 31 | -mysql-connector==2.2.9 | |
| 32 | -mysql-connector-python==8.0.33 | |
| 33 | -mysqlclient==2.1.1 | |
| 34 | -peppercorn==0.6 | |
| 35 | -protobuf==3.20.3 | |
| 36 | -PyJWT==2.7.0 | |
| 37 | -python-engineio==4.4.1 | |
| 38 | -python-socketio==5.8.0 | |
| 39 | -pytz==2023.3 | |
| 40 | -PyYAML==6.0 | |
| 41 | -requests==2.31.0 | |
| 42 | -six==1.16.0 | |
| 43 | -SQLAlchemy==2.0.15 | |
| 44 | -typing_extensions==4.6.2 | |
| 45 | -urllib3==2.0.2 | |
| 46 | -Werkzeug==2.3.4 | |
| 47 | -WTForms==3.0.1 |
components/k2auth/setup.py
| 1 | -from setuptools import setup | |
| 2 | - | |
| 3 | -setup( | |
| 4 | - name='k2auth', | |
| 5 | - version='1.0.1', | |
| 6 | - description='Description of my project', | |
| 7 | - author='k2 cloud', | |
| 8 | - author_email='ys@corp2.eu', | |
| 9 | - keywords="k2auth, k2", | |
| 10 | - python_requires=">=3.7, <=3.11.2", | |
| 11 | - packages=['k2auth'], | |
| 12 | - package_data={ # Optional | |
| 13 | - }, | |
| 14 | - install_requires=[""], | |
| 15 | -) |
components/k2test/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/k2test/k2test/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/k2test/k2test/__pycache__/views.cpython-310.pyc
No preview for this file type
db/database.db
No preview for this file type
k2/__pycache__/__init__.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2admmenu.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2cfg.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2comp.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2obj.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2rout.cpython-310.pyc
No preview for this file type
k2/k2cfg.py
| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | version = '2.5.1.27' |
| 16 | 16 | db = SQLAlchemy() |
| 17 | 17 | domain = 'http://127.0.0.1:5000/' |
| 18 | - update_domain ='http://127.0.0.1:8002/' | |
| 18 | + update_domain ='http://185.174.172.137/' | |
| 19 | 19 | venv_bin_path = os.path.join(os.path.dirname(sys.prefix), 'venv/Scripts') |
| 20 | 20 | json_sort_keys = False |
| 21 | 21 | timezone = pytz.timezone('Europe/Kiev') |
| ... | ... | @@ -34,6 +34,7 @@ |
| 34 | 34 | def load_babel_translation_directories(cls): |
| 35 | 35 | with open('languages/babel_translation_directories.yml', 'r') as f: |
| 36 | 36 | data = yaml.safe_load(f) |
| 37 | + print(data['babel_translation_directories']) | |
| 37 | 38 | cls.babel_translation_directories = data['babel_translation_directories'] |
| 38 | 39 | |
| 39 | 40 | @classmethod |
k2/k2rout.py
| ... | ... | @@ -78,12 +78,17 @@ |
| 78 | 78 | return result |
| 79 | 79 | |
| 80 | 80 | |
| 81 | -@components_bp.route('/home', methods=['GET', 'POST']) | |
| 82 | -@first_login_required | |
| 81 | +@components_bp.route('/', methods=['GET', 'POST']) | |
| 83 | 82 | def home(): |
| 84 | - return redirect('/dashboard') | |
| 83 | + components = Component.query.all() | |
| 84 | + components_names = [component.name for component in components] | |
| 85 | + if 'k2site' in components_names: | |
| 86 | + return redirect(url_for('k2test.new_component2')) #змінити на ендпоінт головної k2site | |
| 87 | + else: | |
| 88 | + return redirect('/dashboard') | |
| 85 | 89 | |
| 86 | 90 | |
| 91 | + | |
| 87 | 92 | @components_bp.route('/first-login', methods=['GET', 'POST']) |
| 88 | 93 | def first_login(): |
| 89 | 94 | if request.method == "POST": |
| 90 | 95 | |
| 91 | 96 | |
| 92 | 97 | |
| 93 | 98 | |
| 94 | 99 | |
| 95 | 100 | |
| 96 | 101 | |
| ... | ... | @@ -101,43 +106,47 @@ |
| 101 | 106 | def change_language(lang): |
| 102 | 107 | session['lang'] = lang |
| 103 | 108 | k2.current_language = lang |
| 104 | - return redirect(url_for('components.dashboard')) | |
| 109 | + return redirect(request.referrer) | |
| 105 | 110 | |
| 106 | 111 | |
| 107 | 112 | @components_bp.route('/dashboard') |
| 108 | -@first_login_required | |
| 109 | 113 | def dashboard(): |
| 110 | - # Компоненти доступні для встановлення | |
| 111 | - # GET-запит до API | |
| 112 | - try: | |
| 113 | - response = requests.get(f'{k2.update_domain}api/components') | |
| 114 | - json_data = response.json() | |
| 115 | - # Перетворення JSON-об'єкту на масив | |
| 116 | - component_server = [item for item in json_data] | |
| 117 | - except: | |
| 118 | - component_server = None | |
| 119 | - | |
| 120 | - # Встановлені компоненти | |
| 121 | 114 | components = Component.query.all() |
| 122 | 115 | components_names = [component.name for component in components] |
| 123 | - # Отримання значення пошукового запиту з параметрів URL | |
| 124 | - search_query = request.args.get('search_query') | |
| 125 | - # print(search_query) | |
| 126 | - filtered_components = [] | |
| 127 | - if search_query: | |
| 128 | - filtered_components = [component for component in component_server if | |
| 129 | - (search_query.lower() in component['name'].lower() if component['name'] else False) or | |
| 130 | - (search_query.lower() in component['description'].lower() if component[ | |
| 131 | - 'description'] else False)] | |
| 116 | + if 'k2site' in components_names: | |
| 117 | + return redirect(url_for('components_bp.component_list_dasb')) # змінити на ендпоінт головної k2site | |
| 132 | 118 | else: |
| 133 | - filtered_components = component_server | |
| 134 | - current_language = k2.current_language | |
| 119 | + # Компоненти доступні для встановлення | |
| 120 | + # GET-запит до API | |
| 121 | + try: | |
| 122 | + response = requests.get(f'{k2.update_domain}api/components') | |
| 123 | + json_data = response.json() | |
| 124 | + # Перетворення JSON-об'єкту на масив | |
| 125 | + component_server = [item for item in json_data] | |
| 126 | + except: | |
| 127 | + component_server = None | |
| 135 | 128 | |
| 136 | - return render_template('dashboard.html', components=components, | |
| 137 | - components_names=components_names, component_server=filtered_components, | |
| 138 | - search_query=search_query, language=k2.menu) | |
| 129 | + # Встановлені компоненти | |
| 130 | + components = Component.query.all() | |
| 131 | + components_names = [component.name for component in components] | |
| 132 | + # Отримання значення пошукового запиту з параметрів URL | |
| 133 | + search_query = request.args.get('search_query') | |
| 134 | + # print(search_query) | |
| 135 | + filtered_components = [] | |
| 136 | + if search_query: | |
| 137 | + filtered_components = [component for component in component_server if | |
| 138 | + (search_query.lower() in component['name'].lower() if component['name'] else False) or | |
| 139 | + (search_query.lower() in component['description'].lower() if component[ | |
| 140 | + 'description'] else False)] | |
| 141 | + else: | |
| 142 | + filtered_components = component_server | |
| 143 | + current_language = k2.current_language | |
| 139 | 144 | |
| 145 | + return render_template('dashboard.html', components=components, | |
| 146 | + components_names=components_names, component_server=filtered_components, | |
| 147 | + search_query=search_query, language=current_language) | |
| 140 | 148 | |
| 149 | + | |
| 141 | 150 | @components_bp.route('/show_components/<string:component_id>') |
| 142 | 151 | def show_components(component_id): |
| 143 | 152 | response = requests.get(f'{k2.update_domain}api/components') |
| ... | ... | @@ -287,7 +296,6 @@ |
| 287 | 296 | db.session.commit() |
| 288 | 297 | |
| 289 | 298 | # add language folders |
| 290 | - | |
| 291 | 299 | k2.search_babel_translation_directories() |
| 292 | 300 | return f'''Component installed successfully: {selected_component["name"]} v{version} {k2.babel_translation_directories}, |
| 293 | 301 | \n \n please wait installing requirments... |
| 294 | 302 | |
| 295 | 303 | |
| ... | ... | @@ -404,39 +412,39 @@ |
| 404 | 412 | return 'Error removing component: ' + str(e) |
| 405 | 413 | |
| 406 | 414 | |
| 407 | -@components_bp.route('/component/add') | |
| 408 | -def component_add(): | |
| 409 | - # components for install | |
| 410 | - try: | |
| 411 | - # GET-requests to API | |
| 412 | - response = requests.get(f'{k2.update_domain}api/components') | |
| 413 | - json_data = response.json() | |
| 414 | - for item in json_data: | |
| 415 | - item['button'] = f"{k2.domain}/install_components/{item['id']}" | |
| 415 | +# @components_bp.route('/component/add') | |
| 416 | +# def component_add(): | |
| 417 | +# # components for install | |
| 418 | +# try: | |
| 419 | +# # GET-requests to API | |
| 420 | +# response = requests.get(f'{k2.update_domain}api/components') | |
| 421 | +# json_data = response.json() | |
| 422 | +# for item in json_data: | |
| 423 | +# item['button'] = f"{k2.domain}/install_components/{item['id']}" | |
| 424 | +# | |
| 425 | +# except: | |
| 426 | +# json_data = None | |
| 427 | +# return jsonify(json_data) | |
| 428 | +# | |
| 429 | +# | |
| 430 | +# @components_bp.route('/component/list') | |
| 431 | +# def component_list(): | |
| 432 | +# # Встановлені компоненти | |
| 433 | +# component_list = [] | |
| 434 | +# components = Component.query.all() | |
| 435 | +# for component in components: | |
| 436 | +# component_dict = {} | |
| 437 | +# component_dict['name'] = component.name | |
| 438 | +# component_dict['id'] = component.id | |
| 439 | +# component_dict['description'] = component.description | |
| 440 | +# component_dict['version'] = component.version | |
| 441 | +# component_dict['button_off'] =f"{k2.domain}/remove_dependencies/{component.id}" | |
| 442 | +# component_dict['button_on'] = f"{k2.domain}/add_dependencies/{component.id}" | |
| 443 | +# component_dict['button_del'] = f"{k2.domain}/remove-component/{component.id}" | |
| 444 | +# component_list.append(component_dict) | |
| 445 | +# return jsonify(component_list) | |
| 416 | 446 | |
| 417 | - except: | |
| 418 | - json_data = None | |
| 419 | - return jsonify(json_data) | |
| 420 | 447 | |
| 421 | - | |
| 422 | -@components_bp.route('/component/list') | |
| 423 | -def component_list(): | |
| 424 | - # Встановлені компоненти | |
| 425 | - component_list = [] | |
| 426 | - components = Component.query.all() | |
| 427 | - for component in components: | |
| 428 | - component_dict = {} | |
| 429 | - component_dict['name'] = component.name | |
| 430 | - component_dict['id'] = component.id | |
| 431 | - component_dict['description'] = component.description | |
| 432 | - component_dict['version'] = component.version | |
| 433 | - component_dict['button_off'] =f"{k2.domain}/remove_dependencies/{component.id}" | |
| 434 | - component_dict['button_on'] = f"{k2.domain}/add_dependencies/{component.id}" | |
| 435 | - component_dict['button_del'] = f"{k2.domain}/remove-component/{component.id}" | |
| 436 | - component_list.append(component_dict) | |
| 437 | - return jsonify(component_list) | |
| 438 | - | |
| 439 | - | |
| 440 | 448 | # menu |
| 441 | 449 | @components_bp.route('/api/add-to-menu', methods=['GET']) |
| 442 | 450 | def add_to_menu(): |
| ... | ... | @@ -445,7 +453,7 @@ |
| 445 | 453 | data.append(response.json()[0]) |
| 446 | 454 | prev_menu = response.json()[0]['title'] |
| 447 | 455 | for item in response.json()[0]['children']: |
| 448 | - name_menu = item['to'] | |
| 456 | + name_menu = str(item['to']).replace('/','-') | |
| 449 | 457 | caption_menu = item['title'] |
| 450 | 458 | add_menu_with_permissions_db(name_menu, prev_menu, caption_menu) |
| 451 | 459 | components = Component.query.all() |
| ... | ... | @@ -505,7 +513,6 @@ |
| 505 | 513 | caption=caption_menu, |
| 506 | 514 | module_name=name_menu |
| 507 | 515 | ) |
| 508 | - # Додавання об'єкта k2admin_menus до сесії | |
| 509 | 516 | db.session.add(new_menu_element) |
| 510 | 517 | db.session.commit() |
| 511 | 518 | # Створення об'єкта k2admin_menus_prava |
| 512 | 519 | |
| 513 | 520 | |
| ... | ... | @@ -528,11 +535,42 @@ |
| 528 | 535 | db.session.add(new_prava) |
| 529 | 536 | db.session.commit() |
| 530 | 537 | |
| 538 | +@components_bp.route('/component-add') | |
| 539 | +def component_add_dasb(): | |
| 540 | + try: | |
| 541 | + response = requests.get(f'{k2.update_domain}api/components') | |
| 542 | + json_data = response.json() | |
| 543 | + # Перетворення JSON-об'єкту на масив | |
| 544 | + component_server = [item for item in json_data] | |
| 545 | + except: | |
| 546 | + component_server = None | |
| 547 | + # Отримання значення пошукового запиту з параметрів URL | |
| 548 | + search_query = request.args.get('search_query') | |
| 549 | + # print(search_query) | |
| 550 | + filtered_components = [] | |
| 551 | + if search_query: | |
| 552 | + filtered_components = [component for component in component_server if | |
| 553 | + (search_query.lower() in component['name'].lower() if component[ | |
| 554 | + 'name'] else False) or | |
| 555 | + (search_query.lower() in component['description'].lower() if component[ | |
| 556 | + 'description'] else False)] | |
| 557 | + else: | |
| 558 | + filtered_components = component_server | |
| 531 | 559 | |
| 560 | + return render_template('dashboard-add.html', | |
| 561 | + component_server=filtered_components, | |
| 562 | + ) | |
| 563 | + | |
| 564 | +@components_bp.route('/component-list') | |
| 565 | +def component_list_dasb(): | |
| 566 | + components = Component.query.all() | |
| 567 | + return render_template('dashboard-list.html', components=components) | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 532 | 571 | @components_bp.route('/menu-admin-items') |
| 533 | 572 | def menu_items(): |
| 534 | 573 | menu = [ |
| 535 | - | |
| 536 | 574 | { |
| 537 | 575 | "title": 'Add components', |
| 538 | 576 | "icon": {"icon": 'mdi-account-circle-outline'}, |
languages/en/LC_MESSAGES/messages.mo
No preview for this file type
languages/en/LC_MESSAGES/messages.po
| 1 | -msgid "Installed components" | |
| 1 | +msgid "t_installed_components" | |
| 2 | 2 | msgstr "Installed components" |
| 3 | 3 | |
| 4 | -msgid "Name" | |
| 4 | +msgid "t_name" | |
| 5 | 5 | msgstr "Name" |
| 6 | 6 | |
| 7 | -msgid "Description" | |
| 7 | +msgid "t_description" | |
| 8 | 8 | msgstr "Description" |
| 9 | 9 | |
| 10 | -msgid "Version" | |
| 10 | +msgid "t_version" | |
| 11 | 11 | msgstr "Version" |
| 12 | 12 | |
| 13 | -msgid "Dependencies" | |
| 13 | +msgid "t_dependencies" | |
| 14 | 14 | msgstr "Dependencies" |
| 15 | 15 | |
| 16 | -msgid "Git Link" | |
| 16 | +msgid "t_git_link" | |
| 17 | 17 | msgstr "Git Link" |
| 18 | 18 | |
| 19 | -msgid "Install At" | |
| 19 | +msgid "t_install_at" | |
| 20 | 20 | msgstr "Install At" |
| 21 | 21 | |
| 22 | -msgid "Status" | |
| 22 | +msgid "t_status" | |
| 23 | 23 | msgstr "Status" |
| 24 | 24 | |
| 25 | -msgid "Action" | |
| 25 | +msgid "t_action" | |
| 26 | 26 | msgstr "Action" |
| 27 | 27 | |
| 28 | -msgid "Components Shop" | |
| 29 | -msgstr "Components Shop" | |
| 28 | +msgid "t_components_shop" | |
| 29 | +msgstr "Add component" |
languages/pl/LC_MESSAGES/messages.mo
No preview for this file type
languages/pl/LC_MESSAGES/messages.po
| 1 | +msgid "" | |
| 2 | +msgstr "" | |
| 3 | +"Content-Type: text/plain; charset=UTF-8\n" | |
| 4 | +"Content-Transfer-Encoding: 8bit\n" | |
| 5 | + | |
| 6 | +msgid "t_installed_components" | |
| 7 | +msgstr "Zainstalowane komponenty" | |
| 8 | + | |
| 9 | +msgid "t_name" | |
| 10 | +msgstr "Nazwa" | |
| 11 | + | |
| 12 | +msgid "t_description" | |
| 13 | +msgstr "Opis" | |
| 14 | + | |
| 15 | +msgid "t_version" | |
| 16 | +msgstr "Wersja" | |
| 17 | + | |
| 18 | +msgid "t_dependencies" | |
| 19 | +msgstr "Zależności" | |
| 20 | + | |
| 21 | +msgid "t_git_link" | |
| 22 | +msgstr "Link do Git" | |
| 23 | + | |
| 24 | +msgid "t_install_at" | |
| 25 | +msgstr "Zainstalowano" | |
| 26 | + | |
| 27 | +msgid "t_status" | |
| 28 | +msgstr "Status" | |
| 29 | + | |
| 30 | +msgid "t_action" | |
| 31 | +msgstr "Akcja" | |
| 32 | + | |
| 33 | +msgid "t_components_shop" | |
| 34 | +msgstr "Dodaj komponent" |
languages/uk/LC_MESSAGES/messages.mo
No preview for this file type
languages/uk/LC_MESSAGES/messages.po
| 1 | -msgid "Installed components" | |
| 2 | -msgstr "Встановлені компоненти" | |
| 1 | +msgid "" | |
| 2 | +msgstr "" | |
| 3 | +"Content-Type: text/plain; charset=UTF-8\n" | |
| 4 | +"Content-Transfer-Encoding: 8bit\n" | |
| 3 | 5 | |
| 4 | -msgid "Installed components" | |
| 6 | +msgid "t_installed_components" | |
| 5 | 7 | msgstr "Встановлені компоненти" |
| 6 | 8 | |
| 7 | -msgid "Name" | |
| 9 | +msgid "t_name" | |
| 8 | 10 | msgstr "Назва" |
| 9 | 11 | |
| 10 | -msgid "Description" | |
| 12 | +msgid "t_description" | |
| 11 | 13 | msgstr "Опис" |
| 12 | 14 | |
| 13 | -msgid "Version" | |
| 15 | +msgid "t_version" | |
| 14 | 16 | msgstr "Версія" |
| 15 | 17 | |
| 16 | -msgid "Dependencies" | |
| 18 | +msgid "t_dependencies" | |
| 17 | 19 | msgstr "Залежності" |
| 18 | 20 | |
| 19 | -msgid "Git Link" | |
| 21 | +msgid "t_git_link" | |
| 20 | 22 | msgstr "Посилання на Git" |
| 21 | 23 | |
| 22 | -msgid "Install At" | |
| 24 | +msgid "t_install_at" | |
| 23 | 25 | msgstr "Встановлено" |
| 24 | 26 | |
| 25 | -msgid "Status" | |
| 27 | +msgid "t_status" | |
| 26 | 28 | msgstr "Статус" |
| 27 | 29 | |
| 28 | -msgid "Action" | |
| 30 | +msgid "t_action" | |
| 29 | 31 | msgstr "Дія" |
| 30 | 32 | |
| 31 | -msgid "Components Shop" | |
| 32 | -msgstr "Магазин компонент" | |
| 33 | +msgid "t_components_shop" | |
| 34 | +msgstr "Додати компоненту" |
main.py
| 1 | 1 | from flask_cors import CORS |
| 2 | 2 | from flask_babel import Babel |
| 3 | 3 | from flask_jwt_extended import JWTManager |
| 4 | -#from k2.k2inst import * | |
| 4 | +#from k2.k2rout import * | |
| 5 | 5 | from flask import Flask |
| 6 | 6 | from k2.k2cfg import k2 |
| 7 | 7 | |
| 8 | + | |
| 9 | + | |
| 8 | 10 | # configure flask app |
| 9 | 11 | app = Flask(__name__) |
| 10 | 12 | app.config['SECRET_KEY'] = k2.secret_key |
| 11 | 13 | app.json.sort_keys = k2.json_sort_keys |
| 12 | 14 | #app.config.from_object(k2) |
| 13 | 15 | |
| 16 | + | |
| 14 | 17 | # init db |
| 15 | 18 | k2().init_db(app) |
| 16 | 19 | CORS(app) |
| ... | ... | @@ -19,6 +22,13 @@ |
| 19 | 22 | #translate |
| 20 | 23 | k2.load_babel_translation_directories() |
| 21 | 24 | app.config['BABEL_TRANSLATION_DIRECTORIES'] = k2.babel_translation_directories |
| 25 | +app.config['BABEL_DEFAULT_LOCALE'] = k2.default_language | |
| 26 | +app.config['BABEL_LANGUAGES'] = { | |
| 27 | + 'en': 'English', | |
| 28 | + 'uk': 'Українська', | |
| 29 | + 'pl': 'Polski' | |
| 30 | +} | |
| 31 | +app.config['BABEL_DEFAULT_TIMEZONE'] = k2.timezone | |
| 22 | 32 | babel = Babel(app) |
| 23 | 33 | babel.init_app(app, locale_selector=k2.get_locale) |
| 24 | 34 |
routes.py
| ... | ... | @@ -4,10 +4,4 @@ |
| 4 | 4 | app.register_blueprint(components_bp) |
| 5 | 5 | from components.k2test.k2test.views import k2test |
| 6 | 6 | app.register_blueprint(k2test, url_prefix='/k2test') |
| 7 | - | |
| 8 | -from components.k2auth.k2auth.views import k2auth | |
| 9 | -app.register_blueprint(k2auth, url_prefix='/k2auth') | |
| 10 | - | |
| 11 | -from components.k2adm.k2adm.views import k2adm | |
| 12 | -app.register_blueprint(k2adm, url_prefix='/k2adm') |
templates/base.html
templates/component-info.html
templates/dashboard-add.html
| 1 | +{% extends 'base.html' %} | |
| 2 | + | |
| 3 | + | |
| 4 | +{% block styles %} | |
| 5 | +<style> | |
| 6 | + .table { | |
| 7 | + border-collapse: collapse; | |
| 8 | + width: 100%; | |
| 9 | + } | |
| 10 | + | |
| 11 | + .table th, .table td { | |
| 12 | + text-align: left; | |
| 13 | + padding: 8px; | |
| 14 | + border-bottom: 1px solid #ddd; | |
| 15 | + } | |
| 16 | + | |
| 17 | + .table tr:hover { | |
| 18 | + background-color: #f5f5f5; | |
| 19 | + } | |
| 20 | + | |
| 21 | + .search-form { | |
| 22 | + margin-bottom: 20px; | |
| 23 | + } | |
| 24 | + | |
| 25 | + .search-form .input-group { | |
| 26 | + width: 300px; | |
| 27 | + } | |
| 28 | +</style> | |
| 29 | +{% endblock %} | |
| 30 | +<!DOCTYPE html> | |
| 31 | +<html> | |
| 32 | +<head> | |
| 33 | + <title>{% block title %}{% endblock %}</title> | |
| 34 | + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"> | |
| 35 | + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.min.css') }}"> | |
| 36 | + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> | |
| 37 | + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> | |
| 38 | + <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> | |
| 39 | + | |
| 40 | + | |
| 41 | +</head> | |
| 42 | +<body> | |
| 43 | + | |
| 44 | + <div class="content"> | |
| 45 | +{% block content %} | |
| 46 | + | |
| 47 | +<div class="container px-4 py-5" id="hanging-icons"> | |
| 48 | + <h2 class="pb-2 border-bottom">{{gettext('t_components_shop')}}</h2> | |
| 49 | + <form action="{{ url_for('components.dashboard') }}" method="GET" class="search-form"> | |
| 50 | + <div class="input-group"> | |
| 51 | + <input type="text" name="search_query" class="form-control" placeholder="Search components"> | |
| 52 | + <button type="submit" class="btn btn-primary">Search</button> | |
| 53 | + </div> | |
| 54 | +</form> | |
| 55 | + | |
| 56 | + | |
| 57 | + <div class="row g-4 py-5 row-cols-1 row-cols-lg-3"> | |
| 58 | + {% if component_server %} | |
| 59 | + {% for component in component_server %} | |
| 60 | + <div class="col d-flex align-items-start"> | |
| 61 | + <div class="icon-square bg-light text-dark flex-shrink-0 me-3"> | |
| 62 | + <img class="d-block mx-auto mb-4" src="/static/img/logo-k2.png" alt="" width="60"> | |
| 63 | + </div> | |
| 64 | + <div> | |
| 65 | + <h2>{{ component.name|title }}</h2> | |
| 66 | + <p>{{ component.description }}</p> | |
| 67 | + <p>ВЕРСІЯ {{ component.latest_version }}</p> | |
| 68 | + {% if component.name in components_names %} | |
| 69 | + <button type="button" class="btn btn-success">Installed</button> | |
| 70 | + {% else %} | |
| 71 | + <a href="" class="btn btn-primary">Install</a> | |
| 72 | + {% endif %} | |
| 73 | + </div> | |
| 74 | + </div> | |
| 75 | + {% endfor %} | |
| 76 | + {% else %} | |
| 77 | + <div class="col"> | |
| 78 | + <p>No components available.</p> | |
| 79 | + </div> | |
| 80 | + {% endif %} | |
| 81 | + </div> | |
| 82 | +</div> | |
| 83 | + | |
| 84 | +{% endblock %} | |
| 85 | + | |
| 86 | + | |
| 87 | + </div> | |
| 88 | + | |
| 89 | +</body> | |
| 90 | +</html> |
templates/dashboard-list.html
| 1 | + {% extends 'base.html' %} | |
| 2 | + | |
| 3 | +{% block styles %} | |
| 4 | +<style> | |
| 5 | + .table { | |
| 6 | + border-collapse: collapse; | |
| 7 | + width: 100%; | |
| 8 | + } | |
| 9 | + | |
| 10 | + .table th, .table td { | |
| 11 | + text-align: left; | |
| 12 | + padding: 8px; | |
| 13 | + border-bottom: 1px solid #ddd; | |
| 14 | + } | |
| 15 | + | |
| 16 | + .table tr:hover { | |
| 17 | + background-color: #f5f5f5; | |
| 18 | + } | |
| 19 | + | |
| 20 | + .search-form { | |
| 21 | + margin-bottom: 20px; | |
| 22 | + } | |
| 23 | + | |
| 24 | + .search-form .input-group { | |
| 25 | + width: 300px; | |
| 26 | + } | |
| 27 | +</style> | |
| 28 | +{% endblock %} | |
| 29 | +<!DOCTYPE html> | |
| 30 | +<html> | |
| 31 | +<head> | |
| 32 | + <title>{% block title %}{% endblock %}</title> | |
| 33 | + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"> | |
| 34 | + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.min.css') }}"> | |
| 35 | + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> | |
| 36 | + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> | |
| 37 | + <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> | |
| 38 | + | |
| 39 | + | |
| 40 | +</head> | |
| 41 | +<body> | |
| 42 | + | |
| 43 | + <div class="content"> | |
| 44 | +{% block content %} | |
| 45 | + | |
| 46 | +<h2>{{ gettext('t_installed_components') }}</h2> | |
| 47 | + | |
| 48 | +<table class="table"> | |
| 49 | + <thead> | |
| 50 | + <tr> | |
| 51 | + <th>{{gettext('t_name')}}</th> | |
| 52 | + <th>{{gettext('t_description')}}</th> | |
| 53 | + <th>{{gettext('t_version')}}</th> | |
| 54 | + <th>{{gettext('t_dependencies')}}</th> | |
| 55 | + <th>{{gettext('t_git_link')}}</th> | |
| 56 | + <th>{{gettext('t_install_at')}}</th> | |
| 57 | + <th>{{gettext('t_status')}}</th> | |
| 58 | + <th>{{gettext('t_action')}}</th> | |
| 59 | + </tr> | |
| 60 | + </thead> | |
| 61 | + | |
| 62 | + <tbody> | |
| 63 | + <tr> | |
| 64 | + <td>k2root</td> | |
| 65 | + <td>main component</td> | |
| 66 | + <td colspan="6">2.5.1.27</td></tr> | |
| 67 | + | |
| 68 | + {% for component in components %} | |
| 69 | + <tr> | |
| 70 | + <td>{{ component.name }}</td> | |
| 71 | + <td>{{ component.description }}</td> | |
| 72 | + <td>{{ component.version }}</td> | |
| 73 | + <td>{{ component.dependencies }}</td> | |
| 74 | + <td>{{ component.git_link }}</td> | |
| 75 | + <td>{{ component.date_installed }}</td> | |
| 76 | + <td> | |
| 77 | + {% if component.installed %} | |
| 78 | + Yes | |
| 79 | + {% else %} | |
| 80 | + No | |
| 81 | + {% endif %} | |
| 82 | + </td> | |
| 83 | + <td> | |
| 84 | + {% if component.installed %} | |
| 85 | + <a href="/remove_dependencies/{{ component.id }}" class="btn btn-primary">Вимкнути</a> | |
| 86 | + {% else %} | |
| 87 | + <a href="/add_dependencies/{{ component.id }}" class="btn btn-primary">Увімкнути</a> | |
| 88 | + <!-- Button trigger modal --> | |
| 89 | +<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#components-{{ component.id }}"> | |
| 90 | + Видалити | |
| 91 | +</button> | |
| 92 | + | |
| 93 | +<!-- Modal --> | |
| 94 | +<div class="modal fade" id="components-{{ component.id }}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> | |
| 95 | + <div class="modal-dialog"> | |
| 96 | + <div class="modal-content"> | |
| 97 | + <div class="modal-header"> | |
| 98 | + <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1> | |
| 99 | + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> | |
| 100 | + </div> | |
| 101 | + <div class="modal-body"> | |
| 102 | + Видалити компоненту? | |
| 103 | + </div> | |
| 104 | + <div class="modal-footer"> | |
| 105 | + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> | |
| 106 | + <a href="/remove-component/{{ component.id }}" class="btn btn-danger">Видалити</a> | |
| 107 | + </div> | |
| 108 | + </div> | |
| 109 | + </div> | |
| 110 | +</div> | |
| 111 | + {% endif %} | |
| 112 | + </td> | |
| 113 | + </tr> | |
| 114 | + {% endfor %} | |
| 115 | + </tbody> | |
| 116 | +</table> | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | +{% endblock %} | |
| 122 | + | |
| 123 | + | |
| 124 | + </div> | |
| 125 | + | |
| 126 | +</body> | |
| 127 | +</html> |
templates/dashboard.html
| 1 | -{% extends "base.html" %} | |
| 2 | 1 | |
| 2 | + | |
| 3 | 3 | {% block styles %} |
| 4 | 4 | <style> |
| 5 | 5 | .table { |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | |
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | |
| ... | ... | @@ -26,27 +26,40 @@ |
| 26 | 26 | } |
| 27 | 27 | </style> |
| 28 | 28 | {% endblock %} |
| 29 | +<!DOCTYPE html> | |
| 30 | +<html> | |
| 31 | +<head> | |
| 32 | + <title>{% block title %}{% endblock %}</title> | |
| 33 | + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"> | |
| 34 | + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.min.css') }}"> | |
| 35 | + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> | |
| 36 | + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> | |
| 37 | + <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> | |
| 29 | 38 | |
| 39 | + | |
| 40 | +</head> | |
| 41 | +<body> | |
| 42 | + | |
| 43 | + <div class="content"> | |
| 30 | 44 | {% block content %} |
| 31 | 45 | <h1>K2CloudERP-2.5.1.27</h1> |
| 32 | -<p> <a href="/logout">вихід</a></p> | |
| 33 | -<p> <a href="{{ url_for('components.change_language', lang='en') }}">en</a> | <a href="{{ url_for('components.change_language', lang='uk') }}">uk</a></p> | |
| 46 | +<p> <a href="{{ url_for('components.change_language', lang='en') }}">en</a> | <a href="{{ url_for('components.change_language', lang='pl') }}">pl</a> | <a href="">uk</a></p> | |
| 34 | 47 | {{language}} |
| 35 | -{{lang_d}} | |
| 36 | 48 | |
| 37 | -<h2>{{ _('Installed components') }}</h2> | |
| 38 | 49 | |
| 50 | +<h2>{{ gettext('t_installed_components') }}</h2> | |
| 51 | + | |
| 39 | 52 | <table class="table"> |
| 40 | 53 | <thead> |
| 41 | 54 | <tr> |
| 42 | - <th>{{_('Name')}}</th> | |
| 43 | - <th>{{_('Description')}}</th> | |
| 44 | - <th>{{_('Version')}}</th> | |
| 45 | - <th>{{_('Dependencies')}}</th> | |
| 46 | - <th>{{_('Git Link')}}</th> | |
| 47 | - <th>{{_('Install At')}}</th> | |
| 48 | - <th>{{_('Status')}}</th> | |
| 49 | - <th>{{_('Action')}}</th> | |
| 55 | + <th>{{gettext('t_name')}}</th> | |
| 56 | + <th>{{gettext('t_description')}}</th> | |
| 57 | + <th>{{gettext('t_version')}}</th> | |
| 58 | + <th>{{gettext('t_dependencies')}}</th> | |
| 59 | + <th>{{gettext('t_git_link')}}</th> | |
| 60 | + <th>{{gettext('t_install_at')}}</th> | |
| 61 | + <th>{{gettext('t_status')}}</th> | |
| 62 | + <th>{{gettext('t_action')}}</th> | |
| 50 | 63 | </tr> |
| 51 | 64 | </thead> |
| 52 | 65 | |
| ... | ... | @@ -112,7 +125,7 @@ |
| 112 | 125 | |
| 113 | 126 | |
| 114 | 127 | <div class="container px-4 py-5" id="hanging-icons"> |
| 115 | - <h2 class="pb-2 border-bottom">{{_('ADD Components')}}</h2> | |
| 128 | + <h2 class="pb-2 border-bottom">{{gettext('t_components_shop')}}</h2> | |
| 116 | 129 | <form action="{{ url_for('components.dashboard') }}" method="GET" class="search-form"> |
| 117 | 130 | <div class="input-group"> |
| 118 | 131 | <input type="text" name="search_query" class="form-control" placeholder="Search components"> |
| ... | ... | @@ -149,4 +162,13 @@ |
| 149 | 162 | </div> |
| 150 | 163 | |
| 151 | 164 | {% endblock %} |
| 165 | +<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> | |
| 166 | + <footer> | |
| 167 | + © 2023 Корпорація k2 | |
| 168 | + </footer> | |
| 169 | + | |
| 170 | + </div> | |
| 171 | + | |
| 172 | +</body> | |
| 173 | +</html> |