Exemple #1
0
 def test_dissert(self):
     objs = [
         {"accounts": {"actions": {"add": "", "delete": "", "edit": ""}}, "proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"add": "", "delete": "", "edit": ""}}},
         {"proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"add": "", "delete": "", "edit": ""}}, "proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
         {"proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}}
     ]
     
     dissect = [
         {"accounts": {"actions": {"add": "", "edit": ""}}, "proftpd": {"ftp_client": {"access": "self", "type": "read"}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"add": ""}}, "proftpd": {"ftp_client": {"type": {"write": {"access_change": ""}}}}},
         {"proftpd": {"ftp_client": {"access": "self", "type": "read"}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"add": "", "delete": "", "edit": ""}}},
         {"proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
     ]
     
     result = [
         {'proftpd': {'ftp_client': {'type': {"write": {"access_change": ""}}}}, 'accounts': {'actions': {'delete': ''}}},
         {"accounts": {"actions": {"delete": "", "edit": ""}}},
         {"proftpd": {"ftp_client": {"type": {"write": {"access_change": ""}}}}},
         {"proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
         {}
     ]
     
     i = 0
     for o in objs:
         perm_obj = Permission(o)
         perm_obj.dissect(dissect[i])
         self.assertTrue(perm_obj.permissions == result[i])
         i += 1
Exemple #2
0
 def test_merge(self):
     objs = [
         {"accounts": {"actions": {"add": "", "delete": "", "edit": ""}}},
         {},
         {"proftpd": {"ftp_client": {"access": "self", "type": "read"}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"edit": "", "delete": ""}}},
         {"proftpd": {"ftp_client": {"access": "self", "type": "read"}}}
     ]
     
     merge = [
         {"proftpd": {"ftp_client": {"access": "self", "type": "read"}, "statistics": "self", "daemon": ""}},
         {},
         {"proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"add": ""}}},
         {"proftpd": {"ftp_client": {"access": "global", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}}
     ]
     
     result = [
         {"accounts": {"actions": {"add": "", "delete": "", "edit": ""}}, "proftpd": {"ftp_client": {"access": "self", "type": "read"}, "statistics": "self", "daemon": ""}},
         {},
         {"proftpd": {"ftp_client": {"access": "self", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}},
         {"accounts": {"actions": {"edit": "", "delete": "", "add": ""}}},
         {"proftpd": {"ftp_client": {"access": "global", "type": {"write": {"access_change": ""}}}, "statistics": "self", "daemon": ""}}
     ]
     
     i = 0
     for o in objs:
         perm_obj = Permission(o)
         perm_obj.merge(merge[i])
         self.assertTrue(perm_obj.permissions == result[i])
         i += 1
Exemple #3
0
 def merged_permissions(self):
     cache_key = CACHE_KEY_USERPERM % self.id
     
     if not cache.get(cache_key):
         permission = Permission(self.profile.permissions)
         cache.set(cache_key,
                   permission.merge(self.group_permissions()))
     
     return cache.get(cache_key)
Exemple #4
0
 def group_permissions(self):
     cache_key = CACHE_KEY_UGRPERM % self.id
     
     if not cache.get(cache_key):
         group_perms = Permission()
         for group in self.groups.all():
             group_perms.merge(group.permissions)
         
         cache.set(cache_key, group_perms.permissions)
     
     return cache.get(cache_key)
Exemple #5
0
 def delete(self, args_, current_user):
     """
     删除用户,逻辑删除
     :return:
     """
     res = AppSetting.general_result()
     res["request_info"] = self.request_info
     if not Permission.check_user_role(self.edit_roles,
                                       current_user["roles"]):
         res["err_code"] = APIStatus.ROLE_FORBIDDEN
         res["message"] = "user role is forbidden: {}".format(
             current_user["username"])
         res["result"] = "fail"
         return res
     if "item" not in args_ or not args_["item"]:
         res["err_code"] = APIStatus.FIELD_LACK
         res["message"] = "no such params: item"
         res["result"] = "fail"
         return res
     res["data"] = {"uid": args_.get("item", "")}
     try:
         self.controller.delete(args_["item"])
     except SQLAlchemyError as err:
         # print(err.orig.args)
         res["err_code"] = APIStatus.DB_ERROR
         res["message"] = json.dumps(err.orig.args)
         res["result"] = "fail"
     except Exception as err:
         res["err_code"] = APIStatus.UNDEFINED
         res["message"] = str(err)
         res["result"] = "fail"
     else:
         res["err_code"] = APIStatus.SUCCESS
     return res
Exemple #6
0
    def get(self, args_, current_user):
        """
        获取用户信息
        :return:
        """
        res = AppSetting.general_result()
        res["request_info"] = self.request_info
        if not Permission.check_user_role(self.view_roles,
                                          current_user["roles"]):
            res["err_code"] = APIStatus.ROLE_FORBIDDEN
            res["message"] = "user role is forbidden: {}".format(
                current_user["username"])
            res["result"] = "fail"
            return res

        order_key = args_.get("order_key", "-create_time")
        if order_key:
            if order_key.startswith("-"):
                key_check = order_key[1:]
            else:
                key_check = order_key
            if key_check not in self.fields_border:
                res["err_code"] = APIStatus.FIELD_OUTER
                res["message"] = "order_key: [{}] is unknown field".format(
                    key_check)
                res["result"] = "fail"
                return res

        start = args_.get("start", 0)
        count = args_.get("count", 0)

        start = start if isinstance(start, int) and start >= 0 else 0
        count = count if isinstance(count, int) and count >= 0 else 0
        try:
            total = self.controller.count()
            res["data"] = self.controller.all(
                start=start, count=count, order_key=order_key) or []
        except SQLAlchemyError as err:
            # print(err.orig.args)
            res["err_code"] = APIStatus.DB_ERROR
            res["message"] = json.dumps(err.orig.args)
            res["result"] = "fail"
        except Exception as err:
            res["err_code"] = APIStatus.UNDEFINED
            res["message"] = str(err)
            res["result"] = "fail"
        else:
            res["err_code"] = APIStatus.SUCCESS
            res["total"] = total
        return res
Exemple #7
0
    def put(self, args_, body_, current_user):
        """
        更改用户信息
        :return:
        """
        res = AppSetting.general_result()
        res["request_info"] = self.request_info
        if not Permission.check_user_role(self.edit_roles,
                                          current_user["roles"]):
            res["err_code"] = APIStatus.ROLE_FORBIDDEN
            res["message"] = "user role is forbidden: {}".format(
                current_user["username"])
            res["result"] = "fail"
            return res
        if "item" not in args_ or not args_["item"]:
            res["err_code"] = APIStatus.FIELD_LACK
            res["message"] = "no such params: item"
            res["result"] = "fail"
            return res

        res["data"] = {"uid": args_.get("item", "")}
        for field in list(body_.keys()):
            if field not in self.fields_border:
                body_.pop(field)
        # print(body_)
        unique_list = deepcopy(self.controller.get_model().unique_list)
        unique_list.append(self.controller.get_model().key_word)
        try:
            self._check_unique_field(body_, unique_list)
        except Exception as err:
            res["err_code"] = APIStatus.ALREADY_EXIST
            res["message"] = str(err)
            res["result"] = "fail"
            return res
        try:
            self.controller.update(args_["item"], **body_)
        except SQLAlchemyError as err:
            res["err_code"] = APIStatus.DB_ERROR
            res["message"] = json.dumps(err.orig.args)
            res["result"] = "fail"
        except Exception as err:
            res["err_code"] = APIStatus.UNDEFINED
            res["message"] = str(err)
            res["result"] = "fail"
        else:
            res["err_code"] = APIStatus.SUCCESS
        res["err_code"] = APIStatus.SUCCESS
        return res
Exemple #8
0
 def search(self, body_, current_user):
     res = AppSetting.general_result()
     res["request_info"] = self.request_info
     if not Permission.check_user_role(self.view_roles,
                                       current_user["roles"]):
         res["err_code"] = APIStatus.ROLE_FORBIDDEN
         res["message"] = "user role is forbidden: {}".format(
             current_user["username"])
         res["result"] = "fail"
         return res
     try:
         res["data"] = self.controller.search(**body_) or []
     except SQLAlchemyError as err:
         # print(err.orig.args)
         res["err_code"] = APIStatus.DB_ERROR
         res["message"] = json.dumps(err.orig.args)
         res["result"] = "fail"
     except Exception as err:
         res["err_code"] = APIStatus.UNDEFINED
         res["message"] = str(err)
         res["result"] = "fail"
     else:
         res["err_code"] = APIStatus.SUCCESS
     return res
Exemple #9
0
def manage(request, mode, action):
    data_str = request.POST.get("data", None)
    formset_id = request.COOKIES.get("formset_id", None)
    instance_id = request.POST.get("id",  request.GET.get("id", None))
    data = None
    
    # If in the "edit" mode, account_obj contains either a user or a group object
    # Otherwise the object is None
    account_obj = None
    """
    If data is send, write this data in cache and follow the following steps
    accordingly. Otherwise, if it's a step back return the cached data. In any
    other case it should be the first request in a formset, so return an empty
    form.
    """
    if data_str:
        # The user is submitting the form. Trying to deserialize data first.
        try:
            data = json.loads(data_str)
        except: # Damn... returng a bad request error
            log(6, "accounts_app - account add", "Failed to serialize data string: %s" % data_str)
            return HttpResponseBadRequest()
    
    # Let's dig out the previously recorded data from the cache.
    formset = cache.get(formset_id)
    
    # If the request uses POST method, apperently the user is submiting the form
    if request.method == "POST":
        if formset:
            step = formset["step"]
            object = formset["object"]
            
            # Fetching an object from the DB
            if instance_id and action == "edit":
                if object == "user":
                    class_obj = WenixUser
                else:
                    class_obj = WenixGroup
                
                account_obj = class_obj.objects.get(pk=instance_id)
            
            if data:
                # Get the form and check wether the submitted data valid or not.
                form = get_form(object.title(), action, step)(data)
                if not form.is_valid():
                    print data
                    print form
                    return HttpResponse(json.dumps({"ok": 0,"errors": get_errors(form, data)}),
                                        mimetype="application/json")
                
                # Update formset. All data in the following lines could be reached
                # only with the formset.
                formset["data"].update(data)
                
                """
                If it's the last step in a formset we don't need to return the next
                step, but rather we return the result of the user/group creation.
                """
                if object == "user" and step == 3:
                    u_perm_obj = Permission(formset["data"]["permissions"])
                    perm_obj = Permission(request.user.merged_permissions())
                    groups = WenixGroup.objects.in_bulk(formset["data"]["groups"]).values()
                    
                    g_perm_obj = Permission()
                    for group in groups:
                        g_perm_obj.merge(group.permissions)
                    
                    if u_perm_obj >= g_perm_obj and u_perm_obj <= perm_obj:
                        """
                        Priviliges check has passed. We have nothing to do but to
                        create or change the user.
                        We don't want redundancy, therefore the common attributes
                        will be fetched here.
                        """
                        # User permissions first
                        permissions = u_perm_obj.dissect(g_perm_obj.permissions)
                        if action == "add":
                            new_user = WenixUser.objects.create(username=formset["data"]["username"])
                            
                            # Saving general information about the user
                            for key in ("first_name", "last_name", "email", "permissions"):
                                setattr(new_user, key, formset["data"][key])
                            
                            # Changing the user's membership
                            new_user.groups = groups
                            
                            # We need to store a clean user password in order for
                            # other modules to be aware of it
                            new_user.password = formset["data"]["password"]
                            
                            # Invoking a method to notify all modules about the new user
                            WenixUser.objects.on_create(new_user)
                            
                            # Setting crypted password and saving the user
                            new_user.set_password(formset["data"]['password'])
                            new_user.save()
                            
                            message = _("A new user '%(username)s' has been created") % {"username": new_user.username}
                        else: # action == "edit"
                            account_obj.save()
                            
                            # Saving general information about the user
                            for key in ("first_name", "last_name", "email", "permissions"):
                                setattr(account_obj, key, formset["data"][key])
                            
                            # Resetting the user's password if needed
                            if formset["data"]['password']:
                                account_obj.set_password(formset["data"]['password'])
                            
                            # Changing the user's membership
                            account_obj.groups = groups
                            account_obj.save()
                            
                            # Invoking a method to notify all modules about the change
                            WenixUser.objects.on_edit(account_obj, formset["data"])
                            
                            message = _("The user '%(username)s' has been changed") % {"username": account_obj.username}
                            
                        response = HttpResponse(json.dumps({"ok": 1,"message": message}))
                        response.delete_cookie("formset_id")
                        return response
                    else:
                        """
                        It turns out as if the user created another user with higher
                        priviliges. That breaks the rules, therefore access should be
                        denied.
                        """
                        log(5, "accounts_app - account add", "Permission denied for user '%s' creating another user" % request.user.username)
                        return HttpResponse(json.dumps({"ok": 1, "message": _("Access denied")}))
                
                elif object == "group" and step == 2:
                    g_perm_obj = Permission(formset["data"]["permissions"])
                    perm_obj = Permission(request.user.merged_permissions())
                    
                    if g_perm_obj <= perm_obj:
                        
                        # Fetching users to be included in the group
                        users = WenixUser.objects.in_bulk(formset["data"]["users"] or []).values()
                        
                        """
                        Priviliges check has passed. We have nothing to do but to
                        create or change the group.
                        """
                        if action == "add":
                            # We are going to create a new group.
                            group = WenixGroup.objects.create(name=formset["data"]["name"],
                                                              permissions=g_perm_obj.permissions)
                            
                            # The new members of the group should have their priviliges updated
                            [user.groups.add(group) for user in users]
                            WenixGroup.objects.on_create(group)
                            message = _("A new group '%(name)s' has been created") % {"name": formset["data"]["name"]}
                        else: # action == "edit"
                            # We are going to change a group.
                            group = account_obj
                            
                            # Reseting users's permissions so they can form again
                            # At the same time if a user was in the MultipleChoice
                            # field remove his membership from the group
                            choice_ids = dict(id_and_name_to_dict(request.user, mode, "user")).keys()
                            old_group_users = WenixUser.objects.filter(groups__name=group.name)
                            for u in old_group_users:
                                #cache.delete(CACHE_KEY_UGRPERM % u.username)
                                #cache.delete(CACHE_KEY_USERPERM % u.username)
                                if str(u.id) in choice_ids:
                                    u.groups.remove(group)
                            
                            # Contructing a new dictionary with old_dat to pass with "on_edit" method
                            old_data = {"permissions": group.permissions,
                                        "users": old_group_users}
                            
                            group.permissions = g_perm_obj.permissions
                            group.save()
                            
                            # We're going to add users to the group
                            for user in users:
                                user.groups.add(group)
                                #if not user in old_group_users:
                                #    cache.delete(CACHE_KEY_UGRPERM % user.username)
                                #    cache.delete(CACHE_KEY_USERPERM % user.username)
                            
                            # On edit method has three arguments: user, object_being_changed and new_data
                            WenixGroup.objects.on_edit(request.user, group, old_data)
                            message = _("The priviliges for the group '%(name)s' have been saved") % {"name": group.name}
                        
                        response = HttpResponse(json.dumps({"ok": 1,"message": message}))
                        response.delete_cookie("formset_id")
                        return response
                    else:
                        """
                        It turns out as if the user created another group with higher
                        priviliges. That breaks the rules, therefore access should be
                        denied.
                        """
                        log(6, "accounts_app - account add", "Permission denied for user '%s' creating another group" % request.user.username)
                        return HttpResponse(json.dumps({"ok": 1,"message": _("Access denied")}))
                
                formset["step"] += 1
            else:
                if formset["step"] > 1:
                    formset["step"] -= 1
                else:
                    formset["step"] = 1
            
            step = formset["step"]
            form = get_form(object.title(), action, step)
            
            # Generating the next form according to the step
            if object == "user":
                if step == 1:
                    new_form = form(initial=formset["data"])
                elif step == 2:
                    """
                    We need to initialize group list here. At the same time we can't
                    list groups the user is not a memeber of if she's in the "group"
                    mode. That's why we use "id_and_name_to_dict" function to generate
                    the list.
                    """
                    new_form = form(initial=formset['data'])
                    new_form["groups"].field.choices = id_and_name_to_dict(request.user, mode, "group")
                elif step == 3:
                    # Generating permissions
                    groups = WenixGroup.objects.in_bulk(data["groups"])
                    perm_obj = Permission(request.user.merged_permissions())
                    g_perm_obj = Permission()
                    for g in groups:
                        g_perm_obj.merge(groups[g].permissions)
                    
                    if action == "add":
                        new_form = {"permissions": perm_obj.render(g_perm_obj.permissions)}
                    else: # action == "edit"
                        u_perm_obj = Permission(account_obj.permissions)
                        u_perm_obj.merge(g_perm_obj.permissions)
                        new_form = {"permissions": perm_obj.render(g_perm_obj.permissions, u_perm_obj.permissions)}
                else:
                    # Unrecognised step
                    log(6, "accounts_app - account add", "Unknown step: %s" % step)
                    return HttpResponseBadRequest()
            
            elif object == "group":
                if step == 1:
                    new_form = form(initial=formset["data"])
                    new_form["users"].field.choices = id_and_name_to_dict(request.user, mode, "user")
                elif step == 2:
                    # Generating permissions
                    perm_obj = Permission(request.user.merged_permissions())
                    
                    if action == "add":
                        new_form = {"permissions": perm_obj.render()}
                    else: # action == "edit"
                        g_perm_obj = Permission(WenixGroup.objects.get(pk=instance_id).permissions)
                        new_form = {"permissions": perm_obj.render({}, g_perm_obj.permissions)}
                else:
                    # Unrecognised step
                    log(6, "accounts_app - account add", "Unknown step: %s" % step)
                    return HttpResponseBadRequest()
                
            template = get_template(TEMPLATE_FORM_PATH % object)
            cache.set(formset_id, formset)
            context = Context({"form": new_form, "step": formset["step"], "action": action, "object": account_obj})
            return HttpResponse(json.dumps({"ok": 1, "html": template.render(context)}),
                                mimetype="application/json")
    
    # No formset is found. Therefore, we conclude this is the first step.
    object = request.POST.get("object", request.GET.get("object", ""))
    if not object in ("user", "group"):
        log(3, "accounts_app - account add", "An alien object type '%s' has been spotted" % object)
        return HttpResponseBadRequest()
    
    # Create a new formset
    cache.delete(formset_id)
    formset_id = gen_formset_id(CACHE_FORMSET[action], object)
    form_obj = get_form(object, action, 1)
    
    if action == "add":
        data = {}
        form = form_obj()
    else: # action == "edit"
        if object == "user":
            account_obj = WenixUser.objects.get(pk=instance_id)
            data = {"groups": map(lambda x: str(int(x)), account_obj.groups.all().values_list("id", flat=True))}
            form = form_obj(instance=account_obj)
        else: # object == "group"
            account_obj = WenixGroup.objects.get(pk=instance_id)
            data = {"users": map(lambda x: str(int(x)), WenixUser.objects.filter(groups__name=account_obj.name).values_list("id", flat=True))}
            form = form_obj(initial=data)
    
    # An ugly way to initialize users list
    if object == "group":
        form["users"].field.choices = id_and_name_to_dict(request.user, mode, "user")
    
    cache.set(formset_id, {"object": object, "step": 1, "data": data})
    response = render_to_response(TEMPLATE_FORM_PATH % object, {"form": form, "step": 1, "action": action, "object": account_obj})
    response.set_cookie("formset_id", formset_id, FORMSET_ID_MAXAGE)
    return response
Exemple #10
0
 def post(self, body_, current_user):
     """
     创建新用户
     """
     res = AppSetting.general_result()
     res["request_info"] = self.request_info
     if not Permission.check_user_role(self.edit_roles,
                                       current_user["roles"]):
         res["err_code"] = APIStatus.ROLE_FORBIDDEN
         res["message"] = "user role is forbidden: {}".format(
             current_user["username"])
         res["result"] = "fail"
         return res
     # print(body_)
     for field in self.fields_require:
         if field not in body_:
             res["err_code"] = APIStatus.FIELD_LACK
             res["message"] = "field lack: {}".format(field)
             res["result"] = "fail"
             return res
     for field in list(body_.keys()):
         if field not in self.fields_border:
             body_.pop(field)
     try:
         self._check_unique_field(body_,
                                  self.controller.get_model().unique_list)
     except Exception as err:
         res["err_code"] = APIStatus.ALREADY_EXIST
         res["message"] = str(err)
         res["result"] = "fail"
         return res
     try:
         key_word = self.controller.get_model().key_word
         table_name = self.controller.get_model().table_name
         search_res = self.controller.search_keyword_on_create(
             key_word=body_[key_word])
         if search_res:
             if search_res["deleted"] is None or search_res["deleted"] == "":
                 res["err_code"] = APIStatus.ALREADY_EXIST
                 res["message"] = "{table_name} [{key_word}] is already exist".format(
                     table_name=table_name, key_word=body_[key_word])
                 res["result"] = "fail"
                 return res
             else:
                 uid = search_res["uid"]
                 body_["deleted"] = None
                 self.controller.update(uid, **body_)
                 res["data"] = {"uid": uid}
         else:
             res["data"] = {"uid": self.controller.create(**body_)}
     except SQLAlchemyError as err:
         res["err_code"] = APIStatus.DB_ERROR
         res["message"] = json.dumps(err.orig.args)
         res["result"] = "fail"
     except Exception as err:
         res["err_code"] = APIStatus.UNDEFINED
         res["message"] = str(err)
         res["result"] = "fail"
     else:
         res["err_code"] = APIStatus.SUCCESS
     return res