Compare commits

...

3 Commits

  1. 3
      .gitignore
  2. 5
      internal_lib/EncryptedField.py
  3. 22
      main.py
  4. 8
      models/Group.py
  5. 12
      models/Payment.py
  6. 7
      models/Union.py
  7. 4
      models/User.py
  8. 0
      scripts/__init__.py
  9. 331
      scripts/generate_flutter_forms.py
  10. 212
      scripts/generate_flutter_model.py

3
.gitignore vendored

@ -25,4 +25,5 @@ var/
trash
mongo_data_dir/*
.directory
.env
.env
flutter_out/

@ -13,7 +13,10 @@ class EncryptedStringField(BaseField):
def __init__(self, **kwargs):
import os
priv_key = os.environ.get('ADUNATIO_PRIV_KEY')
self.keyPair = RSA.importKey(open(priv_key).read())
try:
self.keyPair = RSA.importKey(open(priv_key).read())
except:
pass
super().__init__(**kwargs)

@ -2,8 +2,12 @@ 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 werkzeug.security import check_password_hash ,generate_password_hash
from internal_lib.AuthMethots import AuthJWT
from models.Account import Account
from models.Group import Group, PaymentGroup
from models.Payment import Payments
from os import environ, path
from dotenv import load_dotenv
@ -45,8 +49,12 @@ 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")
api.register_model(User, uri="/api/user/")
api.register_model(Union, uri="/api/union/")
api.register_model(Group, uri="/api/group/")
api.register_model(PaymentGroup, uri="/api/payment_group/")
api.register_model(Account, uri="/api/accounts/")
api.register_model(Payments, uri="/api/payments/")
"""
flask admin register
@ -80,7 +88,13 @@ def login():
app.logger.error(e)
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status": False}), 401
if not check_password_hash(user.password,password):
app.logger.error(password)
app.logger.error(username)
app.logger.error(generate_password_hash(password))
app.logger.error(user.password)
app.logger.error(check_password_hash(pwhash=user.password,password=password))
if check_password_hash(pwhash=user.password,password=password) == False:
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status":False}), 401
# Identity can be any data that is json serializable

@ -5,8 +5,8 @@ from models.Union import Union
class Group(Document):
union = ReferenceField(Union)
name = StringField()
rights = ListField(StringField())
name = StringField(required=True)
rights = ListField(StringField(),required=True)
deleted = BooleanField(default=False)
def __unicode__(self):
return "{} {}".format(self.union.name,self.name)
@ -14,9 +14,9 @@ class Group(Document):
class PaymentGroup(Document):
union = ReferenceField(Union)
name = StringField()
name = StringField(required=True)
deleted = BooleanField(default=False)
discount_percent = IntField()
discount_percent = IntField(required=True)
def __unicode__(self):
return "{} {}".format(self.union.name, self.name)

@ -11,19 +11,17 @@ class Payments(Document):
all payments income and outcome together!
"""
union = ReferenceField(Union)
user = ReferenceField(User)
user = ReferenceField(User, required=True)
income = BooleanField(default=False)
date = DateTimeField()
regular = BooleanField(default=False)
regular_type = StringField(choices=('Weekly','Monthly','Yearly'))
price = DecimalField()
regular_type = StringField(choices=('Weekly', 'Monthly', 'Yearly'))
price = DecimalField(required=True)
deleted = BooleanField(default=False)
description = StringField()
reference_no = StringField()
file = ReferenceField(File)
account = ReferenceField(Account)
account = ReferenceField(Account, required=True)
due_date = DateTimeField()
is_paid = BooleanField(default=False)
is_paid = BooleanField(default=False, required=True)
is_donate = BooleanField(default=False)

@ -20,7 +20,7 @@ class Union(Document):
"indexes": [
('name'),
("-name"),
]
],
}
name = StringField(required=True)
logo = ImageField(thumbnail_size=(120, 120))
@ -55,7 +55,8 @@ class Union(Document):
user.union = self
from flask import current_app
password = ''.join(choices(ascii_letters + digits, k=10))
current_app.logger.info("New union password : {}".format(password))
user.password = generate_password_hash(password)
passhash = generate_password_hash(password,salt_length=20)
current_app.logger.info("New union password : '{}'".format(password))
user.password = passhash
# TODO: send password via mail or sms or nothing
user.save()

@ -29,7 +29,9 @@ class User(Document):
('union'),
('username', 'union'),
('accept_date')
]
],
"auto_generated": ['union','deleted','member_no']
}
deleted = BooleanField(default=False)
union = ReferenceField(Union)

@ -0,0 +1,331 @@
from random import randint, choice
from string import ascii_lowercase
from models.Account import Account
from models.Payment import Payments
from models.User import User
from scripts.generate_flutter_model import build_class
def mainBuilder(classlist):
blist = []
for cls in classlist:
data = build_class(cls, blist)
blist = blist + data[1]
clstypeList = [i.__class__.__name__ for i in blist]
configlistNames = []
for classItem in data[0]:
saveAction = ""
imports = "import 'package:flutter/material.dart';\n"
imports += "import 'package:flutter/services.dart';\n"
imports += "import 'package:dio/dio.dart';\n"
imports += "import 'package:horde/widgets/HorusBox.dart';\n"
imports += "import 'package:dropdown_search/dropdown_search.dart';\n"
imports += "import '../Models.dart';\n"
controller = ""
controllerInit = ""
controllerDispose = ""
textFields = ""
for field in classItem.get('fields'):
if field.get('name') == "id":
continue
if field.get('autogen'):
continue
controller += "\tTextEditingController _{};\n".format(field.get('name'))
controllerInit += "\t\t_{} = new TextEditingController();\n".format(field.get('name'))
controllerDispose += "\t\t_{}.dispose();\n".format(field.get('name'))
req = ""
if field.get('required'):
req = """
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
"""
if field.get("is_class"):
# imports += "import 'package:adunationfe/data/models/{}.dart';\n".format(field.get('class_name'))
if field.get('islist'):
if field.get('embeded') == False:
controller += "\t\tList<{classname}> item{name};\n".format(
classname=field.get('class_name'),
name=field.get('name'))
controllerInit += "\t\t\titem{name} = [];\n".format(name=field.get('name'))
saveAction += "\t\tnew{classname}.{name} = item{name};\n".format(name=field.get('name'),
classname=classItem.get(
'class'))
else:
imports += "import 'Form{}.dart';\n".format(
field.get('class_name'))
if field.get('class_name') not in configlistNames:
clsname = field.get('class_name')
configlistNames.append(field.get('class_name'))
else:
clsname = field.get('class_name') + ''.join(
[choice(ascii_lowercase) for i in range(randint(3, 6))])
while clsname in configlistNames:
clsname = field.get('class_name') + ''.join(
[choice(ascii_lowercase) for i in range(randint(3, 6))])
configlistNames.append(clsname)
saveAction += "\t\tnew{classname}.{name} = item{clist}List;\n".format(clist=clsname,
name=field.get(
'name'),
classname=classItem.get(
'class'))
controller += """
List<{originclass}> item{classname}List = [];
""".format(originclass=field.get("class_name"), classname=clsname)
textFields += """
Padding(padding: EdgeInsets.only(left:40,right: 40),
child: Column(
children: [
Text('{cname} list'),
Column(
children: List.generate(item{clsname}List.length, (index) {{
return HorusBox(
child:
Row(
children: [
Expanded(child: Text(item{clsname}List[index].name)),
GestureDetector(
onTap: () {{
item{clsname}List.removeAt(index);
setState(() {{
}});
}},
child: Icon(Icons.delete),
)
],
)
,
);
}}),
)
],
),
),
ElevatedButton(onPressed: ()
{{
_showMaterialDialog(SingleChildScrollView(child:Container(width:500,height:500,child:new Form{classname}(onSave: ({classname} item) {{
item{clsname}List.add(item);
Navigator.pop(context);
setState(() {{
}});
}}))),"Create {cname}");
}}, child: Text('Add {cname}')),
SizedBox(
height: 15,
),
""".format(classname=field.get('class_name'), cname=field.get('name'), clsname=clsname)
elif field.get("embeded") == False:
controller += "\t\t{classname} item{name};\n".format(classname=field.get('class_name'),
name=field.get('name'))
saveAction += "\t\tnew{classname}.{name} = item{name};\n".format(name=field.get('name'),
classname=classItem.get(
'class'))
controllerInit += "\t\t\titem{name} = {classname}();\n".format(
classname=field.get('class_name'),
name=field.get('name'))
controller += "\t\tList<{classname}> {cname}List = [];".format(
classname=field.get('class_name'), cname=field.get('name'))
controller += """
Future<List<{classname}>> getData{classname}(filter) async {{
print(filter);
var response = await Dio().get(
"${{apiurl}}/{cname}",
queryParameters: {{"{search}__contains": filter}},
);
List<{classname}> models = [];
response.data.forEach((element) {{
{classname} cn = {classname}();
cn.name = element['{search}'];
models.add(cn);
}});
return models;
}}
""".format(classname=field.get('class_name'), cname=field.get('name'),
search=field.get('search_field'))
textFields += """
DropdownSearch<{classname}>(
mode: Mode.BOTTOM_SHEET,
showSearchBox: true,
onFind: (String filter) => getData{classname}(filter),
items: [],
itemAsString: ({classname} u) => u.{search},
isFilteredOnline: true,
autoValidateMode: AutovalidateMode.onUserInteraction,
validator: ({classname} u) =>
u == null ? "field is required " : null,
hint: "{cname} in menu mode",
onChanged: ({classname} selected) {{
item{cname} = selected;
setState(() {{
}});
}}),
SizedBox(
height: 15,
),
""".format(classname=field.get('class_name'), cname=field.get('name'),
search=field.get('search_field'))
elif field.get("embeded"):
imports += "import 'Form{}.dart';\n".format(
field.get('class_name'))
saveAction += "\t\tif(!_key{classname}.currentState.build{classname}()) return false;\n".format(
classname=field.get('class_name'))
saveAction += "\t\tnew{cname}.{name} = _key{classname}.currentState.new{classname};\n".format(
classname=field.get('class_name'), name=field.get('name'), cname=classItem.get('class'))
textFields += "Form{classname}(key:_key{classname}),".format(classname=field.get('class_name'))
controller += "\tGlobalKey<Form{}State> _key{} = GlobalKey();\n".format(field.get('class_name'),
field.get('class_name'))
elif field.get('choices'):
saveAction += "\t\tnew{classname}.{name} = _{name}.text;\n".format(name=field.get('name'),
classname=classItem.get('class'))
imports += "import 'package:dropdown_search/dropdown_search.dart';\n"
textFields += """
DropdownSearch<String>(
mode: Mode.BOTTOM_SHEET,
showClearButton: true,
showSearchBox: true,
label: '{name}',
showSelectedItem: true,
items: ['{items}'],
hint: "country in menu mode",
onChanged: print,
selectedItem: "")
,
SizedBox(
height: 15,
),
""".format(items="','".join(field.get('choices')), name=field.get('name'))
elif field.get('type') == 'String':
saveAction += "\t\tnew{classname}.{name} = _{name}.text;\n".format(name=field.get('name'),
classname=classItem.get('class'))
textFields += """
new TextFormField(
decoration: new InputDecoration(labelText: "Enter your {name}"),
controller: _{name},
{req}
),
SizedBox(
height: 15,
),
""".format(name=field.get('name'), req=req)
elif field.get('type') == 'int':
saveAction += "\t\tnew{classname}.{name} = int.tryParse(_{name}.text);\n".format(
name=field.get('name'),
classname=classItem.get('class'))
textFields += """
new TextFormField(
decoration: new InputDecoration(labelText: "Enter your {name}"),
controller: _{name},
keyboardType: TextInputType.number,
inputFormatters: < TextInputFormatter > [
FilteringTextInputFormatter.digitsOnly
],
{req}
),
SizedBox(
height: 15,
),
""".format(name=field.get('name'), req=req)
# elif field.get('is_class'):
# print(field)
# # exit()
cls_text = """
{imports}
class Form{classname} extends StatefulWidget {{
final Function onSave;
const Form{classname}({{Key key, this.onSave}}) : super(key: key);
@override
Form{classname}State createState() => Form{classname}State();
}}
class Form{classname}State extends State<Form{classname}> {{
{controller}
var apiurl = "";
{classname} new{classname} = new {classname}();
bool build{classname}() {{
if (_{classname}.currentState.validate()) {{
{saveact}
widget.onSave(new{classname});
return true;
}}
return false;
}}
_showMaterialDialog(content, title) {{
showDialog(
context: context,
builder: (_) => new AlertDialog(
title: new Text(title),
content: content,
));
}}
final _{classname} = GlobalKey<FormState>();
@override
void initState() {{
{initdata}
super.initState();
}}
@override
void dispose() {{
{dispose}
super.dispose();
}}
@override
Widget build(BuildContext context) {{
return new Form(
key:_{classname},
child:new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
{textfield}
Row(
children: [
widget.onSave !=null ? ElevatedButton(
child: Text('Save'),
onPressed: () {{
build{classname}();
}},
): Center()
],
)
])
);
}}
}}
""".format(imports=imports, classname=classItem.get('class'), controller=controller,
initdata=controllerInit, dispose=controllerDispose, textfield=textFields, saveact=saveAction)
f = open("flutter_out/Form{}.dart".format(classItem.get('class')), "w+")
f.write(cls_text)
f.close()
import os
os.chdir('../')
print(os.getcwd())
mainBuilder([User, Payments, Account])
os.system("flutter format flutter_out/")

@ -0,0 +1,212 @@
import mongoengine
import os
from models.Account import Account
from models.Payment import Payments
from models.User import *
from mongoengine import fields
types = {
mongoengine.fields.StringField: "String",
IntField: 'int',
BooleanField: 'bool',
FloatField: 'Float',
DictField: 'Map<String,dynamic>'
}
def to_camel_case(snake_str):
components = snake_str.split('_')
# We capitalize the first letter of each component except the first one
# with the 'title' method and join them together.
return components[0] + ''.join(x.title() for x in components[1:])
def buildReferenceField(field_object, builded):
if isinstance(field_object, (ReferenceField, EmbeddedDocumentField)):
if field_object.document_type not in builded:
builded.append(field_object.document_type)
return build_class(field_object.document_type, builded)
return None, builded
else:
return None, builded
def buildFields(field_object):
type = ""
if isinstance(field_object, mongoengine.fields.LongField):
type = "long"
elif isinstance(field_object, EncryptedStringField):
type = "String"
elif isinstance(field_object, fields.ImageField):
type = "String"
elif isinstance(field_object, EncryptedStringField):
type = "String"
elif isinstance(field_object, StringField):
type = "String"
elif isinstance(field_object, ObjectIdField):
type = "String"
elif isinstance(field_object, DateTimeField):
type = "DateTime"
elif isinstance(field_object, IntField):
type = "int"
elif isinstance(field_object, BooleanField):
type = "bool"
elif isinstance(field_object, FloatField):
type = "double"
elif isinstance(field_object, DictField):
type = "Map<String,dynamic>"
elif isinstance(field_object, DynamicField):
type = "dynamic"
else:
type = "String"
return type
def build_class(mongoClass, builded):
if builded is None:
builded = []
mClass = mongoClass
builded.append(mClass)
rClass = mongoClass()
builded.append(rClass)
class_list = []
field_list = []
for field in rClass._fields_ordered:
field_object = getattr(mClass, field)
ignore_fields = mClass._meta.get('ignore_fields')
autogen_fields = mClass._meta.get('auto_generated')
if not ignore_fields:
ignore_fields = []
if not autogen_fields:
autogen_fields = []
if isinstance(field_object, (ReferenceField, EmbeddedDocumentField)):
_, builded = buildReferenceField(field_object, builded)
if _ is not None:
class_list = class_list + list(_)
pn = field_object.document_type()
if field not in ignore_fields:
field_list.append(
{"type": pn._class_name, "origin_name": field, "name": to_camel_case(field), "islist": False,
"is_class": True, "required":field_object.required, "class_name": pn._class_name, "autogen": field in autogen_fields})
elif isinstance(field_object, ListField):
if isinstance(field_object.field, (ReferenceField, EmbeddedDocumentField)):
_, builded = buildReferenceField(field_object.field, builded)
if _ is not None:
class_list = class_list + list(_)
pn = field_object.field.document_type()
if field not in ignore_fields:
field_list.append(
{"type": "List<{}>".format(pn._class_name), "origin_name": field, "name": to_camel_case(field),
"islist": True, "is_class": True, "required":field_object.required, "class_name": pn._class_name, "autogen": field in autogen_fields})
else:
type = buildFields(field_object.field)
if field not in ignore_fields:
field_list.append({"type": "List<{}>".format(type), "name": to_camel_case(field), "origin_name": field,
"islist": True, "originType": field_object.field, "required":field_object.required, "autogen": field in autogen_fields,"choices":field_object.field.choices})
else:
type = buildFields(field_object)
if field not in ignore_fields:
chc = None
req = False
if field_object is not None:
chc = field_object.choices
req = field_object.required
field_list.append(
{"type": "{}".format(type), "name": to_camel_case(field), "origin_name": field, "islist": False,
"originType": field_object, "autogen": field in autogen_fields,"choices":chc,"required":req})
class_list.append({'class': rClass._class_name, "fields": field_list})
return class_list, builded
f = None
def print(item):
if f:
f.writelines(str(item) + "\n")
def buildFunctionFromJson(fields):
print("\t void fromJson(data) {")
for i in fields:
if i.get('type') != "DateTime":
if not i.get('islist') and not i.get('is_class'):
print("\t\tthis.{} = data[\"{}\"];".format(i.get('name'), i.get("origin_name")))
elif i.get('islist') and not i.get('is_class'):
print("\t\tthis.{}=[];".format(i.get('name')));
print("\t\tdata[\"{}\"].forEach((element)".format(i.get("origin_name")))
print("\t\t{")
print("\t\t\tthis.{}.add(element);".format(i.get('name')))
print("\t\t}"
");")
elif not i.get('islist') and i.get('is_class'):
print("\t\tthis.{} = {}();".format(i.get('name'), i.get('class_name')))
print("\t\tthis.{}.fromJson(data[\"{}\"]);".format(i.get('name'), i.get('origin_name')))
else:
print("\t\tthis.{}=[];".format(i.get('name')));
print("\t\tdata[\"{}\"].forEach((element)".format(i.get("origin_name")))
print("\t\t{")
print("\t\t\t{cname} cls = {cname}();".format(cname=i.get('class_name')))
print("\t\t\tcls.fromJson(data[\"{}\"]);".format(i.get('origin_name')))
print("\t\t\tthis.{}.add(cls);".format(i.get('name')))
print("\t\t}"
");")
print("\t}")
def exportJson(fields):
print("\tMap<String,dynamic> toJson() {")
print("\t\tMap<String,dynamic> output = {};")
for i in fields:
if i.get('type') != "DateTime":
if not i.get('islist') and not i.get('is_class'):
print("\t\toutput[\"{}\"] = this.{};".format(i.get('origin_name'), i.get("name")))
elif i.get('islist') and not i.get('is_class'):
print("\t\toutput[\"{}\"] = [];".format(i.get('origin_name')))
print("\t\tthis.{}.forEach((element) => output[\"{}\"].add(element));".format(i.get('name'),i.get('origin_name')))
elif i.get('islist') and i.get('is_class'):
print("\t\toutput[\"{}\"] = [];".format(i.get('origin_name')))
print("\t\tthis.{}.forEach((element) => output[\"{}\"].add(element.toJson()));".format(i.get('name'),
i.get('origin_name')))
elif not i.get('islist') and i.get('is_class'):
print("\t\toutput[\"{}\"] = this.{}.toJson();".format(i.get('origin_name'),i.get('name')))
print("\t\treturn output;")
print("\t}")
def mainBuilder(classlist):
global f
blist = []
for cls in classlist:
data = build_class(cls,blist)
blist = blist + data[1]
for i in data[0]:
f = open('flutter_out/{}.dart'.format(i.get('class')),"w")
print("import 'package:scoped_model/scoped_model.dart';")
print("class {} extends Model ".format(i.get('class')))
print("{")
for field in i.get('fields'):
print("\t {} {};".format(field.get('type'), field.get('name')))
print("")
print("\t// Build Functions")
print("\t// ")
buildFunctionFromJson(i.get('fields'))
exportJson(i.get('fields'))
print("}")
if __name__ == '__main__':
import os
os.chdir('../')
print(os.getcwd())
mainBuilder([User, Payments, Account])
Loading…
Cancel
Save