permission system

jwt auth
added deleted field all models
encrypyed field logging disabled
remotes/1725865088694522691/master
Mustafa Yontar 4 years ago
parent 0a98495731
commit 4f3e40a3d2
  1. 1
      .gitignore
  2. 92
      internal_lib/AuthMethots.py
  3. 13
      internal_lib/EncryptedField.py
  4. 42
      internal_lib/permission_parser.py
  5. 57
      main.py
  6. 1
      models/Account.py
  7. 2
      models/File.py
  8. 5
      models/Group.py
  9. 1
      models/Payment.py
  10. 13
      models/Union.py
  11. 27
      models/User.py
  12. 2
      restapi

1
.gitignore vendored

@ -24,3 +24,4 @@ var/
*test.py
trash
mongo_data_dir/*
.directory

@ -0,0 +1,92 @@
from flask import request
from flask_jwt_extended.exceptions import NoAuthorizationError
from flask_jwt_extended.utils import verify_token_claims
from flask_jwt_extended.view_decorators import _decode_jwt_from_request
from werkzeug.exceptions import Unauthorized
from internal_lib.permission_parser import parse_permission, control_permission, is_admin
from models.User import User
from restapi.BaseAuthModel import BaseAuth
class AuthApi(BaseAuth):
def authorized(self):
""
class AuthJWT(BaseAuth):
user = None
def authorized(self):
try:
jwt_data, jwt_header = _decode_jwt_from_request(request_type='access')
verify_token_claims(jwt_data)
self.user = User.objects.get(id=jwt_data['identity'])
except Exception as e:
self.set_error(e)
return False
return True
def has_model_delete_permission(self, obj, model):
if self.user is None:
self.authorized()
if model.__name__.lower() == "union":
return False, obj
if control_permission(self.user.user_group, model.__name__.lower(), "delete", str(obj.id),
str(self.user.union)):
return True, obj
else:
return False, obj
def has_model_update_permission(self, obj, update: dict):
model = obj.__class__.__name__.lower()
if self.user is None:
self.authorized()
if update.get('id') or update.get('pk'):
return False, update
if not is_admin(self.user.user_group) and update.get('union'):
return False, update
if control_permission(self.user.user_group, model, "update", str(obj.id),
str(self.user.union.id)):
return True, update
return False, update
def has_model_read_permission(self, qs):
from flask import current_app
if self.user is None:
self.authorized()
unions = []
has_read = False
for right in self.user.user_group.rights:
permission = parse_permission(right)
current_app.logger.info(permission)
if permission.get('read'):
has_read = True
unions.append(permission.get('union'))
if has_read:
if qs._collection.name == "union":
qs = qs.filter(id__in=unions, deleted=False)
else:
qs = qs.filter(union__in=unions, deleted=False)
else:
raise Unauthorized()
return qs
def has_model_write_permission(self, obj):
model = obj.__class__.__name__.lower()
if self.user is None:
self.authorized()
obj.union = self.user.union.id
if control_permission(self.user.user_group, model, "write", str(obj.id),
str(self.user.union.id)):
return True, obj
return False, obj

@ -18,13 +18,10 @@ class EncryptedStringField(BaseField):
super().__init__(**kwargs)
def __get__(self, instance, owner):
from flask import current_app as app
app.logger.error(self.name)
import binascii
if instance:
value = instance._data.get(self.name)
if value:
app.logger.error(value)
encryptor = PKCS1_OAEP.new(self.keyPair)
return encryptor.decrypt(binascii.unhexlify(value)).decode("utf-8")
else:
@ -33,13 +30,6 @@ class EncryptedStringField(BaseField):
def __set__(self, instance, value):
super().__set__(instance, value)
if value is not None:
from flask import current_app as app
app.logger.error(self.name)
app.logger.error(instance._data)
app.logger.error("data : {} ".format(value))
print(self.name)
print(instance._data)
print(value)
key = self.name
try:
encryptor = PKCS1_OAEP.new(self.keyPair.publickey())
@ -58,8 +48,5 @@ class EncryptedStringField(BaseField):
pass
return value
def lookup_member(self, member_name):
return None
def prepare_query_value(self, op, value):
return super().prepare_query_value(op, value)

@ -46,39 +46,27 @@ def parse_permission(string):
}
def control_permission(group, module, perm_type, itemid, unionid):
def is_admin(group):
for right_string in group.rights:
right = parse_permission(right_string.strip())
print(right, right_string, group, perm_type)
if right.get('module') in ["*", module]:
return True
elif right.get('union') in ['*', unionid]:
return True
elif right.get(perm_type):
return True
elif right.get('item_id') in ['*', itemid]:
return True
elif right.get('module') in ["*", module] and right.get('union') in ['*', unionid] and right.get(
perm_type) and right.get('item_id') in ['*', itemid]:
if right.get('union') == "*":
return True
return False
def control_permission(group, module, perm_type, itemid, unionid):
has_perm = False
from flask import current_app
def read_permission(module, qs):
union_list = []
for right_string in current_user.group.rights:
right = parse_permission(right_string)
if right.get('module') in [module, '*']:
if right.get('read'):
if right.get('union') != "*":
union_list.append(right.get('union'))
if len(union_list) > 0:
if module == 'union':
qs.filter(id__in=union_list, deleted=False)
else:
qs.filter(union__in=union_list, deleted=False)
return qs
for right_string in group.rights:
right = parse_permission(right_string.strip())
if module == "union" and perm_type == "write" and right.get("union") != "*":
has_perm = False
current_app.logger.info("short shut")
elif right.get('module') in ["*", module] and right.get('union') in ['*', unionid] and right.get(
perm_type) and right.get('item_id') in ['*', itemid]:
current_app.logger.info("long shut")
has_perm = True
return has_perm
def has_permission(module, obj, reqtype, oid):

@ -1,27 +1,78 @@
from flask import Flask
from flask import Flask, request, jsonify
from flask_admin.contrib.mongoengine import ModelView
from flask_jwt_extended import JWTManager, create_access_token
from mongoengine import connect
from werkzeug.security import check_password_hash
from internal_lib.AuthMethots import AuthJWT
from models.Group import Group
from models.Union import Union
from models.User import User
from restapi import MongoApi
from flask_admin import Admin
"""
Mongodb connection string
"""
connect('adunatio', host='mongo', username="xcoder", password="4dun4710", authentication_source='admin')
app = Flask(__name__)
app.secret_key = "secret_key+secret_key"
api = MongoApi(app)
app.config["JWT_TOKEN_LOCATION"] = "headers"
app.config["JWT_HEADER_NAME"] = "Adunation_Session_Token"
app.config["JWT_HEADER_TYPE"] = "Bearer"
"""
flask jwt extended register
"""
jwt = JWTManager(app)
"""
flask mongorester register
"""
api = MongoApi(app, authentication_methods=[AuthJWT])
api.register_model(User, uri="/api/user")
api.register_model(Union, uri="/api/union")
"""
flask admin register
"""
adm = Admin(app)
adm.add_view(ModelView(User))
adm.add_view(ModelView(Union))
adm.add_view(ModelView(Group))
"""
login function
"""
@app.route('/auth/login', methods=['POST'])
def login():
if not request.is_json:
return jsonify({"message": "Missing JSON in request", "error": "parameter_error", "status":False}), 400
username = request.json.get('username', None)
password = request.json.get('password', None)
if not username:
return jsonify({"message": "Missing username parameter", "error": "parameter_error", "status":False}), 400
if not password:
return jsonify({"message": "Missing password parameter", "error": "parameter_error", "status":False}), 400
try:
user = User.objects.get(username=username)
except Exception as e:
app.logger.error(e)
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status": False}), 401
if not check_password_hash(user.password,password):
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status":False}), 401
# Identity can be any data that is json serializable
access_token = create_access_token(identity=str(user.id))
return jsonify(access_token=access_token,status=True), 200
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, debug=True)

@ -8,3 +8,4 @@ class Account(Document):
bank = StringField()
number = StringField()
quick_number = StringField()
deleted = BooleanField(default=False)

@ -7,9 +7,11 @@ class Directory(Document):
path = StringField()
can_see_user_group = ReferenceField(Group)
is_system = BooleanField(default=False)
deleted = BooleanField(default=False)
class File(Document):
path = ReferenceField(Directory)
file = FileField()
description = StringField()
deleted = BooleanField(default=False)

@ -7,6 +7,7 @@ class Group(Document):
union = ReferenceField(Union)
name = StringField()
rights = ListField(StringField())
deleted = BooleanField(default=False)
def __unicode__(self):
return "{} {}".format(self.union.name,self.name)
@ -14,4 +15,8 @@ class Group(Document):
class PaymentGroup(Document):
union = ReferenceField(Union)
name = StringField()
deleted = BooleanField(default=False)
discount_percent = IntField()
def __unicode__(self):
return "{} {}".format(self.union.name, self.name)

@ -17,6 +17,7 @@ class Payments(Document):
regular = BooleanField(default=False)
regular_type = StringField(choices=('Weekly','Monthly','Yearly'))
price = DecimalField()
deleted = BooleanField(default=False)
description = StringField()
reference_no = StringField()
file = ReferenceField(File)

@ -20,13 +20,17 @@ class Union(Document):
("-name"),
]
}
name = StringField()
name = StringField(required=True)
logo = ImageField(thumbnail_size=(120, 120))
description = StringField()
legal_registration_number = StringField()
legal_registration_number = StringField(required=True)
headquarter = StringField()
email = StringField()
email = StringField(required=True)
api_key = ListField(EmbeddedDocumentField(ApiKey))
deleted = BooleanField(default=False)
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
super(Union, self).save(*args, **kwargs)
@ -42,8 +46,9 @@ class Union(Document):
user.username = "{}@root".format(self.legal_registration_number)
user.user_group = group
user.union = self
from flask import current_app
password = ''.join(choices(ascii_letters + digits, k=10))
print("New union password : {}".format(password))
current_app.logger.info("New union password : {}".format(password))
user.password = generate_password_hash(password)
# TODO: send password via mail or sms or nothing
user.save()

@ -1,5 +1,6 @@
from flask_jwt_extended import current_user
from mongoengine import *
from werkzeug.security import generate_password_hash
from internal_lib.EncryptedField import EncryptedStringField
from models.EmbededDocuments import Descriptions
@ -23,28 +24,29 @@ class User(Document):
'with_sub_docs': True,
"quyery": {},
'ignore_fields': ['password'],
'methods': [Methods.Get, Methods.List, Methods.Create],
'methods': [Methods.Get, Methods.List, Methods.Create, Methods.Update],
"indexes": [
('union'),
('username', 'union'),
('accept_date')
]
}
deleted = BooleanField(default=False)
union = ReferenceField(Union)
member_no = LongField()
username = StringField()
username = StringField(required=True)
photo = ImageField(thumbnail_size=(85, 120))
password = StringField()
name = StringField()
password = StringField(required=True)
name = StringField(required=True)
middle_name = StringField()
last_name = StringField()
gov_id = EncryptedStringField()
last_name = StringField(required=True)
gov_id = EncryptedStringField(required=True)
mother_name = EncryptedStringField()
father_name = EncryptedStringField()
email = EncryptedStringField()
place_of_birth = EncryptedStringField()
date_of_birth = EncryptedStringField()
telephone = EncryptedStringField()
date_of_birth = EncryptedStringField(required=True)
telephone = EncryptedStringField(required=True)
job = StringField()
address = EncryptedStringField()
accept_date = DateTimeField()
@ -109,7 +111,7 @@ class User(Document):
'Transsexual Person',
'Transsexual Woman',
'Two-Spirit'
))
),required=True)
custom_fields = ListField(EmbeddedDocumentField(UserCustomFields))
user_group = ReferenceField(Group)
payment_group = ReferenceField(PaymentGroup)
@ -121,7 +123,10 @@ class User(Document):
return str(self.id)
def save(self, *args, **kwargs):
if current_user:
self.union = current_user.union
if self.union:
self.member_no = User.objects.filter(union=self.union).count()
self.password = generate_password_hash(self.password)
super(User, self).save(*args, **kwargs)

@ -1 +1 @@
Subproject commit b4fb234e4781092e5d8765dae527a198ab0567aa
Subproject commit 70be57ef3681f723271cc05edcbc055417a578d8
Loading…
Cancel
Save