Exemplo n.º 1
0
    def edit_user_or_group_resource_permissions(self,
                                                user_or_group_name,
                                                resource_id,
                                                is_user=False):
        if is_user:
            res_perms_path = schemas.UserResourcePermissionsAPI.path \
                .format(user_name=user_or_group_name, resource_id=resource_id)
        else:
            res_perms_path = schemas.GroupResourcePermissionsAPI.path \
                .format(group_name=user_or_group_name, resource_id=resource_id)
        try:
            resp = request_api(self.request, res_perms_path, "GET")
            res_perms = get_json(resp)["permission_names"]
        except Exception as e:
            raise HTTPBadRequest(detail=repr(e))

        selected_perms = self.request.POST.getall("permission")

        removed_perms = list(set(res_perms) - set(selected_perms))
        new_perms = list(set(selected_perms) - set(res_perms))

        for perm in removed_perms:
            path = "{path}/{perm}".format(path=res_perms_path, perm=perm)
            resp = request_api(self.request, path, "DELETE")
            check_response(resp)
        for perm in new_perms:
            data = {u"permission_name": perm}
            resp = request_api(self.request, res_perms_path, "POST", data=data)
            check_response(resp)
        return removed_perms, new_perms
Exemplo n.º 2
0
    def add_group(self):
        return_data = {
            u"conflict_group_name": False,
            u"invalid_group_name": False,
            u"form_group_name": u""
        }

        if "create" in self.request.POST:
            group_name = self.request.POST.get("group_name")
            return_data[u"form_group_name"] = group_name
            if group_name == "":
                return_data[u"invalid_group_name"] = True
                return add_template_data(self.request, return_data)

            data = {u"group_name": group_name}
            resp = request_api(self.request,
                               schemas.GroupsAPI.path,
                               "POST",
                               data=data)
            if resp.status_code == HTTPConflict.code:
                return_data[u"conflict_group_name"] = True
                return add_template_data(self.request, return_data)

            check_response(resp)  # check for any other exception than conflict
            return HTTPFound(self.request.route_url("view_groups"))

        return add_template_data(self.request, return_data)
Exemplo n.º 3
0
    def edit_group_users(self, group_name):
        current_members = self.get_group_users(group_name)
        selected_members = self.request.POST.getall("member")
        removed_members = list(set(current_members) - set(selected_members))
        new_members = list(set(selected_members) - set(current_members))

        for user_name in removed_members:
            path = schemas.UserGroupAPI.path.format(user_name=user_name,
                                                    group_name=group_name)
            resp = request_api(self.request, path, "DELETE")
            check_response(resp)
        for user_name in new_members:
            path = schemas.UserGroupsAPI.path.format(user_name=user_name)
            data = {"group_name": group_name}
            resp = request_api(self.request, path, "POST", data=data)
            check_response(resp)
Exemplo n.º 4
0
 def goto_service(self, resource_id):
     path = schemas.ResourceAPI.path.format(resource_id=resource_id)
     resp = request_api(self.request, path, "GET")
     check_response(resp)
     body = get_json(resp)
     svc_name = body["resource"]["resource_name"]
     # get service type instead of 'cur_svc_type' in case of 'default' ('cur_svc_type' not set yet)
     path = schemas.ServiceAPI.path.format(service_name=svc_name)
     resp = request_api(self.request, path, "GET")
     check_response(resp)
     body = get_json(resp)
     svc_type = body["service"]["service_type"]
     return HTTPFound(
         self.request.route_url("edit_service",
                                service_name=svc_name,
                                cur_svc_type=svc_type))
Exemplo n.º 5
0
 def update_service_url(self, service_name, new_service_url, service_push):
     svc_data = self.get_service_data(service_name)
     svc_data["service_url"] = new_service_url
     svc_data["service_push"] = service_push
     path = schemas.ServiceAPI.path.format(service_name=service_name)
     resp = request_api(self.request, path, "PUT", data=svc_data)
     check_response(resp)
Exemplo n.º 6
0
 def get_all_groups(self, first_default_group=None):
     resp = request_api(self.request, schemas.GroupsAPI.path, "GET")
     check_response(resp)
     groups = list(get_json(resp)["group_names"])
     if isinstance(first_default_group,
                   six.string_types) and first_default_group in groups:
         groups.remove(first_default_group)
         groups.insert(0, first_default_group)
     return groups
Exemplo n.º 7
0
 def get_services(self, cur_svc_type):
     resp = request_api(self.request, schemas.ServicesAPI.path, "GET")
     check_response(resp)
     all_services = get_json(resp)["services"]
     svc_types = sorted(all_services.keys())
     if cur_svc_type not in svc_types:
         cur_svc_type = svc_types[0]
     services = all_services[cur_svc_type]
     return svc_types, cur_svc_type, services
Exemplo n.º 8
0
    def join_discoverable_group(self, group_name):
        """
        Registers the current user to the discoverable group.

        :raises HTTPBadRequest: if the operation is not valid.
        """
        path = schemas.RegisterGroupAPI.path.format(group_name=group_name)
        resp = request_api(self.request, path, "POST", data={})
        check_response(resp)
Exemplo n.º 9
0
 def get_user_emails(self):
     user_names = self.get_user_names()
     emails = list()
     for user in user_names:
         path = schemas.UserAPI.path.format(user_name=user)
         resp = request_api(self.request, path, "GET")
         check_response(resp)
         user_email = get_json(resp)["user"]["email"]
         emails.append(user_email)
     return emails
Exemplo n.º 10
0
 def delete_resource(self, res_id):
     try:
         path = schemas.ResourceAPI.path.format(resource_id=res_id)
         resp = request_api(self.request, path, "DELETE")
         check_response(resp)
     except HTTPNotFound:
         # Some resource ids are already deleted because they were a child
         # of another just deleted parent resource.
         # We just skip them.
         pass
Exemplo n.º 11
0
 def update_service_name(self, old_service_name, new_service_name,
                         service_push):
     svc_data = self.get_service_data(old_service_name)
     svc_data["service_name"] = new_service_name
     svc_data["resource_name"] = new_service_name
     svc_data["service_push"] = service_push
     svc_id = str(svc_data["resource_id"])
     path = schemas.ResourceAPI.path.format(resource_id=svc_id)
     resp = request_api(self.request, path, "PUT", data=svc_data)
     check_response(resp)
Exemplo n.º 12
0
    def leave_discoverable_group(self, group_name):
        # type: (Str) -> None
        """
        Unregisters the current user from the discoverable group.

        :raises HTTPBadRequest: if the operation is not valid.
        """
        path = schemas.RegisterGroupAPI.path.format(group_name=group_name)
        resp = request_api(self.request, path, "DELETE")
        check_response(resp)
Exemplo n.º 13
0
 def get_resource_types(self):
     """
     :return: dictionary of all resources as {id: 'resource_type'}
     :rtype: dict
     """
     resp = request_api(self.request, schemas.ResourcesAPI.path, "GET")
     check_response(resp)
     res_dic = self.default_get(get_json(resp), "resources", dict())
     res_ids = dict()
     self.flatten_tree_resource(res_dic, res_ids)
     return res_ids
Exemplo n.º 14
0
    def login(self):
        external_providers = self.request_providers_json()["external"]
        return_data = {
            "external_providers": external_providers,
            "user_name_external": self.request.POST.get("user_name", ""),
            "user_name_internal": self.request.POST.get("user_name", ""),
            "invalid_credentials": False,
            "error": False,
        }

        try:
            if "submit" in self.request.POST:
                data = {}
                for key in self.request.POST:
                    data[key] = self.request.POST.get(key)

                return_data["provider_name"] = data.get("provider_name", "").lower()
                is_external = return_data["provider_name"] in [p.lower() for p in external_providers]
                if is_external:
                    return_data["user_name_internal"] = ""
                else:
                    return_data["user_name_external"] = ""

                # keep using the external requests for external providers
                if is_external:
                    signin_url = "{}{}".format(self.magpie_url, schemas.SigninAPI.path)
                    response = requests.post(signin_url, data=data, allow_redirects=True)
                # use sub request for internal to avoid retry connection errors
                else:
                    response = request_api(self.request, schemas.SigninAPI.path, "POST", data=data)

                if response.status_code in (HTTPOk.code, HTTPFound.code):
                    if is_external:
                        pyr_res = Response(body=response.content, headers=response.headers)
                        for cookie in response.cookies:
                            pyr_res.set_cookie(name=cookie.name, value=cookie.value, overwrite=True)
                        return HTTPFound(response.url, headers=pyr_res.headers)
                    return HTTPFound(location=self.request.route_url("home"), headers=response.headers)

                if response.status_code == HTTPUnauthorized.code:
                    return_data["invalid_credentials"] = True
                else:
                    return_data["error"] = True
        except HTTPException as exc:
            if exc.status_code == HTTPUnauthorized.code:
                return_data["invalid_credentials"] = True
            else:
                return_data["error"] = True
        except Exception as exc:
            return HTTPInternalServerError(detail=repr(exc))

        return self.add_template_data(data=return_data)
Exemplo n.º 15
0
 def get_service_resources(self, service_name):
     resources = {}
     path = schemas.ServiceResourcesAPI.path.format(
         service_name=service_name)
     resp = request_api(self.request, path, "GET")
     check_response(resp)
     raw_resources = get_json(resp)[service_name]
     resources[service_name] = dict(id=raw_resources["resource_id"],
                                    permission_names=[],
                                    children=self.resource_tree_parser(
                                        raw_resources["resources"], {}))
     resources_id_type = self.get_resource_types()
     return resources, resources_id_type
Exemplo n.º 16
0
    def add_resource(self):
        cur_svc_type = self.request.matchdict["cur_svc_type"]
        service_name = self.request.matchdict["service_name"]
        resource_id = self.request.matchdict["resource_id"]

        if "add_child" in self.request.POST:
            resource_name = self.request.POST.get("resource_name")
            resource_type = self.request.POST.get("resource_type")

            data = {
                u"resource_name": resource_name,
                u"resource_type": resource_type,
                u"parent_id": int(resource_id) if resource_id else None
            }
            resp = request_api(self.request,
                               schemas.ResourcesAPI.path,
                               "POST",
                               data=data,
                               headers={"Content-Type": CONTENT_TYPE_JSON})
            check_response(resp)

            return HTTPFound(
                self.request.route_url("edit_service",
                                       service_name=service_name,
                                       cur_svc_type=cur_svc_type))

        path = schemas.ServiceTypeResourceTypesAPI.path.format(
            service_type=cur_svc_type)
        resp = request_api(self.request, path, "GET")
        check_response(resp)
        svc_res_types = get_json(resp)["resource_types"]
        data = {
            u"service_name": service_name,
            u"cur_svc_type": cur_svc_type,
            u"resource_id": resource_id,
            u"cur_svc_res": svc_res_types,
        }
        return add_template_data(self.request, data)
Exemplo n.º 17
0
    def view_users(self):
        if "delete" in self.request.POST:
            user_name = self.request.POST.get("user_name")
            path = schemas.UserAPI.path.format(user_name=user_name)
            resp = request_api(self.request, path, "DELETE")
            check_response(resp)

        if "edit" in self.request.POST:
            user_name = self.request.POST.get("user_name")
            return HTTPFound(
                self.request.route_url("edit_user",
                                       user_name=user_name,
                                       cur_svc_type="default"))

        return add_template_data(self.request,
                                 {"users": self.get_user_names()})
Exemplo n.º 18
0
    def add_remote_resource(self,
                            service_type,
                            services_names,
                            user_or_group,
                            remote_id,
                            is_user=False):
        try:
            res_perm_names, res_perms = self.get_user_or_group_resources_permissions_dict(
                user_or_group,
                services=services_names,
                service_type=service_type,
                is_user=is_user)
        except Exception as e:
            raise HTTPBadRequest(detail=repr(e))

        # get the parent resources for this remote_id
        # TODO:
        #   Until the api is modified to make it possible to request from the RemoteResource table,
        #   we have to access the database directly here
        session = self.request.db
        parents = remote_resource_tree_service.path_upper(remote_id,
                                                          db_session=session)
        parents = list(reversed(list(parents)))

        parent_id = None
        current_resources = res_perms
        for remote_resource in parents:
            name = remote_resource.resource_name
            if name in current_resources:
                parent_id = current_resources[name]["id"]
                current_resources = current_resources[name]["children"]
            else:
                data = {
                    "resource_name": name,
                    "resource_display_name":
                    remote_resource.resource_display_name,
                    "resource_type": remote_resource.resource_type,
                    "parent_id": parent_id,
                }
                resp = request_api(self.request,
                                   schemas.ResourcesAPI.path,
                                   "POST",
                                   data=data)
                check_response(resp)
                parent_id = get_json(resp)["resource"]["resource_id"]

        return parent_id
Exemplo n.º 19
0
    def view_groups(self):
        if "delete" in self.request.POST:
            group_name = self.request.POST.get("group_name")
            path = schemas.GroupAPI.path.format(group_name=group_name)
            resp = request_api(self.request, path, "DELETE")
            check_response(resp)

        if "edit" in self.request.POST:
            group_name = self.request.POST.get("group_name")
            return HTTPFound(
                self.request.route_url("edit_group",
                                       group_name=group_name,
                                       cur_svc_type="default"))

        groups_info = {}
        groups = sorted(self.get_all_groups())
        for grp in groups:
            if grp != u"":
                groups_info.setdefault(
                    grp, {u"members": len(self.get_group_users(grp))})
        return add_template_data(self.request, {u"group_names": groups_info})
Exemplo n.º 20
0
    def view_services(self):
        if "delete" in self.request.POST:
            service_name = self.request.POST.get("service_name")
            service_data = {
                u"service_push": self.request.POST.get("service_push")
            }
            path = schemas.ServiceAPI.path.format(service_name=service_name)
            resp = request_api(self.request,
                               path,
                               "DELETE",
                               data=json.dumps(service_data))
            check_response(resp)

        cur_svc_type = self.request.matchdict["cur_svc_type"]
        svc_types, cur_svc_type, services = self.get_services(cur_svc_type)
        service_names = services.keys()

        success_sync = None
        if "phoenix_push" in self.request.POST:
            if cur_svc_type in register.SERVICES_PHOENIX_ALLOWED:
                success_sync = register.sync_services_phoenix(
                    services, services_as_dicts=True)

        if "edit" in self.request.POST:
            service_name = self.request.POST.get("service_name")
            return HTTPFound(
                self.request.route_url("edit_service",
                                       service_name=service_name,
                                       cur_svc_type=cur_svc_type))

        return add_template_data(
            self.request, {
                u"cur_svc_type": cur_svc_type,
                u"svc_types": svc_types,
                u"service_names": service_names,
                u"service_push_show": cur_svc_type
                in register.SERVICES_PHOENIX_ALLOWED,
                u"service_push_success": success_sync
            })
Exemplo n.º 21
0
    def add_service(self):
        cur_svc_type = self.request.matchdict["cur_svc_type"]
        svc_types, cur_svc_type, services = self.get_services(cur_svc_type)

        if "register" in self.request.POST:
            service_name = self.request.POST.get("service_name")
            service_url = self.request.POST.get("service_url")
            service_type = self.request.POST.get("service_type")
            service_push = self.request.POST.get("service_push")
            data = {
                u"service_name": service_name,
                u"service_url": service_url,
                u"service_type": service_type,
                u"service_push": service_push
            }
            resp = request_api(self.request,
                               schemas.ServicesAPI.path,
                               "POST",
                               data=data)
            check_response(resp)
            return HTTPFound(
                self.request.route_url("view_services",
                                       cur_svc_type=service_type))

        services_keys_sorted = self.get_service_types()
        services_phoenix_indices = [
            (1 if services_keys_sorted[i] in register.SERVICES_PHOENIX_ALLOWED
             else 0) for i in range(len(services_keys_sorted))
        ]
        return add_template_data(
            self.request, {
                u"cur_svc_type": cur_svc_type,
                u"service_types": svc_types,
                u"services_phoenix": register.SERVICES_PHOENIX_ALLOWED,
                u"services_phoenix_indices": services_phoenix_indices
            })
Exemplo n.º 22
0
 def get_user_names(self):
     resp = request_api(self.request, schemas.UsersAPI.path, "GET")
     check_response(resp)
     return get_json(resp)["user_names"]
Exemplo n.º 23
0
 def get_discoverable_groups(self):
     # type: () -> List[str]
     resp = request_api(self.request, schemas.RegisterGroupsAPI.path, "GET")
     check_response(resp)
     return get_json(resp)["group_names"]
Exemplo n.º 24
0
 def get_current_user_info(self):
     # type: () -> JSON
     user_resp = request_api(self.request, schemas.LoggedUserAPI.path,
                             "GET")
     check_response(user_resp)
     return get_json(user_resp)["user"]
Exemplo n.º 25
0
 def get_current_user_groups(self):
     # type: () -> List[str]
     resp = request_api(self.request, schemas.LoggedUserGroupsAPI.path,
                        "GET")
     check_response(resp)
     return get_json(resp)["group_names"]
Exemplo n.º 26
0
 def get_group_users(self, group_name):
     path = schemas.GroupUsersAPI.path.format(group_name=group_name)
     resp = request_api(self.request, path, "GET")
     check_response(resp)
     return get_json(resp)["user_names"]
Exemplo n.º 27
0
 def get_user_groups(self, user_name):
     path = schemas.UserGroupsAPI.path.format(user_name=user_name)
     resp = request_api(self.request, path, "GET")
     check_response(resp)
     return get_json(resp)["group_names"]
Exemplo n.º 28
0
    def get_user_or_group_resources_permissions_dict(
            self,
            user_or_group_name,
            services,
            service_type,
            is_user=False,
            is_inherit_groups_permissions=False):
        if is_user:
            query = "?inherit=true" if is_inherit_groups_permissions else ""
            path = schemas.UserResourcesAPI.path.format(
                user_name=user_or_group_name) + query
        else:
            path = schemas.GroupResourcesAPI.path.format(
                group_name=user_or_group_name)

        resp_group_perms = request_api(self.request, path, "GET")
        check_response(resp_group_perms)
        resp_group_perms_json = get_json(resp_group_perms)

        path = schemas.ServiceTypeAPI.path.format(service_type=service_type)
        resp = request_api(self.request, path, "GET")
        check_response(resp)
        resp_available_svc_types = get_json(resp)["services"][service_type]

        # remove possible duplicate permissions from different services
        resources_permission_names = set()
        for svc in resp_available_svc_types:
            resources_permission_names.update(
                set(resp_available_svc_types[svc]["permission_names"]))
        # inverse sort so that displayed permissions are sorted, since added from right to left in tree view
        resources_permission_names = sorted(resources_permission_names,
                                            reverse=True)

        resources = OrderedDict()
        for service in sorted(services):
            if not service:
                continue

            permission = OrderedDict()
            try:
                raw_perms = resp_group_perms_json["resources"][service_type][
                    service]
                permission[
                    raw_perms["resource_id"]] = raw_perms["permission_names"]
                permission.update(self.perm_tree_parser(
                    raw_perms["resources"]))
            except KeyError:
                pass

            path = schemas.ServiceResourcesAPI.path.format(
                service_name=service)
            resp = request_api(self.request, path, "GET")
            check_response(resp)
            raw_resources = get_json(resp)[service]
            resources[service] = OrderedDict(
                id=raw_resources["resource_id"],
                permission_names=self.default_get(permission,
                                                  raw_resources["resource_id"],
                                                  []),
                children=self.resource_tree_parser(raw_resources["resources"],
                                                   permission))
        return resources_permission_names, resources
Exemplo n.º 29
0
    def edit_current_user(self):
        joined_groups = self.get_current_user_groups()
        public_groups = self.get_discoverable_groups()
        user_info = self.get_current_user_info()
        user_info["edit_mode"] = "no_edit"
        user_info["joined_groups"] = joined_groups
        user_info["groups"] = public_groups
        # reset error messages/flags
        user_info["error_message"] = ""
        for field in ["password", "user_email", "user_name"]:
            user_info["invalid_" + field] = ""
            user_info["reason_" + field] = ""

        if self.request.method == "POST":
            is_edit_group_membership = False
            is_save_user_info = False

            if "edit_group_membership" in self.request.POST:
                is_edit_group_membership = True
            elif "edit_password" in self.request.POST:
                user_info["edit_mode"] = "edit_password"
            elif "edit_email" in self.request.POST:
                user_info["edit_mode"] = "edit_email"
            elif "save_password" in self.request.POST:
                user_info["password"] = self.request.POST.get(
                    "new_user_password")
                is_save_user_info = True
            elif "save_email" in self.request.POST:
                user_info["email"] = self.request.POST.get("new_user_email")
                is_save_user_info = True
            elif "delete" in self.request.POST:
                delete_response = request_api(
                    self.request,
                    schemas.UserAPI.path.format(
                        user_name=user_info["user_name"]), "DELETE")
                check_response(delete_response)
                logout_response = request_api(self.request,
                                              schemas.SignoutAPI.path, "GET")
                check_response(logout_response)
                return HTTPFound(location="/")

            if is_save_user_info:
                resp = request_api(self.request,
                                   schemas.LoggedUserAPI.path,
                                   "PATCH",
                                   data=user_info)
                if resp.status_code in (HTTPBadRequest.code,
                                        HTTPUnprocessableEntity.code):
                    # attempt to retrieve the API specific reason why the operation is invalid
                    body = get_json(resp)
                    param_name = body.get("param", {}).get("name")
                    reason = body.get("detail", "Invalid")
                    user_info.pop("password",
                                  None)  # always remove password from output
                    if param_name == "password":
                        user_info["invalid_password"] = True
                        user_info["reason_password"] = reason
                        return self.add_template_data(user_info)
                    if param_name == "user_email":
                        user_info["invalid_user_email"] = True
                        user_info["reason_user_email"] = reason
                        return self.add_template_data(user_info)
                # fail if unknown bad request reason or other error type
                check_response(resp)
                # need to commit updates since we are using the same session
                # otherwise, updated user doesn't exist yet in the db for next calls
                self.request.tm.commit()

            # edits to groups checkboxes
            if is_edit_group_membership:
                selected_groups = self.request.POST.getall("member")
                removed_groups = list(
                    set(joined_groups) - set(selected_groups))
                new_groups = list(set(selected_groups) - set(joined_groups))
                for group in removed_groups:
                    self.leave_discoverable_group(group)
                for group in new_groups:
                    self.join_discoverable_group(group)
                user_info["joined_groups"] = self.get_current_user_groups()

        user_info.pop("password", None)  # always remove password from output
        return self.add_template_data(data=user_info)
Exemplo n.º 30
0
    def edit_group(self):
        group_name = self.request.matchdict["group_name"]
        cur_svc_type = self.request.matchdict["cur_svc_type"]
        group_info = {
            u"edit_mode": u"no_edit",
            u"group_name": group_name,
            u"cur_svc_type": cur_svc_type
        }

        error_message = ""

        # TODO:
        #   Until the api is modified to make it possible to request from the RemoteResource table,
        #   we have to access the database directly here
        session = self.request.db

        try:
            # The service type is 'default'. This function replaces cur_svc_type with the first service type.
            svc_types, cur_svc_type, services = self.get_services(cur_svc_type)
        except Exception as e:
            raise HTTPBadRequest(detail=repr(e))

        # In case of update, changes are not reflected when calling
        # get_user_or_group_resources_permissions_dict so we must take care
        # of them
        res_id = None
        removed_perms = None
        new_perms = None

        # move to service or edit requested group/permission changes
        if self.request.method == "POST":
            res_id = self.request.POST.get("resource_id")
            group_path = schemas.GroupAPI.path.format(group_name=group_name)

            if u"delete" in self.request.POST:
                resp = request_api(self.request, group_path, "DELETE")
                check_response(resp)
                return HTTPFound(self.request.route_url("view_groups"))
            elif u"edit_group_name" in self.request.POST:
                group_info[u"edit_mode"] = u"edit_group_name"
            elif u"save_group_name" in self.request.POST:
                group_info[u"group_name"] = self.request.POST.get(
                    u"new_group_name")
                resp = request_api(self.request,
                                   group_path,
                                   "PUT",
                                   data=group_info)
                check_response(resp)
                # return immediately with updated URL to group with new name
                return HTTPFound(
                    self.request.route_url("edit_group", **group_info))
            elif u"goto_service" in self.request.POST:
                return self.goto_service(res_id)
            elif u"clean_resource" in self.request.POST:
                # "clean_resource" must be above "edit_permissions" because they"re in the same form.
                self.delete_resource(res_id)
            elif u"edit_permissions" in self.request.POST:
                if not res_id or res_id == "None":
                    remote_id = int(self.request.POST.get("remote_id"))
                    services_names = [
                        s["service_name"] for s in services.values()
                    ]
                    res_id = self.add_remote_resource(cur_svc_type,
                                                      services_names,
                                                      group_name,
                                                      remote_id,
                                                      is_user=False)
                removed_perms, new_perms = \
                    self.edit_user_or_group_resource_permissions(group_name, res_id, is_user=False)
            elif u"member" in self.request.POST:
                self.edit_group_users(group_name)
            elif u"force_sync" in self.request.POST:
                errors = []
                for service_info in services.values():
                    # noinspection PyBroadException
                    try:
                        sync_resources.fetch_single_service(
                            service_info["resource_id"], session)
                    except Exception:
                        errors.append(service_info["service_name"])
                if errors:
                    error_message += self.make_sync_error_message(errors)

            elif u"clean_all" in self.request.POST:
                ids_to_clean = self.request.POST.get("ids_to_clean").split(";")
                for id_ in ids_to_clean:
                    self.delete_resource(id_)
            else:
                return HTTPBadRequest(detail="Invalid POST request.")

        # display resources permissions per service type tab
        try:
            res_perm_names, res_perms = self.get_user_or_group_resources_permissions_dict(
                group_name, services, cur_svc_type, is_user=False)
        except Exception as e:
            raise HTTPBadRequest(detail=repr(e))

        if res_id and (removed_perms or new_perms):
            self.update_user_or_group_resources_permissions_dict(
                res_perms, res_id, removed_perms, new_perms)

        sync_types = [s["service_sync_type"] for s in services.values()]
        sync_implemented = any(s in sync_resources.SYNC_SERVICES_TYPES
                               for s in sync_types)

        info = self.get_remote_resources_info(res_perms, services, session)
        res_perms, ids_to_clean, last_sync_humanized, out_of_sync = info

        if out_of_sync:
            error_message = self.make_sync_error_message(out_of_sync)

        group_info[u"error_message"] = error_message
        group_info[u"ids_to_clean"] = ";".join(ids_to_clean)
        group_info[u"last_sync"] = last_sync_humanized
        group_info[u"sync_implemented"] = sync_implemented
        group_info[u"out_of_sync"] = out_of_sync
        group_info[u"group_name"] = group_name
        group_info[u"cur_svc_type"] = cur_svc_type
        group_info[u"users"] = self.get_user_names()
        group_info[u"members"] = self.get_group_users(group_name)
        group_info[u"svc_types"] = svc_types
        group_info[u"cur_svc_type"] = cur_svc_type
        group_info[u"resources"] = res_perms
        group_info[u"permissions"] = res_perm_names
        return add_template_data(self.request, data=group_info)