Skip to content
Merged

Sync #41

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions demo/apps/apijson_demo/settings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ comment = {
}

[APIJSON_REQUESTS]
user = {
"POST" :{
"ADD":{"@role": "ADMIN"},
"DISALLOW" : ["id"],
"NECESSARY" : ["username","nickname"],
},
"PUT" :{
"ADD":{"@role": "OWNER"},
"NECESSARY" : ["id"],
},
}
moment = {
"POST" :{
"ADD":{"@role": "OWNER"},
Expand Down
3 changes: 3 additions & 0 deletions demo/apps/tables/settings.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[APIJSON_TABLES]
user = {
"editable" : "auto",
}
moment = {
"editable" : "auto",
"table_fields" : [
Expand Down
8 changes: 4 additions & 4 deletions tests/demo/apps/apijson_demo/dbinit.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,25 @@
"username": "admin",
"nickname": "Administrator",
"email": "admin@localhost",
"date_join": "2018-1-1",
"date_join": "2018-1-1 0:0:0",
},
{
"username": "usera",
"nickname": "User A",
"email": "usera@localhost",
"date_join": "2018-2-2",
"date_join": "2018-2-2 0:0:0",
},
{
"username": "userb",
"nickname": "User B",
"email": "userb@localhost",
"date_join": "2018-3-3",
"date_join": "2018-3-3 0:0:0",
},
{
"username": "userc",
"nickname": "User C",
"email": "userc@localhost",
"date_join": "2018-4-4",
"date_join": "2018-4-4 0:0:0",
},
]

Expand Down
4 changes: 2 additions & 2 deletions tests/demo/apps/apijson_demo/settings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ user = {
"secret_fields" : ["password"],
"GET" : { "roles" : ["LOGIN","ADMIN","OWNER"] },
"HEAD" : { "roles" : ["LOGIN","ADMIN","OWNER"] },
"POST" : { "roles" : ["ADMIN"] },
#"POST" : { "roles" : ["ADMIN"] }, #remove for test case
"PUT" : { "roles" : ["ADMIN","OWNER"] },
"DELETE" : { "roles" : ["ADMIN"] },
}
Expand Down Expand Up @@ -63,7 +63,7 @@ comment = {
"POST" :{
"ADD" :{"@role": "OWNER"},
"DISALLOW" : ["id"],
"NECESSARY" : ["content"]
"NECESSARY" : ["moment_id","content"]
},
"PUT" :{
"ADD":{"@role": "OWNER"},
Expand Down
436 changes: 434 additions & 2 deletions tests/test.py

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions uliweb_apijson/apijson/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ uliweb-apijson is a subset and slightly different variation of [apijson](https:/

# Difference with original apijson

| feature | apijson(java) | uliweb-apijson | comment |
| -------- | ------------- | -------------- | ------------------------------------------------------------ |
| @combine | ✔️ | ✖️ | Example: "@combine":"&key0,&key1,\|key2,key3" |
| @expr | ✖️ | ✔️ | Example: "@expr":[["username$","&","email$"],"&",["!","nickname$"]] |
| feature | apijson(java) | uliweb-apijson | comment |
| ------------------- | --------------- | ---------------- | ------------------------------------------------------------ |
| @combine | ✔️ | ✖️ | Example: "@combine":"&key0,&key1,\|key2,key3" |
| @expr | ✖️ | ✔️ | Example: "@expr":[["username$","&","email$"],"&",["!","nickname$"]] |
| tag in apijson post/put | "tag": "Moment" | "@tag": "Moment" | |



Expand Down
3 changes: 1 addition & 2 deletions uliweb_apijson/apijson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def _get_array_q(self,params):

#@expr
model_expr = params.get("@expr")
if model_expr:
if model_expr!=None:
c = self.parent._expr(self.model,params,model_expr)
q = q.filter(c)
else:
Expand Down Expand Up @@ -258,5 +258,4 @@ def associated_query_array(self):
del params[i]
params.update(refs)
q = self._get_array_q(params)
q = q.limit(1)
item[self.name] = self._get_info(q.one())
26 changes: 20 additions & 6 deletions uliweb_apijson/apijson/templates/vue/inc_apijson_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
var thisp = this
return {
l_request_tag: null,
role: "{{=role or ''}}",

loading: false,
modal_view: false,
Expand Down Expand Up @@ -176,10 +177,13 @@
"@page":thisp.current_page-1,
"@query":2
}
arr_params[thisp.model_name] = {
"@order":thisp.sort_key+thisp.sort_order,
"@role":"{{=role}}"
var model_params = {
"@order":thisp.sort_key+thisp.sort_order
}
if (thisp.role!="") {
model_params["@role"] = thisp.role
}
arr_params[thisp.model_name] = model_params
var params = {
"[]":arr_params,
"total@":"/[]/total"
Expand Down Expand Up @@ -253,15 +257,15 @@
}
}
else {
this.viewedit_items.push({title:"id",value:row.id,component:"input"})
this.viewedit_items.push({key:"id",title:"id",value:row.id,component:"input"})
var type2comp = {
"boolean":"checkbox"
}
for (var k in row){
if (k!="id" && k[0]!="_") {
var value = row[k]
var comp = type2comp[typeof value] || "input"
this.viewedit_items.push({title:k,value:value,component:comp})
this.viewedit_items.push({title:k,key:k,value:value,component:comp})
}
}
}
Expand Down Expand Up @@ -297,6 +301,9 @@
record_params[d.key] = d.value
}
}
if (thisp.role!="") {
record_params["@role"] = thisp.role
}
params[thisp.l_request_tag] = record_params
params = thisp.ajax_hook("apijson_put","update",params)
$.ajax({
Expand Down Expand Up @@ -377,9 +384,13 @@
var params = {
"@tag": thisp.l_request_tag
}
params[thisp.l_request_tag] = {
var model_params = {
"id": thisp.delete_params.row.id
}
if (thisp.role!="") {
model_params["@role"] = thisp.role
}
params[thisp.l_request_tag] = model_params
params = thisp.ajax_hook("apijson_delete","delete",params)
$.ajax({
type: "POST",
Expand Down Expand Up @@ -433,6 +444,9 @@
var d = thisp.add_items[k]
post_params[d.key] = d.value
}
if (thisp.role!="") {
post_params["@role"] = thisp.role
}
params[this.l_request_tag] = post_params
params = thisp.ajax_hook("apijson_post","add",params)
$.ajax({
Expand Down
11 changes: 8 additions & 3 deletions uliweb_apijson/apijson/templates/vue/inc_apijson_viewedit.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
data: function(){
return {
l_request_tag: null,
role: "{{=role}}",
role: "{{=role or ''}}",
row: {},
row_saved: {},
viewedit_items: [],
Expand All @@ -38,8 +38,10 @@
init_viewedit: function(){
var params = {}
var model_params = {
"id":this.id,
"@role":this.role
"id":this.id
}
if (this.role!='') {
model_params["@role"] = this.role
}
params[this.model_name] = model_params
var thisp = this
Expand Down Expand Up @@ -89,6 +91,9 @@
this.row[d.key] = d.value
}
}
if (this.role!='') {
record_params["@role"] = this.role
}
params[this.l_request_tag] = record_params
params = this.ajax_hook("apijson_put","update",params)
var thisp = this
Expand Down
41 changes: 25 additions & 16 deletions uliweb_apijson/apijson/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ def _get_one(self,key):
roles = GET.get("roles")
permission_check_ok = False
if not params_role:
if hasattr(request,"user"):
if hasattr(request,"user") and request.user:
params_role = "LOGIN"
else:
params_role = "UNKNOWN"
elif params_role != "UNKNOWN":
if not hasattr(request,"user"):
if not (hasattr(request,"user") and request.user):
return json({"code":400,"msg":"no login user for role '%s'"%(params_role)})
if params_role not in roles:
return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(model_name,params_role)})
Expand Down Expand Up @@ -200,57 +200,61 @@ def _filter_owner(self,model,model_setting,q):

def _expr(self,model,model_param,model_expr):
if not isinstance(model_expr,list):
raise UliwebError("only accept array in @expr: '%s'"%(model_expr))
raise UliwebError("only accept array in @expr, but get '%s'"%(model_expr))
num = len(model_expr)
if (num<2 or num>3):
raise UliwebError("only accept 2 or 3 items in @expr: '%s'"%(model_expr))
raise UliwebError("only accept 2 or 3 items in @expr, but get '%s'"%(model_expr))
op = model_expr[-2]
if op=='&':
if num!=3:
raise UliwebError("'&'(and) expression need 3 items: '%s'"%(model_expr))
raise UliwebError("'&'(and) expression need 3 items, but get '%s'"%(model_expr))
c1 = self._get_filter_condition(model,model_param,model_expr[0],expr=True)
c2 = self._get_filter_condition(model,model_param,model_expr[2],expr=True)
return and_(c1,c2)
elif op=='|':
if num!=3:
raise UliwebError("'|'(or) expression need 3 items: '%s'"%(model_expr))
raise UliwebError("'|'(or) expression need 3 items, but get '%s'"%(model_expr))
c1 = self._get_filter_condition(model,model_param,model_expr[0],expr=True)
c2 = self._get_filter_condition(model,model_param,model_expr[2],expr=True)
return or_(c1,c2)
elif op=='!':
if num!=2:
raise UliwebError("'!'(not) expression need 2 items: '%s'"%(model_expr))
raise UliwebError("'!'(not) expression need 2 items, but get '%s'"%(model_expr))
return not_(self._get_filter_condition(model,model_param,model_expr[1],expr=True))
else:
raise UliwebError("unknown operator: '%s'"%(op))

def _get_filter_condition(self,model,model_param,item,expr=False):
#item can be param key, or expr which expected to be a list
if isinstance(item,list):
if expr:
return self._expr(model,model_param,model_expr=item)
else:
raise UliwebError("item can be array only in @expr: '%s'"%(item))
#current implementation won't run here, but keep for safe
raise UliwebError("item can be list only in @expr: '%s'"%(item))
if not isinstance(item,string_types):
#current implementation won't run here, but keep for safe
raise UliwebError("item should be array or string: '%s'"%(item))
n = item
if n[0]=="@":
#current implementation won't run here, but keep for safe
raise UliwebError("param key should not begin with @: '%s'"%(n))
if n[-1]=="$":
name = n[:-1]
if hasattr(model,name):
return getattr(model.c,name).like(model_param[n])
else:
raise UliwebError("'%s' does not have '%s'"%(model_name,name))
raise UliwebError("model does not have this column: '%s'"%(name))
elif n[-1]=="}" and n[-2]=="{":
name = n[:-2]
if hasattr(model,name):
# TODO
# TODO: https://github.com/APIJSON/APIJSON/blob/master/Document.md#32-%E5%8A%9F%E8%83%BD%E7%AC%A6
pass
raise UliwebError("still not support '%s'"%(name))
elif hasattr(model,n):
return getattr(model.c,n)==model_param[n]
else:
raise UliwebError("not support item: '%s'"%(item))
raise UliwebError("non-existent column or not support item: '%s'"%(item))

def head(self):
try:
Expand Down Expand Up @@ -286,18 +290,21 @@ def _head(self,key):
roles = HEAD.get("roles")
permission_check_ok = False
if not params_role:
if request.user:
if hasattr(request,"user") and request.user:
params_role = "LOGIN"
else:
params_role = "UNKNOWN"
if params_role not in roles:
return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(model_name,params_role)})
return json({"code":400,"msg":"role '%s' not have permission HEAD for '%s'"%(params_role,model_name)})
if params_role == "UNKNOWN":
permission_check_ok = True
elif not (hasattr(request,"user") and request.user):
return json({"code":400,"msg":"no login user for role '%s'"%(params_role)})
elif functions.has_role(request.user,params_role):
permission_check_ok = True
else:
return json({"code":400,"msg":"user doesn't have role '%s'"%(params_role)})
#current implementation won't run here, but keep for safe
if not permission_check_ok:
return json({"code":400,"msg":"no permission"})

Expand Down Expand Up @@ -381,7 +388,7 @@ def _post_one(self,key,tag):
if roles:
for role in roles:
if role == "OWNER":
if request.user:
if hasattr(request,"user") and request.user:
permission_check_ok = True
if user_id_field:
params[user_id_field] = request.user.id
Expand Down Expand Up @@ -500,7 +507,7 @@ def _put_one(self,key,tag):
if roles:
for role in roles:
if role == "OWNER":
if request.user:
if hasattr(request,"user") and request.user:
if user_id_field:
if obj.to_dict().get(user_id_field)==request.user.id:
permission_check_ok = True
Expand Down Expand Up @@ -535,6 +542,8 @@ def _put_one(self,key,tag):
for k in params:
if k=="id":
continue
elif k[0]=="@":
continue
elif hasattr(obj,k):
kwargs[k] = params[k]
else:
Expand Down Expand Up @@ -621,7 +630,7 @@ def _delete_one(self,key,tag):
if roles:
for role in roles:
if role == "OWNER":
if request.user:
if hasattr(request,"user") and request.user:
if user_id_field:
if obj.to_dict().get(user_id_field)==request.user.id:
permission_check_ok = True
Expand Down