Commit 0fd79827789847350a22a18ec18d78471d7bc0cf

Authored by Василь Свідрик
1 parent 282a39ee6f
Exists in master

add k2, k2obj class, other

Showing 38 changed files with 618 additions and 464 deletions Side-by-side Diff

__pycache__/main.cpython-310.pyc
No preview for this file type
__pycache__/routes.cpython-310.pyc
No preview for this file type
components/k2test/.idea/.gitignore
  1 +# Default ignored files
  2 +/shelf/
  3 +/workspace.xml
components/k2test/.idea/gittest.iml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module type="PYTHON_MODULE" version="4">
  3 + <component name="NewModuleRootManager">
  4 + <content url="file://$MODULE_DIR$">
  5 + <excludeFolder url="file://$MODULE_DIR$/venv" />
  6 + </content>
  7 + <orderEntry type="inheritedJdk" />
  8 + <orderEntry type="sourceFolder" forTests="false" />
  9 + </component>
  10 +</module>
components/k2test/.idea/inspectionProfiles/profiles_settings.xml
  1 +<component name="InspectionProjectProfileManager">
  2 + <settings>
  3 + <option name="USE_PROJECT_PROFILE" value="false" />
  4 + <version value="1.0" />
  5 + </settings>
  6 +</component>
components/k2test/.idea/misc.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (gittest)" project-jdk-type="Python SDK" />
  4 + <component name="PyCharmProfessionalAdvertiser">
  5 + <option name="shown" value="true" />
  6 + </component>
  7 +</project>
components/k2test/.idea/modules.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ProjectModuleManager">
  4 + <modules>
  5 + <module fileurl="file://$PROJECT_DIR$/.idea/gittest.iml" filepath="$PROJECT_DIR$/.idea/gittest.iml" />
  6 + </modules>
  7 + </component>
  8 +</project>
components/k2test/.idea/vcs.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="VcsDirectoryMappings">
  4 + <mapping directory="$PROJECT_DIR$" vcs="Git" />
  5 + </component>
  6 +</project>
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
components/k2test/k2test/languages/en/LC_MESSAGES/messages.mo
No preview for this file type
components/k2test/k2test/languages/en/LC_MESSAGES/messages.po
  1 +msgid "Installed components"
  2 +msgstr "Installed components"
  3 +
  4 +msgid "Name"
  5 +msgstr "Name"
  6 +
  7 +msgid "Description"
  8 +msgstr "Description"
  9 +
  10 +msgid "Version"
  11 +msgstr "Version"
  12 +
  13 +msgid "Dependencies"
  14 +msgstr "Dependencies"
  15 +
  16 +msgid "Git Link"
  17 +msgstr "Git Link"
  18 +
  19 +msgid "Install At"
  20 +msgstr "Install At"
  21 +
  22 +msgid "Status"
  23 +msgstr "Status"
  24 +
  25 +msgid "Action"
  26 +msgstr "Action"
  27 +
  28 +msgid "Components Shop"
  29 +msgstr "Components Shop"
  30 +
  31 +msgid "New 2 page"
  32 +msgstr "New 2 page"
components/k2test/k2test/languages/uk/LC_MESSAGES/messages.mo
No preview for this file type
components/k2test/k2test/languages/uk/LC_MESSAGES/messages.po
  1 +msgid "New 2 page"
  2 +msgstr "Нова сторінка 2"
components/k2test/k2test/templates/login.html
  1 +login
components/k2test/k2test/templates/new2.html
  1 +
  2 +
  3 +<h2>{{ _('New 2 page') }}</h2>
components/k2test/k2test/views.py
  1 +from flask import render_template, redirect, request
  2 +from flask_login import login_user, current_user, logout_user, login_required
  3 +from flask import current_app as k2
  4 +from flask import Blueprint, json
  5 +from flask_sqlalchemy import SQLAlchemy
  6 +
  7 +
  8 +
  9 +k2test = Blueprint('k2test', __name__, template_folder='templates', static_folder='static',)
  10 +
  11 +
  12 +
  13 +@k2test.route('/new')
  14 +def new_component():
  15 + db = k2.extensions['sqlalchemy'].db
  16 + connection = db.engine.connect()
  17 + query = db.text("SELECT email, login FROM k2users")
  18 + result = connection.execute(query).fetchall()
  19 + rows = [dict(email=row.email, login=row.login) for row in result]
  20 + # Перетворення результату на JSON
  21 + json_result = json.dumps(rows)
  22 + return json_result
  23 +
  24 +@k2test.route('/new2')
  25 +def new_component2():
  26 + return render_template('new2.html')
  27 +
  28 +@k2test.route('/new3')
  29 +def new_component3():
  30 + return 'сторінка 3'
  31 +
  32 +@k2test.route('/new4')
  33 +def new_component4():
  34 + return 'сторінка 4'
components/k2test/requirements.txt
  1 +Flask-Login==0.6.2
db/__pycache__/database.cpython-310.pyc
No preview for this file type
No preview for this file type
db/database.py
1   -from flask_sqlalchemy import SQLAlchemy
2   -from sqlalchemy import text
3   -import yaml
4   -import os
5   -# load database settings from yml file
6   -def init_db_uri():
7   - with open('db/db.yml', 'r') as f:
8   - db_config = yaml.load(f, Loader=yaml.FullLoader)
9   - return db_config
10   -# creating a connection string
11   -db = SQLAlchemy()
12   -
13   -def init_db(app):
14   - db_config = init_db_uri()
15   - db_uri = f"mysql+{db_config['driver']}://{db_config['user']}:{db_config['password']}@{db_config['host']}/{db_config['dbname']}"
16   - app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
17   - basedir = os.path.abspath(os.path.dirname(__file__))
18   - db_path = os.path.join(basedir, '', '', 'database.db')
19   - app.config['SQLALCHEMY_BINDS'] = {'db2': f'sqlite:///{db_path}'}
20   - db.init_app(app)
k2/__pycache__/k2cfg.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2inst.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2obj.cpython-310.pyc
No preview for this file type
k2/__pycache__/root.cpython-310.pyc
No preview for this file type
  1 +from flask_sqlalchemy import SQLAlchemy
  2 +from sqlalchemy import text
  3 +from .k2obj import k2obj
  4 +import yaml
  5 +import os
  6 +import requests
  7 +import pytz
  8 +import os
  9 +import sys
  10 +from flask import session
  11 +
  12 +class k2(k2obj):
  13 +
  14 + version = '2.5.1.27'
  15 + db = SQLAlchemy()
  16 + domain = 'http://127.0.0.1:5000/'
  17 + update_domain ='http://127.0.0.1:8001/'
  18 + venv_bin_path = os.path.join(os.path.dirname(sys.prefix), 'venv/Scripts')
  19 + json_sort_keys = False
  20 + timezone = pytz.timezone('Europe/Kiev')
  21 + secret_key = 'JH&INH987gFDHdsagh&8dwbjdw8ckw'
  22 + default_language = 'en'
  23 + current_language = ''
  24 + babel_translation_directories = ''
  25 +
  26 + def __init__(self):
  27 + super().__init__()
  28 +
  29 + @classmethod
  30 + def load_babel_translation_directories(cls):
  31 + with open('languages/babel_translation_directories.yml', 'r') as f:
  32 + data = yaml.safe_load(f)
  33 + cls.babel_translation_directories = data['babel_translation_directories']
  34 +
  35 + @classmethod
  36 + def get_locale(cls):
  37 + if 'lang' in session:
  38 + # Отримати обрану мову з сеансу користувача
  39 + return session['lang']
  40 + else:
  41 + # Повернути мову за замовчуванням з налаштувань додатку
  42 + return cls.default_language #app.config['DEFAULT_LANGUAGE']
  43 +
  44 + @classmethod
  45 + def search_babel_translation_directories(cls):
  46 + response = requests.get(f'{cls.domain}api/languages')
  47 + if response.status_code == 200:
  48 + cls.babel_translation_directories = response.text
  49 + data = {'babel_translation_directories': response.text}
  50 + else:
  51 + cls.babel_translation_directories = 'languages'
  52 + data = {'babel_translation_directories': 'languages'}
  53 +
  54 + with open('languages/babel_translation_directories.yml', 'w') as f:
  55 + yaml.dump(data, f)
  56 +
  57 + # load database settings from yml file
  58 + def init_db_uri(self):
  59 + with open('db/db.yml', 'r') as f:
  60 + db_config = yaml.load(f, Loader=yaml.FullLoader)
  61 + return db_config
  62 +
  63 + # creating a connection string
  64 +
  65 +
  66 + def init_db(self, app):
  67 + db_config = self.init_db_uri()
  68 + db_uri = f"mysql+{db_config['driver']}://{db_config['user']}:{db_config['password']}@{db_config['host']}/{db_config['dbname']}"
  69 + app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
  70 + db_path = '../db/database.db'
  71 + app.config['SQLALCHEMY_BINDS'] = {'db2': f'sqlite:///{db_path}'}
  72 + self.db.init_app(app)
  1 +import zipfile
  2 +from flask import Flask, Blueprint, jsonify, render_template, redirect, url_for, session, g
  3 +import os
  4 +import shutil
  5 +from datetime import datetime
  6 +import uuid
  7 +from flask import request
  8 +from k2.k2cfg import k2
  9 +from flask_migrate import Migrate
  10 +import requests
  11 +import subprocess
  12 +from flask import current_app
  13 +import yaml
  14 +from functools import wraps
  15 +
  16 +db = k2.db
  17 +#migrate = Migrate(app, db)
  18 +def generate_id():
  19 + generated_id = uuid.uuid4().hex[:32]
  20 + return ''.join([generated_id[i:i + 4] for i in range(0, len(generated_id), 4)])
  21 +class Component(db.Model):
  22 + __bind_key__ = 'db2'
  23 + __tablename__ = 'component'
  24 + __table_args__ = {'extend_existing': True}
  25 + id = db.Column(db.String(36), primary_key=True, default=generate_id)
  26 + name = db.Column(db.String(100), nullable=False)
  27 + description = db.Column(db.String(200))
  28 + version = db.Column(db.String(20))
  29 + git_link = db.Column(db.String(200))
  30 + dependencies = db.Column(db.String)
  31 + date_installed = db.Column(db.DateTime, default=datetime.utcnow)
  32 + installed = db.Column(db.Boolean, default=False)
  33 +
  34 + def __init__(self, name, description, version, git_link, dependencies, installed):
  35 + self.name = name
  36 + self.description = description
  37 + self.version = version
  38 + self.git_link = git_link
  39 + self.dependencies = dependencies
  40 + self.installed = installed
  41 + def __repr__(self):
  42 + return f"Component('{self.name}', '{self.version}')"
  43 + @classmethod
  44 + def get_repository_by_id(self,rep_id):
  45 + component = db.session.query(Component).filter(Component.id == rep_id).first()
  46 + return component
  47 +components_bp = Blueprint('components', __name__, template_folder='templates')
  48 +config = yaml.safe_load(open("db/first-login.yml"))
  49 +
  50 +def first_login_required(view_func):
  51 + @wraps(view_func)
  52 + def decorated_view(*args, **kwargs):
  53 + if 'username' not in session:
  54 + return redirect(url_for('first_login'))
  55 + return view_func(*args, **kwargs)
  56 +
  57 + return decorated_view
  58 +
  59 +
  60 +@components_bp.route('/api/languages', methods=['GET'])
  61 +def find_language():
  62 + components = Component.query.all()
  63 + languages_paths = []
  64 + # Додаємо головну директорію languages
  65 + languages_paths.append('languages')
  66 + # Знаходимо шляхи до директорій languages всередині папки components
  67 + for component in components:
  68 + component_languages_directory = 'components/' + component.name + '/' + component.name + '/languages'
  69 + languages_paths.append(component_languages_directory)
  70 + result = ';'.join(languages_paths)
  71 + print(result)
  72 + return result
  73 +
  74 +@components_bp.route('/', methods=['GET', 'POST'])
  75 +@first_login_required
  76 +def home():
  77 + return redirect('/dashboard')
  78 +
  79 +@components_bp.route('/login', methods=['GET', 'POST'])
  80 +def first_login():
  81 + if request.method == "POST":
  82 + username = request.form.get("username")
  83 + password = request.form.get("password")
  84 + for user in config["users"]:
  85 + if user["username"] == username and user["password"] == password:
  86 + session['username'] = username # Збереження ім'я користувача в сесії
  87 + return redirect(url_for('components.dashboard'))
  88 + return "Невірне ім'я користувача або пароль."
  89 + return render_template('first-login.html')
  90 +
  91 +@components_bp.route('/logout')
  92 +def logout():
  93 + session.pop('username', None) # Видалення ім'я користувача з сесії
  94 + return redirect(url_for('first_login'))
  95 +
  96 +@components_bp.route('/change_language/<lang>')
  97 +def change_language(lang):
  98 + session['lang'] = lang
  99 + k2.current_language = lang
  100 + return redirect(url_for('components.dashboard'))
  101 +
  102 +@components_bp.route('/dashboard')
  103 +@first_login_required
  104 +def dashboard():
  105 +
  106 + # Компоненти доступні для встановлення
  107 + try:
  108 + # GET-запит до API
  109 + response = requests.get('http://127.0.0.1:8001/api/components')
  110 + json_data = response.json()
  111 + # Перетворення JSON-об'єкту на масив
  112 + component_server = [item for item in json_data]
  113 + except:
  114 + component_server = None
  115 +
  116 + # Встановлені компоненти
  117 + components = Component.query.all()
  118 + components_names = [component.name for component in components]
  119 + # Отримання значення пошукового запиту з параметрів URL
  120 + search_query = request.args.get('search_query')
  121 + #print(search_query)
  122 + filtered_components = []
  123 + if search_query:
  124 + filtered_components = [component for component in component_server if
  125 + (search_query.lower() in component['name'].lower() if component['name'] else False) or
  126 + (search_query.lower() in component['description'].lower() if component[
  127 + 'description'] else False)]
  128 + else:
  129 + filtered_components = component_server
  130 + current_language = k2.current_language
  131 +
  132 + return render_template('dashboard.html', components=components,
  133 + components_names=components_names, component_server=filtered_components,
  134 + search_query=search_query, language=current_language )
  135 +
  136 +@components_bp.route('/show_components/<string:component_id>')
  137 +@first_login_required
  138 +def show_components(component_id):
  139 + response = requests.get('http://127.0.0.1:8001/api/components')
  140 + json_data = response.json()
  141 + selected_component = next((component for component in json_data if component['id'] == component_id), None)
  142 + return render_template('component-info.html', selected_component=selected_component)
  143 +
  144 +@components_bp.route('/install_components_git/<string:component_id>')
  145 +@first_login_required
  146 +def install_components_git(component_id):
  147 + # Шлях до головної папки проекту
  148 + project_folder = 'components'
  149 + #component = Component.get_repository_by_id(component_id)
  150 + response = requests.get('http://127.0.0.1:8001/api/components')
  151 + json_data = response.json()
  152 + selected_component = next((component for component in json_data if component['id'] == component_id), None)
  153 + # Назва репозиторія
  154 + repository_name = selected_component['name']
  155 + # Шлях до папки репозиторія в межах проекту
  156 + repository_folder = os.path.join(project_folder, repository_name)
  157 + # URL репозиторія
  158 +
  159 + git_repo_url = selected_component['git_link']
  160 + try:
  161 + # Перевірка наявності папки репозиторія
  162 + if not os.path.exists(repository_folder):
  163 + # Створення папки репозиторія
  164 + os.makedirs(repository_folder)
  165 + # Шлях до файлу __init__.py
  166 + init_file = os.path.join(repository_folder, '__init__.py')
  167 + # Перевірка наявності файлу __init__.py
  168 + if not os.path.exists(init_file):
  169 + # Створення пустого файлу __init__.py
  170 + open(init_file, 'a').close()
  171 + #підключення до приватного репозиторію
  172 + #os.environ['GITLAB_PRIVATE_TOKEN'] = '8xxTpxrKVDGoXD5ynjiW'
  173 + #git_repo_url_with_token = git_repo_url.replace('https://',
  174 + # f'https://oauth2:{os.environ["GITLAB_PRIVATE_TOKEN"]}@')
  175 +
  176 + # Команда для встановлення з використанням git_repo_url і повного шляху до папки репозиторія
  177 + command = ['venv/Scripts/python.exe', '-m', 'pip', 'install', '--use-pep517', 'git+' + git_repo_url, '--target=' + repository_folder]
  178 + # Виконуємо команду встановлення
  179 + subprocess.check_call(command)
  180 +
  181 + # Шлях до файлу, до якого потрібно додати код
  182 + file_path = 'routes.py'
  183 + # Код, який потрібно додати
  184 + code = selected_component['dependencies']
  185 + # Відкриття файлу у режимі дозапису
  186 + with open(file_path, 'a') as file:
  187 + # Запис нового коду у файл
  188 + file.write('\n')
  189 + file.write(code)
  190 + file.write('\n')
  191 + component = Component.query.filter_by(name=selected_component['name']).first()
  192 + if not component:
  193 + new_component = Component(
  194 + name=selected_component['name'],
  195 + description=selected_component['description'],
  196 + version=selected_component['version'],
  197 + git_link=selected_component['git_link'],
  198 + dependencies=selected_component['dependencies'],
  199 + installed=True
  200 + )
  201 + # Add the new component to the database
  202 + db.session.add(new_component)
  203 + db.session.commit()
  204 +
  205 + # Повертаємо повідомлення про успішне встановлення
  206 + return f'Installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
  207 + except subprocess.CalledProcessError as e:
  208 + return 'Error installing : ' + str(e)
  209 +
  210 +@components_bp.route('/install_components/<string:component_id>')
  211 +@first_login_required
  212 +def install_component_from_archive(component_id):
  213 + # Шлях до головної папки проекту
  214 + project_folder = 'components'
  215 + # Отримати відповідну компоненту зі списку компонент
  216 + response = requests.get('http://127.0.0.1:8001/api/components')
  217 + json_data = response.json()
  218 + selected_component = next((component for component in json_data if component['id'] == component_id), None)
  219 + if selected_component is None:
  220 + return 'Component not found'
  221 + # Отримати посилання на архів компоненти та версію
  222 + archive_url = selected_component['latest_component_data']
  223 + version = selected_component['latest_version']
  224 + try:
  225 + # Створити шлях до папки компоненти згідно назви та версії
  226 + component_folder = os.path.join(project_folder)
  227 + os.makedirs(component_folder, exist_ok=True)
  228 + # Завантажити архів компоненти
  229 + response = requests.get(archive_url, stream=True)
  230 + response.raise_for_status()
  231 + # Шлях до завантаженого архіву
  232 + archive_path = os.path.join(component_folder, f"{selected_component['name']}.zip")
  233 + # Встановити залежності з файлу requirements.txt
  234 +
  235 + # Зберегти архів на диск
  236 + with open(archive_path, "wb") as file:
  237 + for chunk in response.iter_content(chunk_size=8192):
  238 + file.write(chunk)
  239 + # Розпакувати архів
  240 + with zipfile.ZipFile(archive_path, "r") as zip_ref:
  241 + zip_ref.extractall(component_folder)
  242 +
  243 + # Видалити архів
  244 + os.remove(archive_path)
  245 +
  246 + # Шлях до файлу, до якого потрібно додати код
  247 + file_path = 'routes.py'
  248 + # Код, який потрібно додати
  249 + code = f'''from components.{selected_component['name']}.{selected_component['name']}.views import {selected_component['name']}\napp.register_blueprint({selected_component['name']}, url_prefix='/{selected_component['name']}')'''
  250 + #selected_component['dependencies']
  251 +
  252 + # Відкриття файлу у режимі дозапису
  253 + with open(file_path, 'a') as file:
  254 + # Запис нового коду у файл
  255 + file.write('\n')
  256 + file.write(code)
  257 + file.write('\n')
  258 +
  259 + # Оновити базу даних з встановленою компонентою
  260 + component = Component.query.filter_by(name=selected_component['name']).first()
  261 + if not component:
  262 + component = Component(
  263 + name=selected_component['name'],
  264 + description=selected_component['description'],
  265 + version=version,
  266 + git_link=selected_component['git_link'],
  267 + dependencies=code,
  268 + installed=True
  269 + )
  270 + db.session.add(component)
  271 + else:
  272 + component.version = version
  273 + component.git_link = selected_component['git_link']
  274 + component.dependencies = code
  275 + component.installed = True
  276 +
  277 + db.session.commit()
  278 +
  279 +
  280 + k2.search_babel_translation_directories()
  281 +
  282 + return f'''Component installed successfully: {selected_component["name"]} v{version} {k2.babel_translation_directories},
  283 + \n \n please wait installing requirments...
  284 + <meta http-equiv="refresh" content="0;url=/install-requirments/{selected_component["name"]}" />'''
  285 +
  286 + except Exception as e:
  287 + return f'Error installing component: {str(e)}'
  288 +
  289 +@components_bp.route('/install-requirments/<string:selected_component_name>', methods=['GET'])
  290 +@first_login_required
  291 +def install_requirments(selected_component_name):
  292 + requirements_file = os.path.join('components', selected_component_name, "requirements.txt")
  293 + if os.path.isfile(requirements_file):
  294 + pip_command = f"{k2.venv_bin_path}/python -m pip install -r {requirements_file}"
  295 + subprocess.run(pip_command, shell=True, check=True)
  296 + return f'''Requirements installed successfully
  297 + \n \n please wait installing requirments components...
  298 + <meta http-equiv="refresh" content="1;url=/install-requirments-components" />'''
  299 +
  300 +
  301 +@components_bp.route('/install-requirments-components')
  302 +@first_login_required
  303 +def install_requirements_components():
  304 + # Откриття файлу requirements_components.txt
  305 + requirements_file = 'requirements_components.txt'
  306 + component_ids = None
  307 + if os.path.isfile(requirements_file):
  308 + with open('requirements_components.txt', 'r') as file:
  309 + component_ids = file.read().splitlines()
  310 + if component_ids:
  311 + for component_id in component_ids:
  312 + # Виклик роуту '/install_components/<string:component_name>' для кожної назви компоненти
  313 + response = requests.get(
  314 + f'/install_components/{component_id}')
  315 + return f'Requirements components installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
  316 + else:
  317 + return f'<meta http-equiv="refresh" content="1;url=/dashboard" />'
  318 + # Опрацювання відповіді (за потреби)
  319 +
  320 +
  321 +@components_bp.route('/remove_dependencies/<string:component_id>', methods=['GET'])
  322 +@first_login_required
  323 +def remove_dependencies(component_id):
  324 + # Знаходимо компоненту за її ID
  325 + component = Component.query.get(component_id)
  326 + if not component:
  327 + return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />'
  328 +
  329 + # Шлях до файлу, з якого потрібно видалити залежності
  330 + file_path = 'routes.py'
  331 +
  332 + # Зчитуємо вміст файлу
  333 + with open(file_path, 'r') as file:
  334 + lines = file.readlines()
  335 +
  336 + # Видаляємо рядки, що містять залежності компоненти
  337 + updated_lines = [line for line in lines if line.strip() not in component.dependencies]
  338 +
  339 + # Записуємо оновлений вміст у файл
  340 + with open(file_path, 'w') as file:
  341 + file.writelines(updated_lines)
  342 +
  343 + # Оновлюємо статус компоненти
  344 + component.installed = False
  345 + db.session.commit()
  346 +
  347 + return 'Component successfully turn off <meta http-equiv="refresh" content="1;url=/dashboard" />'
  348 +
  349 +@components_bp.route('/add_dependencies/<string:component_id>', methods=['GET'])
  350 +@first_login_required
  351 +def add_dependencies(component_id):
  352 +
  353 + # Знаходимо компоненту за її ID
  354 + component = Component.query.get(component_id)
  355 + if not component:
  356 + return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />'
  357 +
  358 + # Шлях до файлу, з якого потрібно видалити залежності
  359 + file_path = 'routes.py'
  360 + code = component.dependencies
  361 + # Відкриття файлу у режимі дозапису
  362 + with open(file_path, 'a') as file:
  363 + # Запис нового коду у файл
  364 + file.write(code)
  365 +
  366 + # Оновлюємо статус компоненти
  367 + component.installed = True
  368 + db.session.commit()
  369 + return 'Dependencies added successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
  370 +
  371 +@components_bp.route('/remove-component/<string:component_id>')
  372 +@first_login_required
  373 +def remove_component(component_id):
  374 + # Шлях до головної папки проекту
  375 + project_folder = 'components'
  376 + component = Component.query.get(component_id)
  377 + # Назва репозиторія
  378 + repository_name = component.name
  379 + # Шлях до папки репозиторія в межах проекту
  380 + repository_folder = os.path.join(project_folder, repository_name)
  381 + try:
  382 + # Перевірка наявності папки репозиторія
  383 + if os.path.exists(repository_folder):
  384 + # Видалення папки репозиторія
  385 + shutil.rmtree(repository_folder)
  386 + # Видаляємо компоненту з бази
  387 + if component:
  388 + db.session.delete(component)
  389 + db.session.commit()
  390 +
  391 + # Повертаємо повідомлення про успішне видалення
  392 + return 'Component removed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
  393 + except Exception as e:
  394 + # Повертаємо повідомлення про помилку видалення
  395 + return 'Error removing component: ' + str(e)
  1 +class k2obj:
  2 + name = ''
  3 + version = ''
  4 + domain = ''
  5 + timezone = ''
  6 + menu = ''
1   -import zipfile
2   -from flask import Flask, Blueprint, jsonify, render_template, redirect, url_for, session, g
3   -import os
4   -import shutil
5   -from datetime import datetime
6   -import uuid
7   -from flask import request
8   -from db.database import db
9   -from flask_migrate import Migrate
10   -from main import app
11   -import requests
12   -import subprocess
13   -from flask import current_app
14   -import yaml
15   -from functools import wraps
16   -from languages.views import get_locale
17   -
18   -
19   -with app.app_context():
20   -
21   - #migrate = Migrate(app, db)
22   - def generate_id():
23   - generated_id = uuid.uuid4().hex[:32]
24   - return ''.join([generated_id[i:i + 4] for i in range(0, len(generated_id), 4)])
25   - class Component(db.Model):
26   - __bind_key__ = 'db2'
27   - __tablename__ = 'component'
28   - __table_args__ = {'extend_existing': True}
29   - id = db.Column(db.String(36), primary_key=True, default=generate_id)
30   - name = db.Column(db.String(100), nullable=False)
31   - description = db.Column(db.String(200))
32   - version = db.Column(db.String(20))
33   - git_link = db.Column(db.String(200))
34   - dependencies = db.Column(db.String)
35   - date_installed = db.Column(db.DateTime, default=datetime.utcnow)
36   - installed = db.Column(db.Boolean, default=False)
37   -
38   - def __init__(self, name, description, version, git_link, dependencies, installed):
39   - self.name = name
40   - self.description = description
41   - self.version = version
42   - self.git_link = git_link
43   - self.dependencies = dependencies
44   - self.installed = installed
45   - def __repr__(self):
46   - return f"Component('{self.name}', '{self.version}')"
47   - @classmethod
48   - def get_repository_by_id(self,rep_id):
49   - component = db.session.query(Component).filter(Component.id == rep_id).first()
50   - return component
51   - components_bp = Blueprint('components', __name__, template_folder='templates')
52   - config = yaml.safe_load(open("db/first-login.yml"))
53   -
54   -
55   - def first_login_required(view_func):
56   - @wraps(view_func)
57   - def decorated_view(*args, **kwargs):
58   - if 'username' not in session:
59   - return redirect(url_for('first_login'))
60   - return view_func(*args, **kwargs)
61   -
62   - return decorated_view
63   -
64   -
65   - def find_language():
66   - components = Component.query.all()
67   - languages_paths = []
68   - # Додаємо головну директорію languages
69   - languages_paths.append('languages')
70   - # Знаходимо шляхи до директорій languages всередині папки components
71   - for component in components:
72   - component_languages_directory = 'components/' + component.name + '/languages'
73   - languages_paths.append(component_languages_directory)
74   - result = ';'.join(languages_paths)
75   - return result
76   -
77   - @app.route('/', methods=['GET', 'POST'])
78   - @first_login_required
79   - def home():
80   - return redirect('/dashboard')
81   -
82   -
83   - @app.route('/login', methods=['GET', 'POST'])
84   - def first_login():
85   - if request.method == "POST":
86   - username = request.form.get("username")
87   - password = request.form.get("password")
88   - for user in config["users"]:
89   - if user["username"] == username and user["password"] == password:
90   - session['username'] = username # Збереження ім'я користувача в сесії
91   - return redirect(url_for('components.dashboard'))
92   - return "Невірне ім'я користувача або пароль."
93   - return render_template('first-login.html')
94   -
95   -
96   - @app.route('/logout')
97   - def logout():
98   - session.pop('username', None) # Видалення ім'я користувача з сесії
99   - return redirect(url_for('login'))
100   -
101   -
102   - @components_bp.route('/change_language/<lang>')
103   - def change_language(lang):
104   - session['lang'] = lang
105   - app.config['CURRENT_LANGUAGE'] = lang
106   - return redirect(url_for('components.dashboard'))
107   -
108   - @components_bp.route('/dashboard')
109   - @first_login_required
110   - def dashboard():
111   -
112   - # Компоненти доступні для встановлення
113   - try:
114   - # GET-запит до API
115   - response = requests.get('http://127.0.0.1:8001/api/components')
116   - json_data = response.json()
117   - # Перетворення JSON-об'єкту на масив
118   - component_server = [item for item in json_data]
119   - except:
120   - component_server = None
121   -
122   - # Встановлені компоненти
123   - components = Component.query.all()
124   - components_names = [component.name for component in components]
125   - # Отримання значення пошукового запиту з параметрів URL
126   - search_query = request.args.get('search_query')
127   - #print(search_query)
128   - filtered_components = []
129   - if search_query:
130   - filtered_components = [component for component in component_server if
131   - (search_query.lower() in component['name'].lower() if component['name'] else False) or
132   - (search_query.lower() in component['description'].lower() if component[
133   - 'description'] else False)]
134   - else:
135   - filtered_components = component_server
136   - current_language = app.config['CURRENT_LANGUAGE'] #get_locale()
137   -
138   - return render_template('dashboard.html', components=components,
139   - components_names=components_names, component_server=filtered_components,
140   - search_query=search_query, language=current_language)
141   -
142   - @components_bp.route('/show_components/<string:component_id>')
143   - @first_login_required
144   - def show_components(component_id):
145   - response = requests.get('http://127.0.0.1:8001/api/components')
146   - json_data = response.json()
147   - selected_component = next((component for component in json_data if component['id'] == component_id), None)
148   - return render_template('component-info.html', selected_component=selected_component)
149   -
150   - @components_bp.route('/install_components_git/<string:component_id>')
151   - @first_login_required
152   - def install_components_git(component_id):
153   - # Шлях до головної папки проекту
154   - project_folder = 'components'
155   - #component = Component.get_repository_by_id(component_id)
156   - response = requests.get('http://127.0.0.1:8001/api/components')
157   - json_data = response.json()
158   - selected_component = next((component for component in json_data if component['id'] == component_id), None)
159   - # Назва репозиторія
160   - repository_name = selected_component['name']
161   - # Шлях до папки репозиторія в межах проекту
162   - repository_folder = os.path.join(project_folder, repository_name)
163   - # URL репозиторія
164   -
165   - git_repo_url = selected_component['git_link']
166   - try:
167   - # Перевірка наявності папки репозиторія
168   - if not os.path.exists(repository_folder):
169   - # Створення папки репозиторія
170   - os.makedirs(repository_folder)
171   - # Шлях до файлу __init__.py
172   - init_file = os.path.join(repository_folder, '__init__.py')
173   - # Перевірка наявності файлу __init__.py
174   - if not os.path.exists(init_file):
175   - # Створення пустого файлу __init__.py
176   - open(init_file, 'a').close()
177   - #підключення до приватного репозиторію
178   - #os.environ['GITLAB_PRIVATE_TOKEN'] = '8xxTpxrKVDGoXD5ynjiW'
179   - #git_repo_url_with_token = git_repo_url.replace('https://',
180   - # f'https://oauth2:{os.environ["GITLAB_PRIVATE_TOKEN"]}@')
181   -
182   - # Команда для встановлення з використанням git_repo_url і повного шляху до папки репозиторія
183   - command = ['venv/Scripts/python.exe', '-m', 'pip', 'install', '--use-pep517', 'git+' + git_repo_url, '--target=' + repository_folder]
184   - # Виконуємо команду встановлення
185   - subprocess.check_call(command)
186   -
187   - # Шлях до файлу, до якого потрібно додати код
188   - file_path = 'routes.py'
189   - # Код, який потрібно додати
190   - code = selected_component['dependencies']
191   - # Відкриття файлу у режимі дозапису
192   - with open(file_path, 'a') as file:
193   - # Запис нового коду у файл
194   - file.write('\n')
195   - file.write(code)
196   - file.write('\n')
197   - component = Component.query.filter_by(name=selected_component['name']).first()
198   - if not component:
199   - new_component = Component(
200   - name=selected_component['name'],
201   - description=selected_component['description'],
202   - version=selected_component['version'],
203   - git_link=selected_component['git_link'],
204   - dependencies=selected_component['dependencies'],
205   - installed=True
206   - )
207   - # Add the new component to the database
208   - db.session.add(new_component)
209   - db.session.commit()
210   -
211   - # Повертаємо повідомлення про успішне встановлення
212   - return f'Installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
213   - except subprocess.CalledProcessError as e:
214   - return 'Error installing : ' + str(e)
215   -
216   - @components_bp.route('/install_components/<string:component_id>')
217   - @first_login_required
218   - def install_component_from_archive(component_id):
219   - # Шлях до головної папки проекту
220   - project_folder = 'components'
221   - # Отримати відповідну компоненту зі списку компонент
222   - response = requests.get('http://127.0.0.1:8001/api/components')
223   - json_data = response.json()
224   - selected_component = next((component for component in json_data if component['id'] == component_id), None)
225   - if selected_component is None:
226   - return 'Component not found'
227   - # Отримати посилання на архів компоненти та версію
228   - archive_url = selected_component['latest_component_data']
229   - version = selected_component['latest_version']
230   - try:
231   - # Створити шлях до папки компоненти згідно назви та версії
232   - component_folder = os.path.join(project_folder)
233   - os.makedirs(component_folder, exist_ok=True)
234   - # Завантажити архів компоненти
235   - response = requests.get(archive_url, stream=True)
236   - response.raise_for_status()
237   - # Шлях до завантаженого архіву
238   - archive_path = os.path.join(component_folder, f"{selected_component['name']}.zip")
239   - # Встановити залежності з файлу requirements.txt
240   -
241   - # Зберегти архів на диск
242   - with open(archive_path, "wb") as file:
243   - for chunk in response.iter_content(chunk_size=8192):
244   - file.write(chunk)
245   - # Розпакувати архів
246   - with zipfile.ZipFile(archive_path, "r") as zip_ref:
247   - zip_ref.extractall(component_folder)
248   -
249   - # Видалити архів
250   - os.remove(archive_path)
251   -
252   - # Шлях до файлу, до якого потрібно додати код
253   - file_path = 'routes.py'
254   - # Код, який потрібно додати
255   - code = f'''from components.{selected_component['name']}.{selected_component['name']}.views import {selected_component['name']}\napp.register_blueprint({selected_component['name']}, url_prefix='/{selected_component['name']}')'''
256   - #selected_component['dependencies']
257   -
258   - # Відкриття файлу у режимі дозапису
259   - with open(file_path, 'a') as file:
260   - # Запис нового коду у файл
261   - file.write('\n')
262   - file.write(code)
263   - file.write('\n')
264   -
265   - # Оновити базу даних з встановленою компонентою
266   - component = Component.query.filter_by(name=selected_component['name']).first()
267   - if not component:
268   - component = Component(
269   - name=selected_component['name'],
270   - description=selected_component['description'],
271   - version=version,
272   - git_link=selected_component['git_link'],
273   - dependencies=code,
274   - installed=True
275   - )
276   - db.session.add(component)
277   - else:
278   - component.version = version
279   - component.git_link = selected_component['git_link']
280   - component.dependencies = code
281   - component.installed = True
282   -
283   - db.session.commit()
284   -
285   - return f'''Component installed successfully: {selected_component["name"]} v{version},
286   - \n \n please wait installing requirments...
287   - <meta http-equiv="refresh" content="0;url=/install-requirments/{selected_component["name"]}" />'''
288   -
289   - except Exception as e:
290   - return f'Error installing component: {str(e)}'
291   -
292   - @components_bp.route('/install-requirments/<string:selected_component_name>', methods=['GET'])
293   - @first_login_required
294   - def install_requirments(selected_component_name):
295   - requirements_file = os.path.join('components', selected_component_name, "requirements.txt")
296   - if os.path.isfile(requirements_file):
297   - pip_command = f"{current_app.config['VENV_BIN_PATH']}/python -m pip install -r {requirements_file}"
298   - subprocess.run(pip_command, shell=True, check=True)
299   - return f'''Requirements installed successfully
300   - \n \n please wait installing requirments components...
301   - <meta http-equiv="refresh" content="1;url=/install-requirments-components" />'''
302   -
303   -
304   - @components_bp.route('/install-requirments-components')
305   - @first_login_required
306   - def install_requirements_components():
307   - # Откриття файлу requirements_components.txt
308   - requirements_file = 'requirements_components.txt'
309   - component_ids = None
310   - if os.path.isfile(requirements_file):
311   - with open('requirements_components.txt', 'r') as file:
312   - component_ids = file.read().splitlines()
313   - if component_ids:
314   - for component_id in component_ids:
315   - # Виклик роуту '/install_components/<string:component_name>' для кожної назви компоненти
316   - response = requests.get(
317   - f'/install_components/{component_id}')
318   - return f'Requirements components installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
319   - else:
320   - return f'<meta http-equiv="refresh" content="1;url=/dashboard" />'
321   - # Опрацювання відповіді (за потреби)
322   -
323   -
324   -
325   -
326   - @components_bp.route('/remove_dependencies/<string:component_id>', methods=['GET'])
327   - @first_login_required
328   - def remove_dependencies(component_id):
329   - # Знаходимо компоненту за її ID
330   - component = Component.query.get(component_id)
331   - if not component:
332   - return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />'
333   -
334   - # Шлях до файлу, з якого потрібно видалити залежності
335   - file_path = 'routes.py'
336   -
337   - # Зчитуємо вміст файлу
338   - with open(file_path, 'r') as file:
339   - lines = file.readlines()
340   -
341   - # Видаляємо рядки, що містять залежності компоненти
342   - updated_lines = [line for line in lines if line.strip() not in component.dependencies]
343   -
344   - # Записуємо оновлений вміст у файл
345   - with open(file_path, 'w') as file:
346   - file.writelines(updated_lines)
347   -
348   - # Оновлюємо статус компоненти
349   - component.installed = False
350   - db.session.commit()
351   -
352   - return 'Component successfully turn off <meta http-equiv="refresh" content="1;url=/dashboard" />'
353   -
354   - @components_bp.route('/add_dependencies/<string:component_id>', methods=['GET'])
355   - @first_login_required
356   - def add_dependencies(component_id):
357   -
358   - # Знаходимо компоненту за її ID
359   - component = Component.query.get(component_id)
360   - if not component:
361   - return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />'
362   -
363   - # Шлях до файлу, з якого потрібно видалити залежності
364   - file_path = 'routes.py'
365   - code = component.dependencies
366   - # Відкриття файлу у режимі дозапису
367   - with open(file_path, 'a') as file:
368   - # Запис нового коду у файл
369   - file.write(code)
370   -
371   - # Оновлюємо статус компоненти
372   - component.installed = True
373   - db.session.commit()
374   - return 'Dependencies added successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
375   -
376   - @components_bp.route('/remove-component/<string:component_id>')
377   - @first_login_required
378   - def remove_component(component_id):
379   - # Шлях до головної папки проекту
380   - project_folder = 'components'
381   - component = Component.query.get(component_id)
382   - # Назва репозиторія
383   - repository_name = component.name
384   - # Шлях до папки репозиторія в межах проекту
385   - repository_folder = os.path.join(project_folder, repository_name)
386   - try:
387   - # Перевірка наявності папки репозиторія
388   - if os.path.exists(repository_folder):
389   - # Видалення папки репозиторія
390   - shutil.rmtree(repository_folder)
391   - # Видаляємо компоненту з бази
392   - if component:
393   - db.session.delete(component)
394   - db.session.commit()
395   -
396   - # Повертаємо повідомлення про успішне видалення
397   - return 'Component removed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
398   - except Exception as e:
399   - # Повертаємо повідомлення про помилку видалення
400   - return 'Error removing component: ' + str(e)
401   - app.register_blueprint(components_bp)
languages/__pycache__/find_language.cpython-310.pyc
No preview for this file type
languages/__pycache__/views.cpython-310.pyc
No preview for this file type
languages/babel_translation_directories.yml
  1 +babel_translation_directories: languages;components/k2test/k2test/languages
languages/find_language.py
1   -from k2.root import Component
languages/views.py
1   -import yaml
2   -from flask import session, g
3   -from main import app, babel
4   -
5   -def load_languages():
6   - with open('languages/languages.yml', 'r') as file:
7   - languages = yaml.safe_load(file)
8   - return print(languages)
9   -
10   -def get_locale():
11   - if 'lang' in session:
12   - # Отримати обрану мову з сеансу користувача
13   - return session['lang']
14   - else:
15   - # Повернути мову за замовчуванням з налаштувань додатку
16   - return app.config['DEFAULT_LANGUAGE']
17   -babel.init_app(app, locale_selector=get_locale)
1   -import pytz
2   -from flask import Flask
3 1 from flask_cors import CORS
4   -from db.database import init_db
5   -import os
6   -import sys
7   -from k2.root import *
8   -from flask_login import LoginManager
9 2 from flask_babel import Babel
  3 +#from k2.k2inst import *
  4 +from flask import Flask
  5 +from k2.k2cfg import k2
10 6  
11   -
12 7 # configure flask app
13 8 app = Flask(__name__)
14   -venv_path = os.path.join(os.path.dirname(sys.prefix), 'venv/Scripts')
15   -app.config['VENV_BIN_PATH'] = venv_path
16   -app.config['JSON_SORT_KEYS'] = False
17   -app.config['TIMEZONE'] = pytz.timezone('Europe/Kiev')
18   -app.config['SECRET_KEY'] = 'JH&INH987gFDHdsagh&8dwbjdw8ckw'
19   -app.config['DOMAIN'] = 'http://127.0.0.1:5001/'
20   -app.config['DEFAULT_LANGUAGE'] = 'en'
21   -app.config['CURRENT_LANGUAGE'] = ''
22   -app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'languages;components/k2test/k2test/languages'
  9 +app.config['SECRET_KEY'] = k2.secret_key
  10 +app.config.from_object(k2)
23 11  
24   -# setting flask app
25   -init_db(app)
  12 +# init db
  13 +k2().init_db(app)
26 14 CORS(app)
  15 +
  16 +#translate
  17 +k2.load_babel_translation_directories()
  18 +app.config['BABEL_TRANSLATION_DIRECTORIES'] = k2.babel_translation_directories
27 19 babel = Babel(app)
  20 +babel.init_app(app, locale_selector=k2.get_locale)
28 21  
29 22 # flask routing
30 23 from routes import *
  24 +
31 25 if __name__ == '__main__':
32 26 app.run(debug=True, port=5000)
1 1 from flask import Flask
2 2 #app = Flask(__name__)
3 3 from main import app, babel
  4 +from k2.k2inst import components_bp
  5 +app.register_blueprint(components_bp)
  6 +
  7 +from components.k2test.k2test.views import k2test
  8 +app.register_blueprint(k2test, url_prefix='/k2test')
templates/dashboard.html
... ... @@ -32,6 +32,7 @@
32 32 <p> <a href="/logout">вихід</a></p>
33 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>
34 34 {{language}}
  35 +{{lang_d}}
35 36  
36 37 <h2>{{ _('Installed components') }}</h2>
37 38  
... ... @@ -130,7 +131,7 @@
130 131 <div>
131 132 <h2>{{ component.name|title }}</h2>
132 133 <p>{{ component.description }}</p>
133   - <p>ВЕРСІЯ {{ component.version }}</p>
  134 + <p>ВЕРСІЯ {{ component.latest_version }}</p>
134 135 {% if component.name in components_names %}
135 136 <button type="button" class="btn btn-success">Installed</button>
136 137 {% else %}