Fix authenticated role permissions, now it also has all anonymous permissions.
Added permissions on basic auth, to have more control on who can authenticate with basic auth.
Use webapi version of basic auth filter.
For webapi, when authenticated /api/user/ is the same as /api/user/{uid} where uid is the id of current logged in user.
This commit is contained in:
@@ -16,7 +16,9 @@ inherit
|
||||
redefine
|
||||
make,
|
||||
filters,
|
||||
setup_hooks
|
||||
setup_hooks,
|
||||
install,
|
||||
permissions
|
||||
end
|
||||
|
||||
CMS_WITH_WEBAPI
|
||||
@@ -35,6 +37,17 @@ feature {NONE} -- Initialization
|
||||
description := "Service to manage basic authentication"
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
install (a_api: CMS_API)
|
||||
do
|
||||
Precursor (a_api)
|
||||
if attached a_api.user_api.anonymous_user_role as ano then
|
||||
ano.add_permission (perm_use_basic_auth)
|
||||
a_api.user_api.save_user_role (ano)
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_EXECUTION} -- Administration
|
||||
|
||||
webapi: CMS_BASIC_AUTH_MODULE_WEBAPI
|
||||
@@ -46,6 +59,15 @@ feature -- Access
|
||||
|
||||
name: STRING = "basic_auth"
|
||||
|
||||
permissions: LIST [READABLE_STRING_8]
|
||||
-- List of permission ids, used by this module, and declared.
|
||||
do
|
||||
Result := Precursor
|
||||
Result.force ("use basic_auth")
|
||||
end
|
||||
|
||||
perm_use_basic_auth: STRING = "use basic_auth"
|
||||
|
||||
feature -- Access: auth strategy
|
||||
|
||||
login_title: STRING = "Basic Auth"
|
||||
|
||||
@@ -28,7 +28,7 @@ feature -- Access: filter
|
||||
-- Possibly list of Filter's module.
|
||||
do
|
||||
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
|
||||
Result.extend (create {CMS_BASIC_AUTH_FILTER}.make (a_api))
|
||||
Result.extend (create {CMS_BASIC_WEBAPI_AUTH_FILTER}.make (a_api))
|
||||
end
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
|
||||
@@ -38,12 +38,14 @@ feature -- Basic operations
|
||||
api.user_api.is_valid_credential (l_auth_login, l_auth_password) and then
|
||||
attached api.user_api.user_by_name (l_auth_login) as l_user
|
||||
then
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Maybe we need to store in the credentials in a shared context SECURITY_CONTEXT")
|
||||
-- req.set_execution_variable ("security_content", create SECURITY_CONTEXT.make (l_user))
|
||||
-- other authentication filters (OpenID, etc) should implement the same approach.
|
||||
if api.user_has_permission (l_user, {CMS_BASIC_AUTH_MODULE}.perm_use_basic_auth) then
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Maybe we need to store in the credentials in a shared context SECURITY_CONTEXT")
|
||||
-- req.set_execution_variable ("security_content", create SECURITY_CONTEXT.make (l_user))
|
||||
-- other authentication filters (OpenID, etc) should implement the same approach.
|
||||
end
|
||||
set_current_user (l_user)
|
||||
end
|
||||
set_current_user (l_user)
|
||||
else
|
||||
api.logger.put_error (generator + ".execute login_valid failed for: " + l_auth_login, Void)
|
||||
end
|
||||
|
||||
@@ -29,7 +29,9 @@ feature -- Basic operations
|
||||
api.user_api.is_valid_credential (l_auth_login, l_auth_password) and then
|
||||
attached api.user_api.user_by_name (l_auth_login) as l_user
|
||||
then
|
||||
api.set_user (l_user)
|
||||
if api.user_has_permission (l_user, {CMS_BASIC_AUTH_MODULE}.perm_use_basic_auth) then
|
||||
api.set_user (l_user)
|
||||
end
|
||||
else
|
||||
-- not authenticated due to bad login or password.
|
||||
end
|
||||
@@ -247,15 +247,16 @@ feature -- Status report
|
||||
do
|
||||
if a_permission = Void then
|
||||
Result := True
|
||||
elseif a_user = Void then
|
||||
Result := user_role_has_permission (anonymous_user_role, a_permission)
|
||||
else
|
||||
if is_admin_user (a_user) then
|
||||
Result := True
|
||||
else
|
||||
Result := user_role_has_permission (authenticated_user_role, a_permission)
|
||||
if not Result then
|
||||
Result := across user_roles (a_user) as ic some user_role_has_permission (ic.item, a_permission) end
|
||||
Result := user_role_has_permission (anonymous_user_role, a_permission)
|
||||
if not Result and a_user /= Void then
|
||||
if is_admin_user (a_user) then
|
||||
Result := True
|
||||
else
|
||||
Result := user_role_has_permission (authenticated_user_role, a_permission)
|
||||
if not Result then
|
||||
Result := across user_roles (a_user) as ic some user_role_has_permission (ic.item, a_permission) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,7 +51,7 @@ feature -- Request execution
|
||||
do
|
||||
if attached user_by_uid (a_uid) as l_user then
|
||||
if attached api.user as u then
|
||||
if u.same_as (l_user) or api.user_api.is_admin_user (u) then
|
||||
if u.same_as (l_user) and api.has_permission ("use access_token") then
|
||||
rep := new_access_token_response (l_user, user_access_token (l_user), req, res)
|
||||
if attached {WSF_STRING} req.item ("destination") as dest then
|
||||
rep.set_redirection (dest.url_encoded_value)
|
||||
@@ -77,18 +77,13 @@ feature -- Request execution
|
||||
do
|
||||
if attached user_by_uid (a_uid) as l_user then
|
||||
if attached api.user as u then
|
||||
if u.same_as (l_user) or api.user_api.is_admin_user (u) then
|
||||
if
|
||||
u.same_as (l_user) and api.has_permission ("use access_token")
|
||||
then
|
||||
if attached req.path_parameter ("application") then
|
||||
|
||||
end
|
||||
-- l_access_token := user_access_token (l_user)
|
||||
l_access_token := new_key (40)
|
||||
|
||||
-- if l_access_token /= Void then
|
||||
-- l_access_token := "Updated-" + (create {UUID_GENERATOR}).generate_uuid.out
|
||||
-- else
|
||||
-- l_access_token := "New-" + (create {UUID_GENERATOR}).generate_uuid.out
|
||||
-- end
|
||||
set_user_access_token (l_user, l_access_token)
|
||||
|
||||
rep := new_access_token_response (l_user, l_access_token, req, res)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_MODULE_WEBAPI}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
@@ -25,6 +24,7 @@ feature -- Security
|
||||
Result := Precursor
|
||||
Result.force ("admin users")
|
||||
Result.force ("view users")
|
||||
Result.force ("use access_token")
|
||||
end
|
||||
|
||||
feature {NONE} -- Router/administration
|
||||
@@ -35,11 +35,13 @@ feature {NONE} -- Router/administration
|
||||
l_root: CMS_ROOT_WEBAPI_HANDLER
|
||||
do
|
||||
create l_root.make (a_api)
|
||||
l_root.set_router (a_router)
|
||||
a_router.handle ("", l_root, a_router.methods_get)
|
||||
a_router.handle ("/", l_root, a_router.methods_get)
|
||||
a_router.handle ("/user/{uid}/access_token", create {CMS_ACCESS_TOKEN_WEBAPI_HANDLER}.make (a_api), a_router.methods_get_post)
|
||||
a_router.handle ("/user/{uid}", create {CMS_USER_WEBAPI_HANDLER}.make (a_api), a_router.methods_get)
|
||||
a_router.handle ("/user/", create {CMS_USERS_WEBAPI_HANDLER}.make (a_api), a_router.methods_get_post)
|
||||
a_router.handle ("/user/", create {CMS_USER_WEBAPI_HANDLER}.make (a_api), a_router.methods_get)
|
||||
a_router.handle ("/users/", create {CMS_USERS_WEBAPI_HANDLER}.make (a_api), a_router.methods_get_post)
|
||||
end
|
||||
|
||||
feature -- Access: filter
|
||||
@@ -49,7 +51,6 @@ feature -- Access: filter
|
||||
do
|
||||
create {ARRAYED_LIST [WSF_FILTER]} Result.make (2)
|
||||
Result.extend (create {CMS_ACCESS_TOKEN_WEBAPI_AUTH_FILTER}.make (a_api))
|
||||
Result.extend (create {CMS_BASIC_WEBAPI_AUTH_FILTER}.make (a_api))
|
||||
end
|
||||
|
||||
note
|
||||
|
||||
@@ -14,12 +14,25 @@ inherit
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
router: detachable WSF_ROUTER
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_router (a_router: like router)
|
||||
do
|
||||
router := a_router
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
vis: WSF_ROUTER_AGENT_ITERATOR
|
||||
j: JSON_ARRAY
|
||||
do
|
||||
rep := new_response (req, res)
|
||||
rep.add_string_field ("site_name", api.setup.site_name)
|
||||
@@ -28,6 +41,44 @@ feature -- Execution
|
||||
elseif api.has_permission ("account register") then
|
||||
rep.add_link ("register", Void, api.webapi_path ("/account/register"))
|
||||
end
|
||||
|
||||
-- If query has "router=yes", display basic information about router mapping.
|
||||
-- Note: this may change in the future
|
||||
if
|
||||
attached router as l_router and then
|
||||
attached req.query_parameter ("router") as p_router and then
|
||||
p_router.same_string ("yes")
|
||||
then
|
||||
create j.make_empty
|
||||
create vis
|
||||
vis.on_item_actions.extend (agent (i_item: WSF_ROUTER_ITEM; i_json: JSON_ARRAY)
|
||||
local
|
||||
jo: JSON_OBJECT
|
||||
s: STRING
|
||||
do
|
||||
create jo.make_with_capacity (3)
|
||||
jo.put_string (i_item.mapping.associated_resource, "resource")
|
||||
create s.make_empty
|
||||
if attached i_item.request_methods as methds and then not methds.is_empty then
|
||||
across
|
||||
methds as ic
|
||||
loop
|
||||
if not s.is_empty then
|
||||
s.extend (',')
|
||||
end
|
||||
s.append (ic.item)
|
||||
end
|
||||
jo.put_string (s, "request_methods")
|
||||
else
|
||||
s.append ("*")
|
||||
end
|
||||
|
||||
jo.put_string (i_item.mapping.description, "description")
|
||||
i_json.extend (jo)
|
||||
end(?, j))
|
||||
vis.process_router (l_router)
|
||||
rep.add_string_field ("routing", j.representation)
|
||||
end
|
||||
rep.add_self (req.percent_encoded_path_info)
|
||||
rep.execute
|
||||
end
|
||||
|
||||
@@ -41,41 +41,41 @@ feature -- Execution
|
||||
else
|
||||
l_user := api.user_api.user_by_name (p_uid.value)
|
||||
end
|
||||
-- if l_user = Void and p_uid.is_case_insensitive_equal ("me") then
|
||||
-- l_user := u
|
||||
-- end
|
||||
if l_user /= Void then
|
||||
if l_user.same_as (u) or api.has_permissions (<<"admin users", "view users">>) then
|
||||
rep := new_response (req, res)
|
||||
rep.add_string_field ("uid", l_user.id.out)
|
||||
rep.add_string_field ("name", l_user.name)
|
||||
if attached l_user.email as l_email then
|
||||
rep.add_string_field ("email", l_email)
|
||||
end
|
||||
if not l_user.is_active then
|
||||
rep.add_boolean_field ("is_active", False)
|
||||
end
|
||||
if attached l_user.profile_name as l_profile_name then
|
||||
rep.add_string_field ("profile_name", l_profile_name)
|
||||
end
|
||||
if attached l_user.creation_date as dt then
|
||||
rep.add_string_field ("creation_date", date_time_to_string (dt))
|
||||
end
|
||||
if attached l_user.last_login_date as dt then
|
||||
rep.add_string_field ("last_login_date", date_time_to_string (dt))
|
||||
end
|
||||
add_user_links_to (l_user, rep)
|
||||
else
|
||||
rep := new_error_response ("denied", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.user_access_denied)
|
||||
else
|
||||
-- if uid is not give, use current user if any
|
||||
l_user := u
|
||||
end
|
||||
-- if l_user = Void and p_uid.is_case_insensitive_equal ("me") then
|
||||
-- l_user := u
|
||||
-- end
|
||||
if l_user /= Void then
|
||||
if l_user.same_as (u) or api.has_permissions (<<"admin users", "view users">>) then
|
||||
rep := new_response (req, res)
|
||||
rep.add_string_field ("uid", l_user.id.out)
|
||||
rep.add_string_field ("name", l_user.name)
|
||||
if attached l_user.email as l_email then
|
||||
rep.add_string_field ("email", l_email)
|
||||
end
|
||||
if not l_user.is_active then
|
||||
rep.add_boolean_field ("is_active", False)
|
||||
end
|
||||
if attached l_user.profile_name as l_profile_name then
|
||||
rep.add_string_field ("profile_name", l_profile_name)
|
||||
end
|
||||
if attached l_user.creation_date as dt then
|
||||
rep.add_string_field ("creation_date", date_time_to_string (dt))
|
||||
end
|
||||
if attached l_user.last_login_date as dt then
|
||||
rep.add_string_field ("last_login_date", date_time_to_string (dt))
|
||||
end
|
||||
add_user_links_to (l_user, rep)
|
||||
else
|
||||
rep := new_error_response ("Not found", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||
rep := new_error_response ("denied", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.user_access_denied)
|
||||
end
|
||||
else
|
||||
rep := new_error_response ("Bad request", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.bad_request)
|
||||
rep := new_error_response ("Not found", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||
end
|
||||
else
|
||||
-- FIXME: use specific Web API response!
|
||||
|
||||
@@ -51,13 +51,13 @@ feature {CMS_API, CMS_MODULE_ADMINISTRATION, CMS_MODULE_WEBAPI} -- Access: API
|
||||
|
||||
feature -- Status
|
||||
|
||||
is_initialized: BOOLEAN
|
||||
frozen is_initialized: BOOLEAN
|
||||
-- Is Current module initialized?
|
||||
do
|
||||
Result := module.is_initialized
|
||||
end
|
||||
|
||||
is_enabled: BOOLEAN
|
||||
frozen is_enabled: BOOLEAN
|
||||
-- Is Current module enabled?
|
||||
do
|
||||
Result := module.is_enabled
|
||||
|
||||
Reference in New Issue
Block a user