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
|
redefine
|
||||||
make,
|
make,
|
||||||
filters,
|
filters,
|
||||||
setup_hooks
|
setup_hooks,
|
||||||
|
install,
|
||||||
|
permissions
|
||||||
end
|
end
|
||||||
|
|
||||||
CMS_WITH_WEBAPI
|
CMS_WITH_WEBAPI
|
||||||
@@ -35,6 +37,17 @@ feature {NONE} -- Initialization
|
|||||||
description := "Service to manage basic authentication"
|
description := "Service to manage basic authentication"
|
||||||
end
|
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
|
feature {CMS_EXECUTION} -- Administration
|
||||||
|
|
||||||
webapi: CMS_BASIC_AUTH_MODULE_WEBAPI
|
webapi: CMS_BASIC_AUTH_MODULE_WEBAPI
|
||||||
@@ -46,6 +59,15 @@ feature -- Access
|
|||||||
|
|
||||||
name: STRING = "basic_auth"
|
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
|
feature -- Access: auth strategy
|
||||||
|
|
||||||
login_title: STRING = "Basic Auth"
|
login_title: STRING = "Basic Auth"
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ feature -- Access: filter
|
|||||||
-- Possibly list of Filter's module.
|
-- Possibly list of Filter's module.
|
||||||
do
|
do
|
||||||
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
|
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
|
end
|
||||||
note
|
note
|
||||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
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
|
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
|
attached api.user_api.user_by_name (l_auth_login) as l_user
|
||||||
then
|
then
|
||||||
debug ("refactor_fixme")
|
if api.user_has_permission (l_user, {CMS_BASIC_AUTH_MODULE}.perm_use_basic_auth) then
|
||||||
fixme ("Maybe we need to store in the credentials in a shared context SECURITY_CONTEXT")
|
debug ("refactor_fixme")
|
||||||
-- req.set_execution_variable ("security_content", create SECURITY_CONTEXT.make (l_user))
|
fixme ("Maybe we need to store in the credentials in a shared context SECURITY_CONTEXT")
|
||||||
-- other authentication filters (OpenID, etc) should implement the same approach.
|
-- 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
|
end
|
||||||
set_current_user (l_user)
|
|
||||||
else
|
else
|
||||||
api.logger.put_error (generator + ".execute login_valid failed for: " + l_auth_login, Void)
|
api.logger.put_error (generator + ".execute login_valid failed for: " + l_auth_login, Void)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ feature -- Basic operations
|
|||||||
api.user_api.is_valid_credential (l_auth_login, l_auth_password) and then
|
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
|
attached api.user_api.user_by_name (l_auth_login) as l_user
|
||||||
then
|
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
|
else
|
||||||
-- not authenticated due to bad login or password.
|
-- not authenticated due to bad login or password.
|
||||||
end
|
end
|
||||||
@@ -247,15 +247,16 @@ feature -- Status report
|
|||||||
do
|
do
|
||||||
if a_permission = Void then
|
if a_permission = Void then
|
||||||
Result := True
|
Result := True
|
||||||
elseif a_user = Void then
|
|
||||||
Result := user_role_has_permission (anonymous_user_role, a_permission)
|
|
||||||
else
|
else
|
||||||
if is_admin_user (a_user) then
|
Result := user_role_has_permission (anonymous_user_role, a_permission)
|
||||||
Result := True
|
if not Result and a_user /= Void then
|
||||||
else
|
if is_admin_user (a_user) then
|
||||||
Result := user_role_has_permission (authenticated_user_role, a_permission)
|
Result := True
|
||||||
if not Result then
|
else
|
||||||
Result := across user_roles (a_user) as ic some user_role_has_permission (ic.item, a_permission) end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ feature -- Request execution
|
|||||||
do
|
do
|
||||||
if attached user_by_uid (a_uid) as l_user then
|
if attached user_by_uid (a_uid) as l_user then
|
||||||
if attached api.user as u 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)
|
rep := new_access_token_response (l_user, user_access_token (l_user), req, res)
|
||||||
if attached {WSF_STRING} req.item ("destination") as dest then
|
if attached {WSF_STRING} req.item ("destination") as dest then
|
||||||
rep.set_redirection (dest.url_encoded_value)
|
rep.set_redirection (dest.url_encoded_value)
|
||||||
@@ -77,18 +77,13 @@ feature -- Request execution
|
|||||||
do
|
do
|
||||||
if attached user_by_uid (a_uid) as l_user then
|
if attached user_by_uid (a_uid) as l_user then
|
||||||
if attached api.user as u 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
|
if attached req.path_parameter ("application") then
|
||||||
|
|
||||||
end
|
end
|
||||||
-- l_access_token := user_access_token (l_user)
|
|
||||||
l_access_token := new_key (40)
|
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)
|
set_user_access_token (l_user, l_access_token)
|
||||||
|
|
||||||
rep := new_access_token_response (l_user, l_access_token, req, res)
|
rep := new_access_token_response (l_user, l_access_token, req, res)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
note
|
note
|
||||||
description: "Summary description for {CMS_CORE_MODULE_WEBAPI}."
|
description: "Summary description for {CMS_CORE_MODULE_WEBAPI}."
|
||||||
author: ""
|
|
||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
@@ -25,6 +24,7 @@ feature -- Security
|
|||||||
Result := Precursor
|
Result := Precursor
|
||||||
Result.force ("admin users")
|
Result.force ("admin users")
|
||||||
Result.force ("view users")
|
Result.force ("view users")
|
||||||
|
Result.force ("use access_token")
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Router/administration
|
feature {NONE} -- Router/administration
|
||||||
@@ -35,11 +35,13 @@ feature {NONE} -- Router/administration
|
|||||||
l_root: CMS_ROOT_WEBAPI_HANDLER
|
l_root: CMS_ROOT_WEBAPI_HANDLER
|
||||||
do
|
do
|
||||||
create l_root.make (a_api)
|
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 ("/", 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}/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/{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
|
end
|
||||||
|
|
||||||
feature -- Access: filter
|
feature -- Access: filter
|
||||||
@@ -49,7 +51,6 @@ feature -- Access: filter
|
|||||||
do
|
do
|
||||||
create {ARRAYED_LIST [WSF_FILTER]} Result.make (2)
|
create {ARRAYED_LIST [WSF_FILTER]} Result.make (2)
|
||||||
Result.extend (create {CMS_ACCESS_TOKEN_WEBAPI_AUTH_FILTER}.make (a_api))
|
Result.extend (create {CMS_ACCESS_TOKEN_WEBAPI_AUTH_FILTER}.make (a_api))
|
||||||
Result.extend (create {CMS_BASIC_WEBAPI_AUTH_FILTER}.make (a_api))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
|
|||||||
@@ -14,12 +14,25 @@ inherit
|
|||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
router: detachable WSF_ROUTER
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
set_router (a_router: like router)
|
||||||
|
do
|
||||||
|
router := a_router
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Execution
|
feature -- Execution
|
||||||
|
|
||||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Execute handler for `req' and respond in `res'.
|
-- Execute handler for `req' and respond in `res'.
|
||||||
local
|
local
|
||||||
rep: HM_WEBAPI_RESPONSE
|
rep: HM_WEBAPI_RESPONSE
|
||||||
|
vis: WSF_ROUTER_AGENT_ITERATOR
|
||||||
|
j: JSON_ARRAY
|
||||||
do
|
do
|
||||||
rep := new_response (req, res)
|
rep := new_response (req, res)
|
||||||
rep.add_string_field ("site_name", api.setup.site_name)
|
rep.add_string_field ("site_name", api.setup.site_name)
|
||||||
@@ -28,6 +41,44 @@ feature -- Execution
|
|||||||
elseif api.has_permission ("account register") then
|
elseif api.has_permission ("account register") then
|
||||||
rep.add_link ("register", Void, api.webapi_path ("/account/register"))
|
rep.add_link ("register", Void, api.webapi_path ("/account/register"))
|
||||||
end
|
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.add_self (req.percent_encoded_path_info)
|
||||||
rep.execute
|
rep.execute
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,41 +41,41 @@ feature -- Execution
|
|||||||
else
|
else
|
||||||
l_user := api.user_api.user_by_name (p_uid.value)
|
l_user := api.user_api.user_by_name (p_uid.value)
|
||||||
end
|
end
|
||||||
-- if l_user = Void and p_uid.is_case_insensitive_equal ("me") then
|
else
|
||||||
-- l_user := u
|
-- if uid is not give, use current user if any
|
||||||
-- end
|
l_user := u
|
||||||
if l_user /= Void then
|
end
|
||||||
if l_user.same_as (u) or api.has_permissions (<<"admin users", "view users">>) then
|
-- if l_user = Void and p_uid.is_case_insensitive_equal ("me") then
|
||||||
rep := new_response (req, res)
|
-- l_user := u
|
||||||
rep.add_string_field ("uid", l_user.id.out)
|
-- end
|
||||||
rep.add_string_field ("name", l_user.name)
|
if l_user /= Void then
|
||||||
if attached l_user.email as l_email then
|
if l_user.same_as (u) or api.has_permissions (<<"admin users", "view users">>) then
|
||||||
rep.add_string_field ("email", l_email)
|
rep := new_response (req, res)
|
||||||
end
|
rep.add_string_field ("uid", l_user.id.out)
|
||||||
if not l_user.is_active then
|
rep.add_string_field ("name", l_user.name)
|
||||||
rep.add_boolean_field ("is_active", False)
|
if attached l_user.email as l_email then
|
||||||
end
|
rep.add_string_field ("email", l_email)
|
||||||
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)
|
|
||||||
end
|
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
|
else
|
||||||
rep := new_error_response ("Not found", req, res)
|
rep := new_error_response ("denied", req, res)
|
||||||
rep.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
rep.set_status_code ({HTTP_STATUS_CODE}.user_access_denied)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
rep := new_error_response ("Bad request", req, res)
|
rep := new_error_response ("Not found", req, res)
|
||||||
rep.set_status_code ({HTTP_STATUS_CODE}.bad_request)
|
rep.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- FIXME: use specific Web API response!
|
-- FIXME: use specific Web API response!
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ feature {CMS_API, CMS_MODULE_ADMINISTRATION, CMS_MODULE_WEBAPI} -- Access: API
|
|||||||
|
|
||||||
feature -- Status
|
feature -- Status
|
||||||
|
|
||||||
is_initialized: BOOLEAN
|
frozen is_initialized: BOOLEAN
|
||||||
-- Is Current module initialized?
|
-- Is Current module initialized?
|
||||||
do
|
do
|
||||||
Result := module.is_initialized
|
Result := module.is_initialized
|
||||||
end
|
end
|
||||||
|
|
||||||
is_enabled: BOOLEAN
|
frozen is_enabled: BOOLEAN
|
||||||
-- Is Current module enabled?
|
-- Is Current module enabled?
|
||||||
do
|
do
|
||||||
Result := module.is_enabled
|
Result := module.is_enabled
|
||||||
|
|||||||
Reference in New Issue
Block a user