Skip to content

Commit

Permalink
Begin work on showing admins and admin groups that admins can view.
Browse files Browse the repository at this point in the history
When limited admins have view privileges and they are viewing groups,
the groups were returning all admins that belong to those groups.
However, if viewing the admin show/index pages, some of those admins
would be missing, since the limited admin could only view admins they
have full privileges to edit (so they need to be authorized to all of
the groups that admin belongs to). While this is the correct permissions
for editing admins, we want to loosen the ability to view/show those
admins, so the admin listings can be more complete.

At the same time, when viewing admins, we then need to ensure we only
return groups that the limited admin should know about, and not
necessarily all of the groups that the admin belongs to (since they
might be groups outside of the limited admin's privileges).
  • Loading branch information
GUI committed Jan 24, 2024
1 parent 2404ef4 commit 404c2cc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 13 deletions.
9 changes: 9 additions & 0 deletions src/api-umbrella/web-app/models/admin.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local ApiScope = require "api-umbrella.web-app.models.api_scope"
local admin_group_policy = require "api-umbrella.web-app.policies.admin_group_policy"
local admin_policy = require "api-umbrella.web-app.policies.admin_policy"
local api_backend_policy = require "api-umbrella.web-app.policies.api_backend_policy"
local bcrypt = require "bcrypt"
Expand Down Expand Up @@ -99,6 +100,14 @@ Admin = model_ext.new_class("admins", {
foreign_key = "admin_id",
association_foreign_key = "admin_group_id",
order = "name",
transform_sql = function(sql)
local scope_sql = admin_group_policy.authorized_query_scope(ngx.ctx.current_admin)
if scope_sql then
return string.gsub(sql, " WHERE ", " WHERE " .. scope_sql .. " AND ", 1)
else
return sql
end
end,
}),
},

Expand Down
42 changes: 29 additions & 13 deletions src/api-umbrella/web-app/policies/admin_policy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,36 @@ function _M.authorized_query_scope(current_admin, permission_id)
-- scopes exist, and another, using an anti-join, to filter out any admin
-- records that have any unauthorized API scopes (which ensures we only
-- match admin records where *all* the API scopes are authorized).
local and_sql
if permission_id == "admin_view" then
and_sql = [[
AND EXISTS (
SELECT 1
FROM admin_groups_admins
INNER JOIN admin_groups_api_scopes ON admin_groups_admins.admin_group_id = admin_groups_api_scopes.admin_group_id
WHERE admins.id = admin_groups_admins.admin_id
AND admin_groups_api_scopes.api_scope_id IN ?
)
]]
else
and_sql = [[
AND NOT EXISTS (
SELECT 1
FROM admin_groups_admins
INNER JOIN admin_groups_api_scopes ON admin_groups_admins.admin_group_id = admin_groups_api_scopes.admin_group_id
WHERE admins.id = admin_groups_admins.admin_id
AND admin_groups_api_scopes.api_scope_id IN ? NOT EQUAL TRUE
)
]]
end
return db.interpolate_query([[
EXISTS (
SELECT 1
FROM admin_groups_admins
INNER JOIN admin_groups_api_scopes ON admin_groups_admins.admin_group_id = admin_groups_api_scopes.admin_group_id
WHERE admins.id = admin_groups_admins.admin_id
)
AND NOT EXISTS (
SELECT 1
FROM admin_groups_admins
INNER JOIN admin_groups_api_scopes ON admin_groups_admins.admin_group_id = admin_groups_api_scopes.admin_group_id
WHERE admins.id = admin_groups_admins.admin_id
AND admin_groups_api_scopes.api_scope_id IN ? IS NOT TRUE
)
]], db.list(api_scope_ids))
]] .. and_sql, db.list(api_scope_ids))
end
end

Expand All @@ -62,24 +77,25 @@ function _M.is_authorized_show(current_admin, data, permission_id)
permission_id = "admin_view"
end

local any_groups_allowed = false
local all_groups_allowed = false
if not is_empty(data["group_ids"]) then
local authorized_api_scopes = invert_table(current_admin:nested_api_scope_ids_with_permission(permission_id))
local api_scope_ids = AdminGroup.api_scope_ids_for_admin_group_ids(data["group_ids"])
all_groups_allowed = true
for _, api_scope_id in ipairs(api_scope_ids) do
if authorized_api_scopes[api_scope_id] then
all_groups_allowed = true
any_groups_allowed = true
else
all_groups_allowed = false
break
end
end
end

if all_groups_allowed then
return true
if permission_id == "admin_view" then
return any_groups_allowed
else
return false
return all_groups_allowed
end
end

Expand Down
4 changes: 4 additions & 0 deletions src/api-umbrella/web-app/utils/model_ext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ local function get_join_records(model_name, options, ids, include_foreign_key_id
" WHERE " .. join_table .. "." .. foreign_key .. " IN ?" ..
order_by

if options["transform_sql"] then
sql = options["transform_sql"](sql)
end

local fields = table_name .. ".*"
if include_foreign_key_id then
fields = fields .. ", " .. join_table .. "." .. foreign_key .. " AS _foreign_key_id"
Expand Down

0 comments on commit 404c2cc

Please sign in to comment.