Updated webapi system.
Added specific webapi handler classes for root, user, access token, ... Added new queries to user profile api. Reviewed filter setup depending on the mode (site, admin, webapi).
This commit is contained in:
@@ -1,188 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_MODULE_WEBAPI}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CORE_MODULE_WEBAPI
|
||||
|
||||
inherit
|
||||
CMS_MODULE_WEBAPI [CMS_CORE_MODULE]
|
||||
redefine
|
||||
permissions
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Security
|
||||
|
||||
permissions: LIST [READABLE_STRING_8]
|
||||
-- List of permission ids, used by this module, and declared.
|
||||
do
|
||||
Result := Precursor
|
||||
Result.force ("admin users")
|
||||
end
|
||||
|
||||
feature {NONE} -- Router/administration
|
||||
|
||||
setup_webapi_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
a_router.handle ("", create {WSF_URI_AGENT_HANDLER}.make (agent handle_root (?, ?, a_api)), a_router.methods_get)
|
||||
a_router.handle ("/access_token", create {WSF_URI_AGENT_HANDLER}.make (agent do_post_access_token (?, ?, a_api)), a_router.methods_post)
|
||||
|
||||
a_router.handle ("/user/{uid}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent do_get_user (?, ?, a_api)), a_router.methods_get)
|
||||
end
|
||||
|
||||
feature -- Request handling
|
||||
|
||||
handle_root (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
rep := new_webapi_response (req, res, api)
|
||||
rep.add_field ("site_name", api.setup.site_name)
|
||||
if attached api.user as u then
|
||||
add_user_links_to (u, rep)
|
||||
end
|
||||
rep.add_self (req.percent_encoded_path_info)
|
||||
rep.execute
|
||||
end
|
||||
|
||||
feature -- Access token
|
||||
|
||||
do_get_access_token (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
-- l_access_token: detachable READABLE_STRING_32
|
||||
do
|
||||
if
|
||||
attached api.user as l_user and then
|
||||
attached api.user_api.user_profile_item ("access_token", l_user) as l_access_token
|
||||
then
|
||||
-- l_access_token := new_key (40)
|
||||
-- api.user_api.save_user_profile_item (l_user, "access_token", l_access_token)
|
||||
|
||||
rep := new_webapi_response (req, res, api)
|
||||
rep.add_field ("access_token", l_access_token)
|
||||
rep.add_self (req.percent_encoded_path_info)
|
||||
add_user_links_to (l_user, rep)
|
||||
if attached {WSF_STRING} req.item ("destination") as dest then
|
||||
rep.set_redirection (dest.url_encoded_value)
|
||||
end
|
||||
rep.execute
|
||||
else
|
||||
send_access_denied (Void, req, res, api)
|
||||
end
|
||||
end
|
||||
|
||||
do_post_access_token (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
|
||||
local
|
||||
m: WSF_PAGE_RESPONSE
|
||||
l_access_token: detachable READABLE_STRING_32
|
||||
do
|
||||
if attached api.user as l_user then
|
||||
l_access_token := api.user_api.user_profile_item ("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
|
||||
api.user_api.save_user_profile_item (l_user, "access_token", l_access_token)
|
||||
if attached {WSF_STRING} req.item ("destination") as dest then
|
||||
res.redirect_now (dest.value.to_string_8)
|
||||
else
|
||||
create m.make_with_body ("Ok")
|
||||
res.send (m)
|
||||
end
|
||||
else
|
||||
send_access_denied (Void, req, res, api)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Users
|
||||
|
||||
do_get_user (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
if attached api.user as u then
|
||||
rep := new_webapi_response (req, res, api)
|
||||
rep.add_field ("uid", u.id.out)
|
||||
|
||||
rep.add_field ("name", u.name)
|
||||
if attached u.email as l_email then
|
||||
rep.add_field ("email", l_email)
|
||||
end
|
||||
if attached u.profile_name as l_profile_name then
|
||||
rep.add_field ("profile_name", l_profile_name)
|
||||
end
|
||||
add_user_links_to (u, rep)
|
||||
rep.execute
|
||||
else
|
||||
-- FIXME: use specific Web API response!
|
||||
send_access_denied (Void, req, res, api)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
new_webapi_response (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API): HM_WEBAPI_RESPONSE
|
||||
do
|
||||
-- create {MD_WEBAPI_RESPONSE} Result.make (req, res, api)
|
||||
create {JSON_WEBAPI_RESPONSE} Result.make (req, res, api)
|
||||
end
|
||||
|
||||
send_access_denied (m: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
rep := new_webapi_response (req, res, api)
|
||||
if m /= Void then
|
||||
rep.add_field ("error", m)
|
||||
else
|
||||
rep.add_field ("error", "Access denied")
|
||||
end
|
||||
rep.execute
|
||||
end
|
||||
|
||||
add_user_links_to (u: CMS_USER; rep: HM_WEBAPI_RESPONSE)
|
||||
do
|
||||
rep.add_link ("account", "user/" + u.id.out, rep.api.webapi_path ("/user/" + u.id.out))
|
||||
end
|
||||
|
||||
new_key (len: INTEGER): STRING_8
|
||||
local
|
||||
rand: RANDOM
|
||||
n: INTEGER
|
||||
v: NATURAL_32
|
||||
do
|
||||
create rand.set_seed ((create {DATE_TIME}.make_now_utc).seconds)
|
||||
rand.start
|
||||
create Result.make (len)
|
||||
from
|
||||
n := 1
|
||||
until
|
||||
n = len
|
||||
loop
|
||||
rand.forth
|
||||
v := (rand.item \\ 16).to_natural_32
|
||||
check 0 <= v and v <= 15 end
|
||||
if v < 9 then
|
||||
Result.append_code (48 + v) -- 48 '0'
|
||||
else
|
||||
Result.append_code (97 + v - 9) -- 97 'a'
|
||||
end
|
||||
n := n + 1
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
@@ -118,6 +118,16 @@ feature -- Access: user
|
||||
Result := user_storage.user_by_name (a_username)
|
||||
end
|
||||
|
||||
user_by_id_or_name (a_uid: READABLE_STRING_GENERAL): detachable CMS_USER
|
||||
-- User by id or name `a_uid`, if any.
|
||||
do
|
||||
if a_uid.is_integer_64 then
|
||||
Result := user_by_id (a_uid.to_integer_64)
|
||||
else
|
||||
Result := user_by_name (a_uid)
|
||||
end
|
||||
end
|
||||
|
||||
user_by_email (a_email: READABLE_STRING_GENERAL): detachable CMS_USER
|
||||
-- User by email `a_email', if any.
|
||||
do
|
||||
|
||||
@@ -54,6 +54,15 @@ feature -- Access: profile
|
||||
Result := user_profile_storage.user_profile_item (a_user, a_item_name)
|
||||
end
|
||||
|
||||
users_with_profile_item (a_item_name: READABLE_STRING_GENERAL; a_value: detachable READABLE_STRING_GENERAL): detachable LIST [CMS_USER]
|
||||
-- Users having a profile item `a_item_name:a_value`.
|
||||
-- Note: if `a_value` is Void, return users having a profile item named `a_item_name`.
|
||||
require
|
||||
not a_item_name.is_whitespace
|
||||
do
|
||||
Result := user_profile_storage.users_with_profile_item (a_item_name, a_value)
|
||||
end
|
||||
|
||||
feature -- Change: profile
|
||||
|
||||
save_user_profile (a_user: CMS_USER; a_user_profile: CMS_USER_PROFILE)
|
||||
|
||||
@@ -82,7 +82,6 @@ feature -- HTTP Methods
|
||||
-- <Precursor>
|
||||
local
|
||||
l_user: detachable CMS_USER
|
||||
l_uid: INTEGER_64
|
||||
do
|
||||
if api.has_permission ("view user") then
|
||||
-- Display existing node
|
||||
|
||||
@@ -31,6 +31,12 @@ feature -- Access
|
||||
end
|
||||
end
|
||||
|
||||
users_with_profile_item (a_item_name: READABLE_STRING_GENERAL; a_value: detachable READABLE_STRING_GENERAL): detachable LIST [CMS_USER]
|
||||
-- Users having a profile item `a_item_name:a_value`.
|
||||
-- Note: if `a_value` is Void, return users having a profile item named `a_item_name`.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
save_user_profile (a_user: CMS_USER; a_profile: CMS_USER_PROFILE)
|
||||
@@ -54,4 +60,7 @@ feature -- Change
|
||||
save_user_profile (a_user, pf)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -24,6 +24,11 @@ feature -- Access
|
||||
do
|
||||
end
|
||||
|
||||
users_with_profile_item (a_item_name: READABLE_STRING_GENERAL; a_value: detachable READABLE_STRING_GENERAL): detachable LIST [CMS_USER]
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
save_user_profile (a_user: CMS_USER; a_profile: CMS_USER_PROFILE)
|
||||
@@ -31,4 +36,7 @@ feature -- Change
|
||||
do
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -66,13 +66,63 @@ feature -- Access
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
users_with_profile_item (a_item_name: READABLE_STRING_GENERAL; a_value: detachable READABLE_STRING_GENERAL): detachable LIST [CMS_USER]
|
||||
-- Users having a profile item `a_item_name:a_value`.
|
||||
-- Note: if `a_value` is Void, return users having a profile item named `a_item_name`.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
l_uids: ARRAYED_LIST [INTEGER_64]
|
||||
do
|
||||
reset_error
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_item_name, "key")
|
||||
if a_value = Void then
|
||||
sql_query (sql_select_users_with_profile_item_named, l_parameters)
|
||||
else
|
||||
l_parameters.put (a_value, "value")
|
||||
sql_query (sql_select_users_with_profile_item, l_parameters)
|
||||
end
|
||||
if not has_error then
|
||||
create l_uids.make (0)
|
||||
from
|
||||
sql_start
|
||||
until
|
||||
sql_after or has_error
|
||||
loop
|
||||
if
|
||||
attached sql_read_integer_64 (1) as l_uid and then
|
||||
l_uid > 0
|
||||
then
|
||||
l_uids.force (l_uid)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
end
|
||||
sql_finalize
|
||||
if
|
||||
not has_error and
|
||||
l_uids /= Void and
|
||||
attached api as l_cms_api
|
||||
then
|
||||
create {ARRAYED_LIST [CMS_USER]} Result.make (l_uids.count)
|
||||
across
|
||||
l_uids as ic
|
||||
loop
|
||||
if attached l_cms_api.user_api.user_by_id (ic.item) as u then
|
||||
Result.force (u)
|
||||
else
|
||||
check known_user: False end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
save_user_profile_item (a_user: CMS_USER; a_item_name: READABLE_STRING_GENERAL; a_item_value: READABLE_STRING_GENERAL)
|
||||
-- Save user profile item `a_item_name:a_item_value` for `a_user'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
p: detachable CMS_USER_PROFILE
|
||||
do
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_user.id, "uid")
|
||||
@@ -142,6 +192,12 @@ feature {NONE} -- Queries
|
||||
sql_select_user_profile_item: STRING = "SELECT key, value FROM user_profiles WHERE uid=:uid AND key=:key"
|
||||
-- user profile items for :uid;
|
||||
|
||||
sql_select_users_with_profile_item: STRING = "SELECT uid FROM user_profiles WHERE key=:key and value=:value"
|
||||
-- users with profile item named :key and value :value;
|
||||
|
||||
sql_select_users_with_profile_item_named: STRING = "SELECT uid FROM user_profiles WHERE key=:key"
|
||||
-- users with profile item named :key;
|
||||
|
||||
sql_insert_user_profile_item: STRING = "INSERT INTO user_profiles (uid, key, value) VALUES (:uid, :key, :value);"
|
||||
-- new user profile item for :uid;
|
||||
|
||||
@@ -149,5 +205,8 @@ feature {NONE} -- Queries
|
||||
-- user profile items for :uid;
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_ACCESS_TOKEN_WEBAPI_AUTH_FILTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CORE_ACCESS_TOKEN_WEBAPI_AUTH_FILTER
|
||||
|
||||
inherit
|
||||
WSF_FILTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: CMS_API)
|
||||
-- Initialize Current handler with `a_api'.
|
||||
do
|
||||
api := a_api
|
||||
end
|
||||
|
||||
feature -- API Service
|
||||
|
||||
api: CMS_API
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter.
|
||||
local
|
||||
tok: READABLE_STRING_GENERAL
|
||||
do
|
||||
if
|
||||
attached req.http_authorization as l_auth and then
|
||||
l_auth.starts_with_general ("Bearer ")
|
||||
then
|
||||
tok := l_auth.substring (8, l_auth.count)
|
||||
if attached api.user_api.users_with_profile_item ("access_token", tok) as lst then
|
||||
if lst.count = 1 then
|
||||
api.set_user (lst.first)
|
||||
end
|
||||
end
|
||||
end
|
||||
execute_next (req, res)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
92
src/modules/core/webapi/cms_core_module_webapi.e
Normal file
92
src/modules/core/webapi/cms_core_module_webapi.e
Normal file
@@ -0,0 +1,92 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_MODULE_WEBAPI}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CORE_MODULE_WEBAPI
|
||||
|
||||
inherit
|
||||
CMS_MODULE_WEBAPI [CMS_CORE_MODULE]
|
||||
redefine
|
||||
permissions,
|
||||
filters
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Security
|
||||
|
||||
permissions: LIST [READABLE_STRING_8]
|
||||
-- List of permission ids, used by this module, and declared.
|
||||
do
|
||||
Result := Precursor
|
||||
Result.force ("admin users")
|
||||
Result.force ("view users")
|
||||
end
|
||||
|
||||
feature {NONE} -- Router/administration
|
||||
|
||||
setup_webapi_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_root: CMS_CORE_WEBAPI_ROOT_HANDLER
|
||||
do
|
||||
create l_root.make (a_api)
|
||||
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_CORE_WEBAPI_ACCESS_TOKEN_HANDLER}.make (a_api), a_router.methods_get_post)
|
||||
a_router.handle ("/user/{uid}", create {CMS_CORE_WEBAPI_USER_HANDLER}.make (a_api), a_router.methods_get)
|
||||
end
|
||||
|
||||
feature -- Access: filter
|
||||
|
||||
filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
|
||||
-- Possibly list of Filter's module.
|
||||
do
|
||||
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
|
||||
Result.extend (create {CMS_CORE_ACCESS_TOKEN_WEBAPI_AUTH_FILTER}.make (a_api))
|
||||
end
|
||||
|
||||
--feature -- Helpers
|
||||
|
||||
-- new_webapi_response (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API): HM_WEBAPI_RESPONSE
|
||||
-- do
|
||||
---- create {MD_WEBAPI_RESPONSE} Result.make (req, res, api)
|
||||
-- create {JSON_WEBAPI_RESPONSE} Result.make (req, res, api)
|
||||
-- end
|
||||
|
||||
-- new_wepapi_error_response (msg: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API): HM_WEBAPI_RESPONSE
|
||||
-- do
|
||||
-- Result := new_webapi_response (req, res, api)
|
||||
-- if msg /= Void then
|
||||
-- Result.add_string_field ("error", msg)
|
||||
-- else
|
||||
-- Result.add_string_field ("error", "True")
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- send_access_denied (m: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
|
||||
-- local
|
||||
-- rep: HM_WEBAPI_RESPONSE
|
||||
-- do
|
||||
-- rep := new_webapi_response (req, res, api)
|
||||
-- if m /= Void then
|
||||
-- rep.add_string_field ("error", m)
|
||||
-- else
|
||||
-- rep.add_string_field ("error", "Access denied")
|
||||
-- end
|
||||
-- rep.execute
|
||||
-- end
|
||||
|
||||
-- add_user_links_to (u: CMS_USER; rep: HM_WEBAPI_RESPONSE)
|
||||
-- do
|
||||
-- rep.add_link ("account", "user/" + u.id.out, rep.api.webapi_path ("/user/" + u.id.out))
|
||||
-- end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
177
src/modules/core/webapi/cms_core_webapi_access_token_handler.e
Normal file
177
src/modules/core/webapi/cms_core_webapi_access_token_handler.e
Normal file
@@ -0,0 +1,177 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_WEBAPI_ACCESS_TOKEN_HANDLER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CORE_WEBAPI_ACCESS_TOKEN_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_WEBAPI_HANDLER
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
local
|
||||
l_uid: READABLE_STRING_GENERAL
|
||||
do
|
||||
if attached {WSF_STRING} req.path_parameter ("uid") as p_uid then
|
||||
l_uid := p_uid.value
|
||||
if req.is_post_request_method then
|
||||
post_access_token (l_uid, req, res)
|
||||
elseif req.is_get_request_method then
|
||||
get_access_token (l_uid, req, res)
|
||||
else
|
||||
send_bad_request (Void, req, res)
|
||||
end
|
||||
else
|
||||
send_bad_request ("Missing {uid} parameter", req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
user_by_uid (a_uid: READABLE_STRING_GENERAL): detachable CMS_USER
|
||||
do
|
||||
Result := api.user_api.user_by_id_or_name (a_uid)
|
||||
end
|
||||
|
||||
feature -- Request execution
|
||||
|
||||
get_access_token (a_uid: READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
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
|
||||
rep := new_access_token_webapi_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)
|
||||
end
|
||||
rep.execute
|
||||
else
|
||||
-- Only admin, or current user can see its access_token!
|
||||
send_access_denied (Void, req, res)
|
||||
end
|
||||
else
|
||||
send_access_denied (Void, req, res)
|
||||
end
|
||||
else
|
||||
send_not_found ("User not found", req, res)
|
||||
end
|
||||
end
|
||||
|
||||
post_access_token (a_uid: READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
local
|
||||
l_access_token: detachable READABLE_STRING_32
|
||||
rep: like new_webapi_response
|
||||
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 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_webapi_response (l_user, l_access_token, req, res)
|
||||
if attached {WSF_STRING} req.item ("destination") as dest then
|
||||
rep.set_redirection (dest.url_encoded_value)
|
||||
end
|
||||
rep.execute
|
||||
else
|
||||
-- Only admin, or current user can create the user access_token!
|
||||
send_access_denied (Void, req, res)
|
||||
end
|
||||
else
|
||||
send_access_denied (Void, req, res)
|
||||
end
|
||||
else
|
||||
send_not_found ("User not found", req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
user_access_token (a_user: CMS_USER): READABLE_STRING_8
|
||||
do
|
||||
if
|
||||
attached api.user_api.user_profile_item ("access_token", a_user) as l_access_token and then
|
||||
not l_access_token.is_whitespace and then
|
||||
l_access_token.is_valid_as_string_8
|
||||
then
|
||||
Result := l_access_token.to_string_8
|
||||
else
|
||||
Result := new_key (40)
|
||||
end
|
||||
end
|
||||
|
||||
set_user_access_token (a_user: CMS_USER; a_access_token: READABLE_STRING_GENERAL)
|
||||
do
|
||||
api.user_api.save_user_profile_item (a_user, "access_token", a_access_token)
|
||||
end
|
||||
|
||||
new_access_token_webapi_response (a_user: CMS_USER; a_access_token: READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE): like new_webapi_response
|
||||
local
|
||||
tb: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
Result := new_webapi_response (req, res)
|
||||
Result.add_string_field ("access_token", a_access_token)
|
||||
create tb.make_equal (3)
|
||||
tb.force (a_user.name, "name")
|
||||
tb.force (a_user.id, "uid")
|
||||
Result.add_table_iterator_field ("user", tb)
|
||||
|
||||
-- Result.add_string_field ("username", a_user.name)
|
||||
-- Result.add_integer_64_field ("uid", a_user.id)
|
||||
Result.add_self (req.percent_encoded_path_info)
|
||||
add_user_links_to (a_user, Result)
|
||||
end
|
||||
|
||||
new_key (len: INTEGER): STRING_8
|
||||
local
|
||||
rand: RANDOM
|
||||
n: INTEGER
|
||||
v: NATURAL_32
|
||||
do
|
||||
create rand.set_seed ((create {DATE_TIME}.make_now_utc).seconds)
|
||||
rand.start
|
||||
create Result.make (len)
|
||||
from
|
||||
n := 1
|
||||
until
|
||||
n = len
|
||||
loop
|
||||
rand.forth
|
||||
v := (rand.item \\ 16).to_natural_32
|
||||
check 0 <= v and v <= 15 end
|
||||
if v < 9 then
|
||||
Result.append_code (48 + v) -- 48 '0'
|
||||
else
|
||||
Result.append_code (97 + v - 9) -- 97 'a'
|
||||
end
|
||||
n := n + 1
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
36
src/modules/core/webapi/cms_core_webapi_root_handler.e
Normal file
36
src/modules/core/webapi/cms_core_webapi_root_handler.e
Normal file
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_WEBAPI_ROOT_HANDLER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CORE_WEBAPI_ROOT_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_WEBAPI_HANDLER
|
||||
|
||||
WSF_URI_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
rep := new_webapi_response (req, res)
|
||||
rep.add_string_field ("site_name", api.setup.site_name)
|
||||
if attached api.user as u then
|
||||
add_user_links_to (u, rep)
|
||||
end
|
||||
rep.add_self (req.percent_encoded_path_info)
|
||||
rep.execute
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
80
src/modules/core/webapi/cms_core_webapi_user_handler.e
Normal file
80
src/modules/core/webapi/cms_core_webapi_user_handler.e
Normal file
@@ -0,0 +1,80 @@
|
||||
note
|
||||
description: "Summary description for {CMS_CORE_WEBAPI_USER_HANDLER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CORE_WEBAPI_USER_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_WEBAPI_HANDLER
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
do
|
||||
if req.is_get_request_method then
|
||||
execute_get (req, res)
|
||||
else
|
||||
send_bad_request (Void, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
execute_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute handler for `req' and respond in `res'.
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if attached api.user as u then
|
||||
if attached {WSF_STRING} req.path_parameter ("uid") as p_uid then
|
||||
if p_uid.is_integer then
|
||||
l_user := api.user_api.user_by_id (p_uid.integer_value)
|
||||
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_webapi_response (req, res)
|
||||
rep.add_string_field ("uid", u.id.out)
|
||||
|
||||
rep.add_string_field ("name", u.name)
|
||||
if attached u.email as l_email then
|
||||
rep.add_string_field ("email", l_email)
|
||||
end
|
||||
if attached u.profile_name as l_profile_name then
|
||||
rep.add_string_field ("profile_name", l_profile_name)
|
||||
end
|
||||
add_user_links_to (u, rep)
|
||||
else
|
||||
rep := new_wepapi_error_response ("denied", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.user_access_denied)
|
||||
end
|
||||
else
|
||||
rep := new_wepapi_error_response ("Not found", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||
end
|
||||
else
|
||||
rep := new_wepapi_error_response ("Bad request", req, res)
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.bad_request)
|
||||
end
|
||||
rep.execute
|
||||
else
|
||||
-- FIXME: use specific Web API response!
|
||||
send_access_denied (Void, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
@@ -19,6 +19,7 @@ inherit
|
||||
execute_default,
|
||||
filter_execute,
|
||||
initialize,
|
||||
initialize_filter,
|
||||
initialize_router
|
||||
end
|
||||
|
||||
@@ -61,6 +62,13 @@ feature {NONE} -- Initialization
|
||||
create {WSF_MAINTENANCE_FILTER} filter
|
||||
end
|
||||
|
||||
initialize_filter
|
||||
-- Initialize `filter`.
|
||||
do
|
||||
create_filter
|
||||
-- setup_filter: delayed to `initialize_execution`.
|
||||
end
|
||||
|
||||
initialize_router
|
||||
-- Initialize `router`.
|
||||
do
|
||||
@@ -147,11 +155,12 @@ feature -- Settings: router
|
||||
configure_api_file_handler (l_router)
|
||||
end
|
||||
|
||||
setup_router_for_webapi
|
||||
setup_router_and_filter_for_webapi
|
||||
local
|
||||
l_api: like api
|
||||
l_router: like router
|
||||
l_module: CMS_MODULE
|
||||
f, l_filter, l_last_filter: WSF_FILTER
|
||||
do
|
||||
l_api := api
|
||||
l_router := router
|
||||
@@ -161,6 +170,20 @@ feature -- Settings: router
|
||||
-- Configure root of api handler.
|
||||
l_router.set_base_url (l_api.webapi_path (Void))
|
||||
|
||||
-- Find insertion location for new filter
|
||||
-- i.e just before the CMS_EXECUTION filter.
|
||||
from
|
||||
l_filter := filter
|
||||
until
|
||||
l_last_filter /= Void or not attached l_filter.next as l_next_filter
|
||||
loop
|
||||
if l_next_filter.next = Void then
|
||||
l_last_filter := l_next_filter
|
||||
else
|
||||
l_filter := l_next_filter
|
||||
end
|
||||
end
|
||||
|
||||
-- Include routes from modules.
|
||||
across
|
||||
modules as ic
|
||||
@@ -172,25 +195,52 @@ feature -- Settings: router
|
||||
attached l_webapi.module_webapi as wapi
|
||||
then
|
||||
wapi.setup_router (l_router, l_api)
|
||||
if attached wapi.filters (l_api) as l_filters then
|
||||
across
|
||||
l_filters as f_ic
|
||||
loop
|
||||
f := f_ic.item
|
||||
l_filter.set_next (f)
|
||||
f.set_next (l_last_filter)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
setup_router_for_administration
|
||||
setup_router_and_filter_for_administration
|
||||
-- <Precursor>
|
||||
local
|
||||
l_api: like api
|
||||
l_router: like router
|
||||
l_module: CMS_MODULE
|
||||
f, l_filter, l_last_filter: WSF_FILTER
|
||||
do
|
||||
l_api := api
|
||||
l_router := router
|
||||
|
||||
l_api.logger.put_debug (generator + ".setup_router_for_administration", Void)
|
||||
l_api.logger.put_debug (generator + ".setup_router_and_filter_for_administration", Void)
|
||||
|
||||
-- Configure root of api handler.
|
||||
l_router.set_base_url (l_api.administration_path (Void))
|
||||
|
||||
-- Apply normal filters
|
||||
setup_filter
|
||||
|
||||
-- Find insertion location for new filter
|
||||
-- i.e just before the CMS_EXECUTION filter.
|
||||
from
|
||||
l_filter := filter
|
||||
until
|
||||
l_last_filter /= Void or not attached l_filter.next as l_next_filter
|
||||
loop
|
||||
if l_next_filter.next = Void then
|
||||
l_last_filter := l_next_filter
|
||||
else
|
||||
l_filter := l_next_filter
|
||||
end
|
||||
end
|
||||
|
||||
-- Include routes from modules.
|
||||
across
|
||||
modules as ic
|
||||
@@ -200,15 +250,24 @@ feature -- Settings: router
|
||||
l_module.is_initialized
|
||||
then
|
||||
if
|
||||
attached {CMS_ADMINISTRABLE} l_module as l_administration and then
|
||||
attached {CMS_WITH_MODULE_ADMINISTRATION} l_module as l_administration and then
|
||||
attached l_administration.module_administration as adm
|
||||
then
|
||||
adm.setup_router (l_router, l_api)
|
||||
elseif
|
||||
attached {CMS_WITH_WEBAPI} l_module as l_wapi and then
|
||||
attached l_wapi.module_webapi as wapi
|
||||
then
|
||||
wapi.setup_router (l_router, l_api)
|
||||
if attached adm.filters (l_api) as l_filters then
|
||||
across
|
||||
l_filters as f_ic
|
||||
loop
|
||||
f := f_ic.item
|
||||
l_filter.set_next (f)
|
||||
f.set_next (l_last_filter)
|
||||
end
|
||||
end
|
||||
-- elseif
|
||||
-- attached {CMS_WITH_WEBAPI} l_module as l_wapi and then
|
||||
-- attached l_wapi.module_webapi as wapi
|
||||
-- then
|
||||
-- wapi.setup_router (l_router, l_api)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -283,6 +342,7 @@ feature -- Request execution
|
||||
do
|
||||
api.switch_to_site_mode
|
||||
api.initialize_execution
|
||||
setup_filter
|
||||
setup_router
|
||||
end
|
||||
|
||||
@@ -291,7 +351,7 @@ feature -- Request execution
|
||||
do
|
||||
api.switch_to_webapi_mode
|
||||
api.initialize_execution
|
||||
setup_router_for_webapi
|
||||
setup_router_and_filter_for_webapi
|
||||
end
|
||||
|
||||
initialize_administration_execution
|
||||
@@ -299,7 +359,7 @@ feature -- Request execution
|
||||
do
|
||||
api.switch_to_administration_mode
|
||||
api.initialize_execution
|
||||
setup_router_for_administration
|
||||
setup_router_and_filter_for_administration
|
||||
end
|
||||
|
||||
execute
|
||||
@@ -341,6 +401,36 @@ feature -- Filters
|
||||
-- f.set_next (l_filter)
|
||||
-- l_filter := f
|
||||
|
||||
-- -- Include filters from modules
|
||||
-- across
|
||||
-- modules as ic
|
||||
-- loop
|
||||
-- l_module := ic.item
|
||||
-- if
|
||||
-- l_module.is_enabled and then
|
||||
-- attached l_module.filters (l_api) as l_m_filters
|
||||
-- then
|
||||
-- across l_m_filters as f_ic loop
|
||||
-- f := f_ic.item
|
||||
-- l_filter.append (f)
|
||||
---- f.set_next (l_filter)
|
||||
---- l_filter := f
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
filter := l_filter
|
||||
end
|
||||
|
||||
setup_filter
|
||||
-- Setup `filter'.
|
||||
local
|
||||
f, l_filter: detachable WSF_FILTER
|
||||
l_module: CMS_MODULE
|
||||
l_api: like api
|
||||
do
|
||||
l_api := api
|
||||
l_filter := filter
|
||||
-- Include filters from modules
|
||||
across
|
||||
modules as ic
|
||||
@@ -352,20 +442,15 @@ feature -- Filters
|
||||
then
|
||||
across l_m_filters as f_ic loop
|
||||
f := f_ic.item
|
||||
f.set_next (l_filter)
|
||||
l_filter := f
|
||||
l_filter.append (f)
|
||||
-- f.set_next (l_filter)
|
||||
-- l_filter := f
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
filter := l_filter
|
||||
end
|
||||
|
||||
setup_filter
|
||||
-- Setup `filter'.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
|
||||
@@ -15,11 +15,27 @@ feature -- Element change
|
||||
deferred
|
||||
end
|
||||
|
||||
add_field (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL)
|
||||
add_string_field (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL)
|
||||
deferred
|
||||
end
|
||||
|
||||
add_link (rel: READABLE_STRING_8; a_attname: READABLE_STRING_8 ; a_att_href: READABLE_STRING_8)
|
||||
add_boolean_field (a_name: READABLE_STRING_GENERAL; a_value: BOOLEAN)
|
||||
deferred
|
||||
end
|
||||
|
||||
add_integer_64_field (a_name: READABLE_STRING_GENERAL; a_value: INTEGER_64)
|
||||
deferred
|
||||
end
|
||||
|
||||
add_iterator_field (a_name: READABLE_STRING_GENERAL; a_value: ITERABLE [detachable ANY])
|
||||
deferred
|
||||
end
|
||||
|
||||
add_table_iterator_field (a_name: READABLE_STRING_GENERAL; a_value: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL])
|
||||
deferred
|
||||
end
|
||||
|
||||
add_link (rel: READABLE_STRING_8; a_attname: READABLE_STRING_8; a_att_href: READABLE_STRING_8)
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
@@ -31,14 +31,53 @@ feature -- Element change
|
||||
|
||||
add_self (a_href: READABLE_STRING_8)
|
||||
do
|
||||
add_field ("self", a_href)
|
||||
add_string_field ("self", a_href)
|
||||
end
|
||||
|
||||
add_field (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL)
|
||||
feature -- Fields
|
||||
|
||||
-- add_field (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
|
||||
-- do
|
||||
-- resource.put (new_resource_item (a_value), a_name)
|
||||
-- end
|
||||
|
||||
add_string_field (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL)
|
||||
do
|
||||
resource.put_string (a_value, a_name)
|
||||
end
|
||||
|
||||
add_boolean_field (a_name: READABLE_STRING_GENERAL; a_value: BOOLEAN)
|
||||
do
|
||||
resource.put_boolean (a_value, a_name)
|
||||
end
|
||||
|
||||
add_integer_64_field (a_name: READABLE_STRING_GENERAL; a_value: INTEGER_64)
|
||||
do
|
||||
resource.put_integer (a_value, a_name)
|
||||
end
|
||||
|
||||
add_natural_64_field (a_name: READABLE_STRING_GENERAL; a_value: NATURAL_64)
|
||||
do
|
||||
resource.put_natural (a_value, a_name)
|
||||
end
|
||||
|
||||
add_real_64_field (a_name: READABLE_STRING_GENERAL; a_value: REAL_64)
|
||||
do
|
||||
resource.put_real (a_value, a_name)
|
||||
end
|
||||
|
||||
add_iterator_field (a_name: READABLE_STRING_GENERAL; a_value: ITERABLE [detachable ANY])
|
||||
do
|
||||
resource.put (new_resource_item (a_value), a_name)
|
||||
end
|
||||
|
||||
add_table_iterator_field (a_name: READABLE_STRING_GENERAL; a_value: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL])
|
||||
do
|
||||
resource.put (new_resource_item (a_value), a_name)
|
||||
end
|
||||
|
||||
feature -- Links
|
||||
|
||||
add_link (rel: READABLE_STRING_8; a_attname: READABLE_STRING_8 ; a_att_href: READABLE_STRING_8)
|
||||
local
|
||||
lnks: JSON_OBJECT
|
||||
@@ -66,6 +105,68 @@ feature -- Execution
|
||||
response.send (m)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation factory
|
||||
|
||||
new_resource_item (a_value: detachable ANY): JSON_VALUE
|
||||
local
|
||||
l_serializer: JSON_REFLECTOR_SERIALIZER
|
||||
ctx: JSON_SERIALIZER_CONTEXT
|
||||
do
|
||||
create {JSON_NULL} Result
|
||||
|
||||
create l_serializer
|
||||
create ctx
|
||||
ctx.set_default_serializer (l_serializer)
|
||||
ctx.set_is_type_name_included (False)
|
||||
ctx.register_serializer (create {TABLE_ITERABLE_JSON_SERIALIZER [detachable ANY, READABLE_STRING_GENERAL]}, {TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]})
|
||||
ctx.register_serializer (create {ITERABLE_JSON_SERIALIZER [detachable ANY]}, {ITERABLE [detachable ANY]})
|
||||
Result := l_serializer.to_json (a_value, ctx)
|
||||
-- if a_value = Void then
|
||||
-- create {JSON_NULL} Result
|
||||
-- elseif attached {READABLE_STRING_GENERAL} a_value as s then
|
||||
-- create {JSON_STRING} Result.make_from_string_general (s)
|
||||
-- elseif attached {BOOLEAN} a_value as b then
|
||||
-- create {JSON_BOOLEAN} Result.make (b)
|
||||
-- elseif attached {NUMERIC} a_value as num then
|
||||
---- if attached {INTEGER_64} num as i64 then
|
||||
---- add_integer_64_field (a_name, i64)
|
||||
---- elseif attached {INTEGER_32} num as i32 then
|
||||
---- add_integer_64_field (a_name, i32.as_integer_64)
|
||||
---- elseif attached {INTEGER_16} num as i16 then
|
||||
---- add_integer_64_field (a_name, i16.as_integer_64)
|
||||
---- elseif attached {INTEGER_8} num as i8 then
|
||||
---- add_integer_64_field (a_name, i8.as_integer_64)
|
||||
---- elseif attached {NATURAL_64} num as n64 then
|
||||
---- add_natural_64_field (a_name, n64)
|
||||
---- elseif attached {NATURAL_32} num as n32 then
|
||||
---- add_natural_64_field (a_name, n32.as_natural_64)
|
||||
---- elseif attached {NATURAL_16} num as n16 then
|
||||
---- add_natural_64_field (a_name, n16.as_natural_64)
|
||||
---- elseif attached {NATURAL_8} num as n8 then
|
||||
---- add_natural_64_field (a_name, n8.as_natural_64)
|
||||
---- elseif attached {REAL_64} num as r64 then
|
||||
---- add_real_64_field (a_name, r64)
|
||||
---- elseif attached {REAL_32} num as r32 then
|
||||
---- add_real_64_field (a_name, r32.to_double
|
||||
---- else
|
||||
---- check is_basic_numeric_type: False end
|
||||
---- add_string_field (a_name, num.out)
|
||||
---- end
|
||||
-- elseif attached {CHARACTER_8} a_value as ch8 then
|
||||
---- add_string_field (a_name, ch8.out)
|
||||
-- elseif attached {CHARACTER_32} a_value as ch32 then
|
||||
---- add_string_field (a_name, ch32.out)
|
||||
-- elseif attached {POINTER} a_value as ptr then
|
||||
---- add_string_field (a_name, ptr.out)
|
||||
-- elseif attached {ITERABLE [detachable ANY]} a_value as arr then
|
||||
---- add_iterator_field (a_name, arr)
|
||||
-- elseif attached {TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]} a_value as tb then
|
||||
---- add_table_iterator_field (a_name, tb)
|
||||
-- else
|
||||
-- check is_supported_type: False end
|
||||
-- end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
note
|
||||
|
||||
100
src/service/webapi/cms_webapi_handler.e
Normal file
100
src/service/webapi/cms_webapi_handler.e
Normal file
@@ -0,0 +1,100 @@
|
||||
note
|
||||
description: "[
|
||||
Objects that ...
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
CMS_WEBAPI_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER
|
||||
|
||||
CMS_API_ACCESS
|
||||
|
||||
CMS_ENCODERS
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: CMS_API)
|
||||
-- Initialize Current handler with `a_api'.
|
||||
do
|
||||
api := a_api
|
||||
end
|
||||
|
||||
feature -- API Service
|
||||
|
||||
api: CMS_API
|
||||
|
||||
feature -- Factory
|
||||
|
||||
new_webapi_response (req: WSF_REQUEST; res: WSF_RESPONSE): HM_WEBAPI_RESPONSE
|
||||
do
|
||||
-- create {MD_WEBAPI_RESPONSE} Result.make (req, res, api)
|
||||
create {JSON_WEBAPI_RESPONSE} Result.make (req, res, api)
|
||||
end
|
||||
|
||||
new_wepapi_error_response (msg: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE): HM_WEBAPI_RESPONSE
|
||||
do
|
||||
Result := new_webapi_response (req, res)
|
||||
if msg /= Void then
|
||||
Result.add_string_field ("error", msg)
|
||||
else
|
||||
Result.add_string_field ("error", "True")
|
||||
end
|
||||
end
|
||||
|
||||
send_not_found (m: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
if m /= Void then
|
||||
rep := new_wepapi_error_response (m, req, res)
|
||||
else
|
||||
rep := new_wepapi_error_response ("Not found", req, res)
|
||||
end
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||
rep.execute
|
||||
end
|
||||
|
||||
send_access_denied (m: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
if m /= Void then
|
||||
rep := new_wepapi_error_response (m, req, res)
|
||||
else
|
||||
rep := new_wepapi_error_response ("Access denied", req, res)
|
||||
end
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.user_access_denied)
|
||||
rep.execute
|
||||
end
|
||||
|
||||
send_bad_request (m: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
rep: HM_WEBAPI_RESPONSE
|
||||
do
|
||||
if m /= Void then
|
||||
rep := new_wepapi_error_response (m, req, res)
|
||||
else
|
||||
rep := new_wepapi_error_response ("Bad request", req, res)
|
||||
end
|
||||
rep.set_status_code ({HTTP_STATUS_CODE}.bad_request)
|
||||
rep.execute
|
||||
end
|
||||
|
||||
feature {NONE} -- Builder
|
||||
|
||||
add_user_links_to (u: CMS_USER; rep: HM_WEBAPI_RESPONSE)
|
||||
do
|
||||
rep.add_link ("account", "user/" + u.id.out, rep.api.webapi_path ("/user/" + u.id.out))
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
Reference in New Issue
Block a user