diff --git a/components/adm/README.md b/components/adm/README.md
new file mode 100644
index 0000000..b6e0be0
--- /dev/null
+++ b/components/adm/README.md
@@ -0,0 +1,45 @@
+# main.py
+
+from components.adm.adm.views import adm
+from components.test.test.views import test
+
+app.register_blueprint(adm, url_prefix='/adm')
+
+cd components/adm
+pip install -r requirements.txt
+
+
+endpoint "http://127.0.0.1:5000/adm/register"
+dictionary to register in such way
+{
+ "login": "xxx",
+ "password": "xxx",
+ "name": "xxx",
+ "email": "xxx"
+}
+
+
+endpoint "http://127.0.0.1:5000/adm/login"
+dictionary to login in such way
+{
+ "login":"xxx",
+ "password":"xxx"
+}
+
+endpoint http://127.0.0.1:5000/adm/changePassword
+dictionary to changePassword in such way
+{
+ "old_password":"xxx",
+ "new_password": "xxx",
+ "re_new_password": "xxx"
+}
+endpoint http://127.0.0.1:5000/adm/newUser
+{
+ "login": "xxx",
+ "password": "xxx",
+ "name": "xxx",
+ "email": "xxx",
+ "phone": "xxx",
+ "repassword": "xxx"
+
+}
\ No newline at end of file
diff --git a/components/adm/__init__.py b/components/adm/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/components/adm/__pycache__/__init__.cpython-310.pyc b/components/adm/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..afbe1a2ab049fb58ba60772d1a4cbbe477696acd
GIT binary patch
literal 144
zcmd1j<>g`kf`ls_DIoeWh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6vQKO;XkRlhPZ
zFHt|+s3nEn<>c_`t=4F<|$LkeT-r}&y%}*)KNwotRR?Gw>
GSQr3d+aM(X
literal 0
HcmV?d00001
diff --git a/components/adm/__pycache__/__init__.cpython-311.pyc b/components/adm/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..27cdf7de3373c51133558684e965fb2ada9f68aa
GIT binary patch
literal 176
zcmZ3^%ge<81nPWcDIoeWh=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09t%UM4oKQ~oB
zKPNT2I597!NI#$`KPxr4q*&j`z{ptN+sHX5zcj@)C_q0sKer%1FEtM+m6(#NA0MBY
tmst`YuUAm{i^C>2KczG$)vkyYXeP+kVtyd;ftit!@dE>lC}IYR0RZ*0DJK8`
literal 0
HcmV?d00001
diff --git a/components/adm/adm/.idea/.gitignore b/components/adm/adm/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/components/adm/adm/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/components/adm/adm/.idea/adm.iml b/components/adm/adm/.idea/adm.iml
new file mode 100644
index 0000000..6c86ab2
--- /dev/null
+++ b/components/adm/adm/.idea/adm.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/adm/adm/.idea/inspectionProfiles/Project_Default.xml b/components/adm/adm/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..62102dd
--- /dev/null
+++ b/components/adm/adm/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/adm/adm/.idea/inspectionProfiles/profiles_settings.xml b/components/adm/adm/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/components/adm/adm/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/adm/adm/.idea/misc.xml b/components/adm/adm/.idea/misc.xml
new file mode 100644
index 0000000..dc9ea49
--- /dev/null
+++ b/components/adm/adm/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/components/adm/adm/.idea/modules.xml b/components/adm/adm/.idea/modules.xml
new file mode 100644
index 0000000..52b9a11
--- /dev/null
+++ b/components/adm/adm/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/adm/adm/.idea/vcs.xml b/components/adm/adm/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/components/adm/adm/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/adm/adm/__init__.py b/components/adm/adm/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/components/adm/adm/__pycache__/__init__.cpython-310.pyc b/components/adm/adm/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e2ab797d9944c811b990c246aeb45d593d05e011
GIT binary patch
literal 148
zcmd1j<>g`kg2XEwDIoeWh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6vUKO;XkRlhPZ
zFHt|+s3nEnlgl8K**n{
zY!4rluVLy2fD=w7$?(f0ty#uuFY{_Y^C{Xq8Ps7GI@y;|9cQtV1KFvQEO9cG-K-0~
zq3qTDY(R+!Z%MZEE#VQ5?+A~@&aIaXIXxk1=N`@^$Ejz-m#v)Djg7u*j2H=J!xN*b
zW|UGp?DopiCvQOvnN~ju9E|2@9~gFcO>ic
z0q^kSj%EX~!@In9M_{)h??d)GHkusGv{3p740o!kx={0cBIfr;5Y_#!2zvk}1=tJ*
z0`!r54^y857_y{>8E@&YVDDwHA}hKKS7br*XhD}Trz;9_2mPGRV13&waaPZHb)D=x
zx##4-$$d^B;_%o8vK>{8ji-gym#yN~Z;D#jK-5JgZ7?0TjYtPJ8W(yjt5fUM{Dt+j
zQP!W$DsBVB&uu80vgN{d#^Q=sBcY9ruoOACcq3ud05VfM2t$Njghv1=v%VJc%!ZT8
zLXGtAM75f79I3W7n@`!+QwXXt`mo@&n>8FQ^}%#*<2>283aSlDW^{${B!Tdk9L|@24mSa)R
zElK;9O^$3Lu8e4O)i&BPerh8PcN;VtT+D=;+wiQCMyM@nJcd{m-VlXtQBMG@hXf3)
zS4zF*`57+x$guxbtyj#<7#mW;gYpr$X(Zf$`IONwsPBjWgw$u(dz%t&yC0`iJqPb}
z7m0)yAG0=>WQOu=NxxWQ~1v2Ek17^GlPv?s35#fo;s8oQ|=M)YvH-IA;~(K`9#iZ{Rt1
dLHu71HvV#5$glAI(^!U>>}^tjZ|Lo@e*rFLs`3B;
literal 0
HcmV?d00001
diff --git a/components/adm/adm/__pycache__/views.cpython-310.pyc b/components/adm/adm/__pycache__/views.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..476e19f29996f431487ea9aa3f4506d11e3dee23
GIT binary patch
literal 3895
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
literal 0
HcmV?d00001
diff --git a/components/adm/adm/__pycache__/views.cpython-311.pyc b/components/adm/adm/__pycache__/views.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1fd4961259cfcdff8899daa48ed2e44b133afdaf
GIT binary patch
literal 1119
zcmZ`%%}X0W6rb6TY?384ND4M77)lF`2UkoD7D5lL(nCR{?V*Iil4iyvx*uV7Q>#SC
zL3;M4mqJcf(QE&YjRcedLFlQs6mOpTX4`xn`j~k;^WK}^{^tGWdm<4>V659BzJ$O)_%9L3$vpPbYSIR)J3iMoJ=dvk?C>c@
z9YUGuQ@df6eVW5O=GEM7v&!m(%VlC$@DLCo71lD$TOZsZ^2c%ni*5{TlG`3`q0U%#
zP=%1Mjn+gu2E4N&=Hw2e7KYo%Ydj9D%to1&ZI36atm*g_*YTNac{zm%c06jDPT8iW
z$)_2u);%9?_-Sx?7J-tS1ea?xcxr?-s_+EWZ1!%&sJS*ZT#IgbWrr|how=K|;(Ny8
z!eZWdv-rw#n`HIvx>0fMhU-uVQUDmv&vm-(%{O+~Jpc=x_^($0*GAWw$DNNqmb;l^
zFH;PZnSK9{1omJMj8e;Fp>+mMN%-4L|I>lTOt;}I2
zv}gChc|xHqn-crfz=@rg2G>S6`gD8cT2CJpPe`EWyL!H-=L03rl8|1@>0I5g%HCEe
z6%$-TX#Qx_#ChNm&aseqkfC%;ha)@zB_qYc{&JPMO^{k}Iz{2%LXvmUqV1BVMPIOo
zkP_^@18{vAV|;~{g8z>zv>Z&1o8*Io*wK^DOgA~#OU|_ueMQ6BJ{r1dBu!o7)CEo*
hd^k}%+W}5>vC+duUy|^%J_7e!M$*DWBn*d){{S6C2-^Sv
literal 0
HcmV?d00001
diff --git a/components/adm/adm/models.py b/components/adm/adm/models.py
new file mode 100644
index 0000000..d765f05
--- /dev/null
+++ b/components/adm/adm/models.py
@@ -0,0 +1,43 @@
+import uuid
+from sqlalchemy import Column, Integer, String
+from sqlalchemy.ext.declarative import declarative_base
+from flask_jwt_extended import create_access_token
+from datetime import timedelta
+import hashlib
+from flask import current_app as k2
+
+
+Base = declarative_base()
+
+class k2users(Base):
+ __tablename__ = 'k2users'
+ user_id = Column(Integer, primary_key=True)
+ login = Column(String(50))
+ name = Column(String(50))
+ email = Column(String(150))
+ password = Column(String(50))
+ phone = Column(String(20))
+
+ def __init__(self, **kwargs):
+ self.user_id = hashlib.md5(str(uuid.uuid4()).encode()).hexdigest()
+ self.login = kwargs.get('login')
+ self.password = hashlib.md5(kwargs.get('password').encode()).hexdigest()
+ self.name = kwargs.get('name')
+ self.email = kwargs.get('email')
+ self.phone = kwargs.get('phone')
+
+ def get_token(self, expire_time=24):
+ expires_delta = timedelta(expire_time)
+ token = create_access_token(identity=self.user_id, expires_delta=expires_delta)
+ return token
+
+ @classmethod
+ def authenticate(cls, login, password):
+ session = k2.extensions['sqlalchemy'].db.session
+ user = ''
+ try:
+ user = session.query(cls).filter(cls.login == login).filter(cls.password == hashlib.md5(password.encode()).hexdigest()).one()
+ except:
+ user = None
+
+ return user
\ No newline at end of file
diff --git a/components/adm/adm/views.py b/components/adm/adm/views.py
new file mode 100644
index 0000000..f3d0640
--- /dev/null
+++ b/components/adm/adm/views.py
@@ -0,0 +1,136 @@
+import hashlib
+import uuid
+from flask import Blueprint, request, jsonify
+from flask import current_app as k2
+from flask_jwt_extended import jwt_required, get_jwt_identity
+# from flask_sqlalchemy import session
+# from sqlalchemy.orm import sessionmaker
+# from k2.k2inst import Component
+
+from .models import k2users
+
+
+adm = Blueprint('adm', __name__, template_folder='templates', static_folder='static', static_url_path='/adm')
+
+
+@adm.route('/register', methods=["POST"])
+def register():
+ params = request.json
+ session = k2.extensions['sqlalchemy'].db.session
+ try:
+ user = k2users(**params)
+ session.add(user)
+ session.commit()
+ token = user.get_token()
+ return {'access_token': token}
+ except:
+ return jsonify({'error': 'Unauthorized'}), 401
+
+
+@adm.route('/login', methods=["POST"])
+def login():
+ params = request.json
+ login = params.get('login')
+ password = params.get('password')
+ user = k2users.authenticate(login, password)
+ if user:
+ token = user.get_token()
+ return {'access_token': token}
+ else:
+ return jsonify({'error': 'Unauthorized'}), 401
+
+
+@adm.route('/logout', methods=["GET"])
+@jwt_required()
+def logout():
+ response = {
+ 'message': 'Logged out successfully'
+ }
+ return jsonify(response)
+
+
+@adm.route('/users', methods=["GET"])
+@jwt_required()
+def grid_users():
+ return jsonify({"data": "users"})
+
+
+@adm.route('/roles', methods=["GET"])
+@jwt_required()
+def grid_roles():
+ return jsonify({"data": "roles"})
+
+
+@adm.route('/usersclients', methods=["GET"])
+@jwt_required()
+def users_clients():
+ return jsonify({"data": "roles"})
+
+@adm.route('/menuaaccess', methods=["GET"])
+@jwt_required()
+def menu_aaccess():
+ return jsonify({"data": "roles"})
+
+
+@adm.route('/newUser', methods=["GET", "POST"])
+@jwt_required()
+def newUser():
+ session = k2.extensions['sqlalchemy'].db.session
+ exist = session.query(k2users).filter_by(login=request.json['login']).first()
+ if not exist:
+ res = k2users(
+ user_id=hashlib.md5(str(uuid.uuid4()).encode()).hexdigest(),
+ login=request.json['login'],
+ name=request.json['name'],
+ email=request.json['email'],
+ password=hashlib.md5(request.json['password'].encode()).hexdigest(),
+ phone=request.json['phone'])
+ if res:
+ session.add(res)
+ session.commit()
+ return jsonify({'status': 'ok'})
+ else:
+ return jsonify({'error': 'Such user exist'}), 404
+
+
+@adm.route('/changePassword', methods=["POST"])
+@jwt_required()
+def changePassword():
+ session = k2.extensions['sqlalchemy'].db.session
+ current_user = get_jwt_identity()
+ user = session.query(k2users).filter_by(user_id=current_user).first()
+ if user.password == hashlib.md5(request.json['old_password'].encode()).hexdigest():
+ if request.json['new_password'] == request.json['re_new_password']:
+ user.password = hashlib.md5(request.json['new_password'].encode()).hexdigest()
+ session.commit()
+ else:
+ return jsonify({'error': 'Пароль не найден в базе'}), 404
+ else:
+ return jsonify({'error': 'Пароль не совпвдает'}), 404
+ return jsonify({'status': 'ok'})
+
+
+@adm.route('/menu-items')
+def menu_items():
+ menu = [
+ {"heading": 'APPS & PAGES'},
+ {
+ "title": 'Адміністрування сайту',
+
+ "icon": {"icon": 'mdi mdi-database'},
+ "children": [
+ {'title': 'Зміна паролю', 'to': 'adm-changePassword'},
+ {'title': 'Новий користувач', 'to': 'adm-newUser'},
+ {'title': 'Користувачі', 'to': 'adm-users'},
+ {'title': 'Користувачі клієнти', 'to': 'adm-usersclients'},
+ {'title': 'Права', 'to': 'adm-roles'},
+ {'title': 'Доступ до меню', 'to': 'adm-menuaaccess'},
+ ],
+ }]
+
+ return menu
+
+
+
+
+
diff --git a/components/adm/setup.py b/components/adm/setup.py
new file mode 100644
index 0000000..8370eae
--- /dev/null
+++ b/components/adm/setup.py
@@ -0,0 +1,15 @@
+from setuptools import setup
+
+setup(
+ name='adm',
+ version='1.0.0',
+ description='Description of my project',
+ author='Your Name',
+ author_email='yourname@example.com',
+ keywords="adm, k2",
+ python_requires=">=3.7, <=3.11.2",
+ packages=['adm'],
+ package_data={ # Optional
+ },
+ install_requires=[""],
+)
\ No newline at end of file