diff --git a/modules/basic_auth/cms_basic_auth_module.e b/modules/basic_auth/cms_basic_auth_module.e index 3493a54..f986245 100644 --- a/modules/basic_auth/cms_basic_auth_module.e +++ b/modules/basic_auth/cms_basic_auth_module.e @@ -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" diff --git a/modules/basic_auth/cms_basic_auth_module_webapi.e b/modules/basic_auth/cms_basic_auth_module_webapi.e index e5cc766..3c3741d 100644 --- a/modules/basic_auth/cms_basic_auth_module_webapi.e +++ b/modules/basic_auth/cms_basic_auth_module_webapi.e @@ -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" diff --git a/modules/basic_auth/filter/cms_basic_auth_filter.e b/modules/basic_auth/filter/cms_basic_auth_filter.e index 1baf777..1c5094e 100644 --- a/modules/basic_auth/filter/cms_basic_auth_filter.e +++ b/modules/basic_auth/filter/cms_basic_auth_filter.e @@ -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 diff --git a/src/modules/core/webapi/cms_basic_webapi_auth_filter.e b/modules/basic_auth/filter/cms_basic_webapi_auth_filter.e similarity index 88% rename from src/modules/core/webapi/cms_basic_webapi_auth_filter.e rename to modules/basic_auth/filter/cms_basic_webapi_auth_filter.e index 68f9d80..3c13d91 100644 --- a/src/modules/core/webapi/cms_basic_webapi_auth_filter.e +++ b/modules/basic_auth/filter/cms_basic_webapi_auth_filter.e @@ -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 diff --git a/src/modules/core/cms_user_api.e b/src/modules/core/cms_user_api.e index 1b99c57..f1f000e 100644 --- a/src/modules/core/cms_user_api.e +++ b/src/modules/core/cms_user_api.e @@ -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 diff --git a/src/modules/core/webapi/cms_access_token_webapi_handler.e b/src/modules/core/webapi/cms_access_token_webapi_handler.e index 40d6ea9..dbb7096 100644 --- a/src/modules/core/webapi/cms_access_token_webapi_handler.e +++ b/src/modules/core/webapi/cms_access_token_webapi_handler.e @@ -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) diff --git a/src/modules/core/webapi/cms_core_module_webapi.e b/src/modules/core/webapi/cms_core_module_webapi.e index 781810c..784a168 100644 --- a/src/modules/core/webapi/cms_core_module_webapi.e +++ b/src/modules/core/webapi/cms_core_module_webapi.e @@ -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 diff --git a/src/modules/core/webapi/cms_root_webapi_handler.e b/src/modules/core/webapi/cms_root_webapi_handler.e index 97a108b..ca8e810 100644 --- a/src/modules/core/webapi/cms_root_webapi_handler.e +++ b/src/modules/core/webapi/cms_root_webapi_handler.e @@ -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 diff --git a/src/modules/core/webapi/cms_user_webapi_handler.e b/src/modules/core/webapi/cms_user_webapi_handler.e index d9f5ac5..576cf69 100644 --- a/src/modules/core/webapi/cms_user_webapi_handler.e +++ b/src/modules/core/webapi/cms_user_webapi_handler.e @@ -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! diff --git a/src/service/webapi/cms_module_webapi.e b/src/service/webapi/cms_module_webapi.e index 8e954d1..92b976b 100644 --- a/src/service/webapi/cms_module_webapi.e +++ b/src/service/webapi/cms_module_webapi.e @@ -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