Skip to content

Commit adae9d9

Browse files
authored
Merge pull request #38 from epochtalk/role-validate
Role validate
2 parents 74f3168 + 0ef9174 commit adae9d9

File tree

5 files changed

+205
-138
lines changed

5 files changed

+205
-138
lines changed

lib/epochtalk_server/models/role_permission.ex

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -58,56 +58,72 @@ defmodule EpochtalkServer.Models.RolePermission do
5858
def insert([%{} | _] = roles_permissions),
5959
do: Repo.insert_all(RolePermission, roles_permissions)
6060

61-
## for admin api use, modifying permissions for a role
61+
@doc """
62+
For admin api use.
63+
64+
Updates the `modified` value of `RolePermission`s for a `Role`
65+
and updates the `Role`'s permissions and priority restrictions
66+
67+
If a permission is not included in `new_permissions`, it will be set to
68+
`false`. `new_permissions` may be an empty list - in which case, all
69+
permissions will be set to `false`.
70+
71+
Any permissions in `new_permissions` which are not valid will be ignored.
72+
"""
73+
@spec modify_by_role(role :: Role.t()) :: {:ok, :success}
6274
def modify_by_role(
6375
%Role{
6476
id: role_id,
6577
permissions: new_permissions,
6678
priority_restrictions: priority_restrictions
6779
} = _new_role
6880
) do
69-
# if a permission is false, they're not included in the permissions
70-
# if they're all false, permissions can be empty
71-
old_role_permissions =
72-
from(rp in RolePermission,
73-
where: rp.role_id == ^role_id
74-
)
75-
|> Repo.all()
76-
77-
new_permissions = new_permissions |> Iteraptor.to_flatmap()
78-
79-
# change a permission if it's different
80-
new_role_permissions =
81-
Enum.reduce(old_role_permissions, [], fn %{
82-
permission_path: permission_path,
83-
value: old_value
84-
} = _old_role_permission,
85-
acc ->
86-
# check new value for permission_path
87-
# if value is not there, set it to false
88-
new_value = new_permissions[permission_path] || false
89-
# if new value is different
90-
new_role_permission =
91-
if old_value != new_value do
92-
# set modified true
93-
%{role_id: role_id, permission_path: permission_path, modified: true}
94-
# if new value is same, set modified false
95-
else
96-
%{role_id: role_id, permission_path: permission_path, modified: false}
97-
end
98-
99-
[new_role_permission | acc]
100-
end)
101-
102-
# update role permissions for this role
103-
upsert_modified(new_role_permissions)
104-
105-
# update role's permissions
106-
permissions = RolePermission.permissions_map_by_role_id(role_id)
107-
Role.set_permissions(role_id, permissions)
108-
109-
# update role's priority_restrictions
110-
Role.set_priority_restrictions(role_id, priority_restrictions)
81+
if is_map(new_permissions) do
82+
# get current set of role permissions
83+
current_role_permissions =
84+
from(rp in RolePermission,
85+
where: rp.role_id == ^role_id
86+
)
87+
|> Repo.all()
88+
89+
# flat map the new permissions into permissions paths
90+
new_permissions_paths = new_permissions |> Iteraptor.to_flatmap()
91+
92+
# calculate updated role permissions based on default values
93+
new_role_permissions =
94+
Enum.reduce(current_role_permissions, [], fn %{
95+
permission_path: permission_path,
96+
value: default_value
97+
} = _current_role_permission,
98+
acc ->
99+
# get new value for permission_path if it exists
100+
# otherwise, set it to false
101+
new_value = new_permissions_paths[permission_path] || false
102+
103+
new_role_permission =
104+
if default_value != new_value do
105+
# if new value is different from default value, set modified true
106+
%{role_id: role_id, permission_path: permission_path, modified: true}
107+
else
108+
# if new value is same as default value, set modified false
109+
%{role_id: role_id, permission_path: permission_path, modified: false}
110+
end
111+
112+
[new_role_permission | acc]
113+
end)
114+
115+
# update role permissions for this role
116+
upsert_modified(new_role_permissions)
117+
118+
# update role's permissions
119+
permissions = RolePermission.permissions_map_by_role_id(role_id)
120+
Role.set_permissions(role_id, permissions)
121+
end
122+
123+
if is_list(priority_restrictions) do
124+
# update role's priority_restrictions
125+
Role.set_priority_restrictions(role_id, priority_restrictions)
126+
end
111127

112128
# return success
113129
{:ok, :success}

lib/epochtalk_server_web/controllers/role_controller.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ defmodule EpochtalkServerWeb.RoleController do
1919
:ok <- ACL.allow!(conn, "roles.update"),
2020
id <- Validate.cast(attrs, "id", :integer, min: 1),
2121
# TODO(boka): implement validators
22-
priority_restrictions <- Validate.sanitize_list(attrs, "priority_restrictions"),
22+
priority_restrictions <- attrs["priority_restrictions"],
2323
permissions <- attrs["permissions"],
2424
{:ok, data} <-
2525
RolePermission.modify_by_role(%Role{

lib/epochtalk_server_web/helpers/validate.ex

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@ defmodule EpochtalkServerWeb.Helpers.Validate do
66
"""
77
alias EpochtalkServerWeb.CustomErrors.InvalidPayload
88

9-
@doc """
10-
Helper used to default a list request parameter. If the list is valid, returns the list
11-
otherwise, defaults to empty list
12-
"""
13-
@spec sanitize_list(attrs :: map, key :: String.t()) :: [any()] | []
14-
def sanitize_list(attrs, key)
15-
when is_map(attrs) and is_binary(key),
16-
do: if(is_list(attrs[key]), do: attrs[key], else: [])
17-
189
@doc """
1910
Helper used to validate and cast request parameters directly out of the incoming
2011
paylod map (usually a controller function's `attrs` parameter) to the specified type.

test/epochtalk_server/session_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ defmodule EpochtalkServerWeb.SessionTest do
5959
test "deletes an expired user session when logging in", %{conn: conn, user: user} do
6060
remember_me = false
6161
# create session that should be deleted
62-
{:ok, authed_user_to_delete, _token, authed_conn_to_delete} =
62+
{:ok, _authed_user_to_delete, _token, authed_conn_to_delete} =
6363
Session.create(user, remember_me, conn)
6464

6565
session_id_to_delete = authed_conn_to_delete.private.guardian_default_claims["jti"]
6666
# create session that shouldn't be deleted
67-
{:ok, authed_user_to_persist, _token, authed_conn_to_persist} =
67+
{:ok, _authed_user_to_persist, _token, authed_conn_to_persist} =
6868
Session.create(user, remember_me, conn)
6969

7070
session_id_to_persist = authed_conn_to_persist.private.guardian_default_claims["jti"]
@@ -94,7 +94,7 @@ defmodule EpochtalkServerWeb.SessionTest do
9494
])
9595

9696
# create a new session (should delete expired sessions)
97-
{:ok, new_authed_user, _token, new_authed_conn} = Session.create(user, remember_me, conn)
97+
{:ok, _new_authed_user, _token, new_authed_conn} = Session.create(user, remember_me, conn)
9898
new_session_id = new_authed_conn.private.guardian_default_claims["jti"]
9999
# check that active sessions are still active
100100
{:ok, resource_to_persist} = Session.get_resource(user.id, session_id_to_persist)

0 commit comments

Comments
 (0)