diff --git a/demo/apps/apijson_demo/settings.ini b/demo/apps/apijson_demo/settings.ini index f9a25f3..c002a8d 100644 --- a/demo/apps/apijson_demo/settings.ini +++ b/demo/apps/apijson_demo/settings.ini @@ -6,14 +6,16 @@ moment = 'apijson_demo.models.Moment' [APIJSON_MODELS] moment = { "user_id_field" : "user_id", - "GET" : { "roles" : ["OWNER"] }, + "GET" : { "roles" : ["OWNER","LOGIN"] }, + "HEAD" : { "roles" : ["OWNER","LOGIN"] }, "POST" : { "roles" : ["OWNER"] }, "PUT" : { "roles" : ["OWNER"] }, "DELETE" : { "roles" : ["OWNER"] }, } comment = { "user_id_field" : "user_id", - "GET" : { "roles" : ["OWNER"] }, + "GET" : { "roles" : ["OWNER","LOGIN"] }, + "HEAD" : { "roles" : ["OWNER","LOGIN"] }, "POST" : { "roles" : ["OWNER"] }, "PUT" : { "roles" : ["OWNER"] }, "DELETE" : { "roles" : ["OWNER"] }, diff --git a/demo/apps/apijson_demo/templates/index.html b/demo/apps/apijson_demo/templates/index.html index 96666ed..2e630a4 100644 --- a/demo/apps/apijson_demo/templates/index.html +++ b/demo/apps/apijson_demo/templates/index.html @@ -7,6 +7,7 @@
+ @@ -33,6 +34,20 @@ + +
HTTP HEAD URL
+ +
+ +
apijson head request examples
+ + + { item.label } + + +
+ +
POST URL
@@ -88,6 +103,7 @@ delimiters: ['{', '}'], data: { request_get : {{=request_get_json}}, + request_head : {{=request_head_json}}, request_post : {{=request_post_json}}, request_put : {{=request_put_json}}, request_delete : {{=request_delete_json}}, @@ -97,6 +113,7 @@ tab_current : "tab_get", tab2url : { "tab_get":"{{=url_for('uliweb_apijson.apijson.views.ApiJson.get')}}", + "tab_head":"{{=url_for('uliweb_apijson.apijson.views.ApiJson.head')}}", "tab_post":"{{=url_for('uliweb_apijson.apijson.views.ApiJson.post')}}", "tab_put":"{{=url_for('uliweb_apijson.apijson.views.ApiJson.put')}}", "tab_delete":"{{=url_for('uliweb_apijson.apijson.views.ApiJson.delete')}}" @@ -130,6 +147,9 @@ if (n=="tab_get") { vm.request_data = vm.request_get[0].value } + else if (n=="tab_head") { + vm.request_data = vm.request_head[0].value + } else if (n=="tab_post") { vm.request_data = vm.request_post[0].value } diff --git a/demo/apps/apijson_demo/views.py b/demo/apps/apijson_demo/views.py index 9dbac13..86f6a8c 100644 --- a/demo/apps/apijson_demo/views.py +++ b/demo/apps/apijson_demo/views.py @@ -8,11 +8,13 @@ def index(): user_info = "login as user '%s(%s)'"%(request.user.username,request.user) else: user_info = "not login, you can login with username 'admin/usera/userb/userc', and password '123'" + request_get = [ { - "label":"Single record query: no parameter", + "label":"Single record query: self user", "value":'''{ "user":{ + "@role":"OWNER" } }''', }, @@ -20,7 +22,8 @@ def index(): "label":"Single record query: with id as parameter", "value":'''{ "user":{ - "id":1 + "id":2, + "@role":"ADMIN" } }''', }, @@ -28,7 +31,8 @@ def index(): "label":"Single record query: @column", "value":'''{ "user":{ - "@column": "id,username,email" + "@column": "id,username,email", + "@role":"OWNER" } }''', }, @@ -40,7 +44,8 @@ def index(): "@page":0, "user":{ "@column":"id,username,nickname,email", - "@order":"id-" + "@order":"id-", + "@role":"ADMIN" } } }''', @@ -59,6 +64,17 @@ def index(): }, ] + request_head = [ + { + "label":"query number of moments for one user", + "value":'''{ + "moment": { + "user_id": 1 + } +}''', + }, + ] + request_post = [ { "label":"Add new moment", @@ -112,6 +128,7 @@ def index(): return { "user_info":user_info, "request_get_json":dumps(request_get), + "request_head_json":dumps(request_head), "request_post_json":dumps(request_post), "request_put_json":dumps(request_put), "request_delete_json":dumps(request_delete), diff --git a/uliweb_apijson/apijson/settings.ini b/uliweb_apijson/apijson/settings.ini index cee3792..badc16c 100644 --- a/uliweb_apijson/apijson/settings.ini +++ b/uliweb_apijson/apijson/settings.ini @@ -11,6 +11,7 @@ user = { "user_id_field" : "id", "secret_fields" : ["password"], "GET" : { "roles" : ["ADMIN","OWNER"] }, + "HEAD" : { "roles" : ["ADMIN","OWNER"] }, "POST" : { "roles" : ["ADMIN","OWNER"] }, "PUT" : { "roles" : ["ADMIN","OWNER"] }, "DELETE" : { "roles" : ["ADMIN","OWNER"] }, diff --git a/uliweb_apijson/apijson/views.py b/uliweb_apijson/apijson/views.py index 0f6d71d..47a0b4f 100644 --- a/uliweb_apijson/apijson/views.py +++ b/uliweb_apijson/apijson/views.py @@ -33,6 +33,7 @@ def get(self): def _get_one(self,key): modelname = key params = self.request_data[key] + params_role = params.get("@role") try: model = getattr(models,modelname) @@ -43,48 +44,30 @@ def _get_one(self,key): model_column_set = None q = model.all() - #rbac check begin - GET = model_setting.get("GET",{}) + GET = model_setting.get("GET") if not GET: - return json({"code":401,"msg":"'%s' not accessible by apijson"%(modelname)}) + return json({"code":400,"msg":"'%s' not accessible"%(modelname)}) roles = GET.get("roles") - perms = GET.get("perms") - params_role = params.get("@role") permission_check_ok = False - user_role = None - if params_role: - if params_role not in roles: - return json({"code":401,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) - if functions.has_role(request.user,params_role): - permission_check_ok = True - user_role = params_role + if not params_role: + if request.user: + params_role = "LOGIN" else: - return json({"code":401,"msg":"user doesn't have role '%s'"%(params_role)}) - if not permission_check_ok and roles: - for role in roles: - if functions.has_role(request.user,role): - permission_check_ok = True - user_role = role - break - - if not permission_check_ok and perms: - for perm in perms: - if functions.has_permission(request.user,perm): - permission_check_ok = True - break - + params_role = "UNKNOWN" + if params_role not in roles: + return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) + if 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)}) if not permission_check_ok: - return json({"code":401,"msg":"no permission"}) - #rbac check end - - filtered = False + return json({"code":400,"msg":"no permission"}) - if user_role == "OWNER": + if params_role=="OWNER": owner_filtered,q = self._filter_owner(model,model_setting,q) if not owner_filtered: - return json({"code":401,"msg":"'%s' cannot filter with owner"%(modelname)}) - filtered = True + return json({"code":400,"msg":"'%s' cannot filter with owner"%(modelname)}) params = self.request_data[key] if isinstance(params,dict): @@ -94,12 +77,8 @@ def _get_one(self,key): model_column_set = set(params[n].split(",")) elif hasattr(model,n): q = q.filter(getattr(model.c,n)==params[n]) - filtered = True else: return json({"code":400,"msg":"'%s' have no attribute '%s'"%(modelname,n)}) - #default filter is trying to filter with owner - if not filtered and request.user: - owner_filtered,q = self._filter_owner(model,model_setting,q) o = q.one() if o: o = o.to_dict() @@ -168,45 +147,32 @@ def _get_array(self,key): q = model.all() - #rbac check begin - GET = model_setting.get("GET",{}) + GET = model_setting.get("GET") if not GET: - return json({"code":401,"msg":"'%s' not accessible by apijson"%(modelname)}) + return json({"code":400,"msg":"'%s' not accessible by apijson"%(modelname)}) roles = GET.get("roles") - perms = GET.get("perms") - params_role = params.get("@role") + params_role = model_param.get("@role") permission_check_ok = False - user_role = None - if params_role: - if params_role not in roles: - return json({"code":401,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) - if functions.has_role(request.user,params_role): - permission_check_ok = True - user_role = params_role + if not params_role: + if request.user: + params_role = "LOGIN" else: - return json({"code":401,"msg":"user doesn't have role '%s'"%(params_role)}) - if not permission_check_ok and roles: - for role in roles: - if functions.has_role(request.user,role): - permission_check_ok = True - user_role = role - break - - if not permission_check_ok and perms: - for perm in perms: - if functions.has_permission(request.user,perm): - permission_check_ok = True - break + params_role = "UNKNOWN" + if params_role not in roles: + return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) + if 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)}) if not permission_check_ok: - return json({"code":401,"msg":"no permission"}) - #rbac check end + return json({"code":400,"msg":"no permission"}) - if user_role == "OWNER": + if params_role == "OWNER": owner_filtered,q = self._filter_owner(model,model_setting,q) if not owner_filtered: - return json({"code":401,"msg":"'%s' cannot filter with owner"%(modelname)}) + return json({"code":400,"msg":"'%s' cannot filter with owner"%(modelname)}) if query_count: if query_page: @@ -252,6 +218,67 @@ def _filter_owner(self,model,model_setting,q): owner_filtered = True return owner_filtered,q + def head(self): + for key in self.request_data: + rsp = self._head(key) + if rsp: return rsp + + return json(self.rdict) + + def _head(self,key): + modelname = key + params = self.request_data[key] + params_role = params.get("@role") + + try: + model = getattr(models,modelname) + model_setting = settings.APIJSON_MODELS.get(modelname,{}) + except ModelNotFound as e: + log.error("try to find model '%s' but not found: '%s'"%(modelname,e)) + return json({"code":400,"msg":"model '%s' not found"%(modelname)}) + + q = model.all() + + HEAD = model_setting.get("HEAD") + if not HEAD: + return json({"code":400,"msg":"'%s' not accessible"%(modelname)}) + + roles = HEAD.get("roles") + permission_check_ok = False + if not params_role: + if 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'"%(modelname,params_role)}) + if 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)}) + if not permission_check_ok: + return json({"code":400,"msg":"no permission"}) + + if params_role=="OWNER": + owner_filtered,q = self._filter_owner(model,model_setting,q) + if not owner_filtered: + return json({"code":400,"msg":"'%s' cannot filter with owner"%(modelname)}) + for n in params: + if n[0]=="@": + pass + else: + param = params[n] + if not hasattr(model.c,n): + return json({"code":400,"msg":"'%s' don't have field '%s'"%(modelname,n)}) + q = model.filter(getattr(model.c,n)==param) + rdict = { + "code":200, + "msg":"success", + "count":q.count(), + } + + self.rdict[key] = rdict + def post(self): tag = self.request_data.get("@tag") if not tag: @@ -274,15 +301,17 @@ def _post_one(self,key,tag): try: model = getattr(models,modelname) model_setting = settings.APIJSON_MODELS.get(modelname,{}) - request_setting_tag = settings.APIJSON_REQUESTS.get(tag,{}) user_id_field = model_setting.get("user_id_field") except ModelNotFound as e: log.error("try to find model '%s' but not found: '%s'"%(modelname,e)) return json({"code":400,"msg":"model '%s' not found"%(modelname)}) - request_setting_model = request_setting_tag.get(modelname,{}) - request_setting_POST = request_setting_model.get("POST",{}) - ADD = request_setting_POST.get("ADD") + request_tag = settings.APIJSON_REQUESTS.get(tag,{}) + request_tag_tag = request_tag.get(tag,{}) + if not request_tag_tag: + return json({"code":400,"msg":"tag '%s' not found"%(tag)}) + tag_POST = request_tag_tag.get("POST",{}) + ADD = tag_POST.get("ADD") if ADD: ADD_role = ADD.get("@role") if ADD_role and not params_role: @@ -294,7 +323,7 @@ def _post_one(self,key,tag): roles = POST.get("roles") if params_role: if not params_role in roles: - return json({"code":401,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) + return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) roles = [params_role] if roles: @@ -371,16 +400,17 @@ def _put_one(self,key,tag): try: model = getattr(models,modelname) model_setting = settings.APIJSON_MODELS.get(modelname,{}) - request_setting_tag = settings.APIJSON_REQUESTS.get(tag,{}) user_id_field = model_setting.get("user_id_field") except ModelNotFound as e: log.error("try to find model '%s' but not found: '%s'"%(modelname,e)) return json({"code":400,"msg":"model '%s' not found"%(modelname)}) - request_setting_model = request_setting_tag.get(modelname,{}) - request_setting_PUT = request_setting_model.get("PUT",{}) - - ADD = request_setting_PUT.get("ADD") + request_tag = settings.APIJSON_REQUESTS.get(tag,{}) + request_tag_tag = request_tag.get(tag,{}) + if not request_tag_tag: + return json({"code":400,"msg":"tag '%s' not found"%(tag)}) + tag_PUT = request_tag_tag.get("PUT",{}) + ADD = tag_PUT.get("ADD") if ADD: ADD_role = ADD.get("@role") if ADD_role and not params_role: @@ -403,7 +433,7 @@ def _put_one(self,key,tag): roles = PUT.get("roles") if params_role: if not params_role in roles: - return json({"code":401,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) + return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) roles = [params_role] if roles: for role in roles: @@ -468,16 +498,17 @@ def _delete_one(self,key,tag): try: model = getattr(models,modelname) model_setting = settings.APIJSON_MODELS.get(modelname,{}) - request_setting_tag = settings.APIJSON_REQUESTS.get(tag,{}) user_id_field = model_setting.get("user_id_field") except ModelNotFound as e: log.error("try to find model '%s' but not found: '%s'"%(modelname,e)) return json({"code":400,"msg":"model '%s' not found"%(modelname)}) - request_setting_model = request_setting_tag.get(modelname,{}) - request_setting_DELETE = request_setting_model.get("DELETE",{}) - - ADD = request_setting_DELETE.get("ADD") + request_tag = settings.APIJSON_REQUESTS.get(tag,{}) + request_tag_tag = request_tag.get(tag,{}) + if not request_tag_tag: + return json({"code":400,"msg":"tag '%s' not found"%(tag)}) + tag_DELETE = request_tag_tag.get("DELETE",{}) + ADD = tag_DELETE.get("ADD") if ADD: ADD_role = ADD.get("@role") if ADD_role and not params_role: @@ -500,7 +531,7 @@ def _delete_one(self,key,tag): roles = DELETE.get("roles") if params_role: if not params_role in roles: - return json({"code":401,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) + return json({"code":400,"msg":"'%s' not accessible by role '%s'"%(modelname,params_role)}) roles = [params_role] if roles: for role in roles: