Added webapi system and first attempt for the core webapi.

Added user profile system to the core module.
Moved /user/{uid} from auth module to core module.
Added possibility to add html before and after a cms form. (useful to add a form before or after, as nested form are forbidden).
Now theme can be installed using roc install command.
This commit is contained in:
Jocelyn Fiat
2017-07-11 20:53:48 +02:00
parent 34f0aa5844
commit db585a4873
61 changed files with 2382 additions and 511 deletions

View File

@@ -103,6 +103,24 @@ feature {NONE} -- Initialization
site_theme_name := text_item_or_default ("site.theme", "default")
set_theme (site_theme_name)
-- Webapi
webapi_enabled := string_8_item_or_default ("webapi.mode", "off").is_case_insensitive_equal_general ("on")
l_url := string_8_item ("webapi.base_path")
if l_url /= Void and then not l_url.is_empty then
if l_url [l_url.count] = '/' then
l_url := l_url.substring (1, l_url.count - 1)
end
if l_url [1] /= '/' then
l_url := "/" + l_url
end
create webapi_base_path.make_from_string (l_url)
else
create webapi_base_path.make_from_string (default_webapi_base_path)
end
-- Administration
l_url := string_8_item ("administration.base_path")
if l_url /= Void and then not l_url.is_empty then
@@ -117,6 +135,7 @@ feature {NONE} -- Initialization
create administration_base_path.make_from_string (default_administration_base_path)
end
administration_theme_name := text_item_or_default ("administration.theme", theme_name) -- TODO: Default to builtin theme?
end
feature -- Access
@@ -314,11 +333,19 @@ feature -- Access: Site
-- Optional path defining the front page.
-- By default "" or "/".
webapi_enabled: BOOLEAN
-- Is WebAPI enabled?
webapi_base_path: IMMUTABLE_STRING_8
-- Web API base url, default=`default_webapi_base_path`.
administration_base_path: IMMUTABLE_STRING_8
-- Administration base url, default=`default_administration_base_path`.
feature {NONE} -- Constants
default_webapi_base_path: STRING = "/api"
default_administration_base_path: STRING = "/admin"
feature -- Settings
@@ -338,6 +365,12 @@ feature -- Settings
end
end
set_webapi_mode
-- Switch to webapi mode.
do
set_site_mode
end
set_administration_mode
-- Switch to administration mode.
--| - Change theme

View File

@@ -110,7 +110,7 @@ feature -- Hook: form_alter
-- Add `h' as subscriber of form alter hooks CMS_HOOK_FORM_ALTER,
-- and response `a_response'.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_ALTER})
subscribe_to_hook (h, {CMS_HOOK_FORM_ALTER})
end
invoke_form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_response: CMS_RESPONSE)

View File

@@ -10,11 +10,68 @@ inherit
WSF_FORM
rename
process as process_form
redefine
append_to_html
end
create
make
feature -- Access
before_widgets: detachable ARRAYED_LIST [WSF_WIDGET]
-- Optional widget before the Current form.
after_widgets: detachable ARRAYED_LIST [WSF_WIDGET]
-- Optional widget after the Current form.
feature -- Element change
put_widget_before_form (w: WSF_WIDGET)
local
lst: like before_widgets
do
lst := before_widgets
if lst = Void then
create lst.make (1)
before_widgets := lst
end
lst.extend (w)
end
put_widget_after_form (w: WSF_WIDGET)
local
lst: like after_widgets
do
lst := after_widgets
if lst = Void then
create lst.make (1)
after_widgets := lst
end
lst.extend (w)
end
feature -- Conversion
append_to_html (a_theme: WSF_THEME; a_html: STRING_8)
do
if attached before_widgets as lst then
across
lst as ic
loop
ic.item.append_to_html (a_theme, a_html)
end
end
Precursor (a_theme, a_html)
if attached after_widgets as lst then
across
lst as ic
loop
ic.item.append_to_html (a_theme, a_html)
end
end
end
feature -- Basic operation
prepare (a_response: CMS_RESPONSE)
@@ -40,6 +97,6 @@ feature -- Basic operation
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
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

View File

@@ -10,10 +10,17 @@ inherit
CMS_MODULE
redefine
initialize,
setup_hooks,
install,
permissions
end
CMS_WITH_WEBAPI
CMS_HOOK_AUTO_REGISTER
CMS_HOOK_FORM_ALTER
create
make
@@ -41,10 +48,16 @@ feature {CMS_API} -- Module Initialization
feature {CMS_API} -- Module management
install (a_api: CMS_API)
local
l_parent_loc: PATH
do
-- Schema
if attached a_api.storage.as_sql_storage as l_sql_storage then
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended (name + ".sql")), Void)
l_parent_loc := a_api.module_resource_location (Current, create {PATH}.make_from_string ("scripts"))
l_sql_storage.sql_execute_file_script (l_parent_loc.extended (name + ".sql"), Void)
if not l_sql_storage.has_error then
l_sql_storage.sql_execute_file_script (l_parent_loc.extended ("user_profile.sql"), Void)
end
if l_sql_storage.has_error then
a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
@@ -81,6 +94,7 @@ feature {CMS_API} -- Module management
--! external configuration file?
--! at the moment we only have 1 admin to the whole site.
--! is that ok?
l_anonymous_role.add_permission ("view any page")
a_api.user_api.save_user_role (l_anonymous_role)
@@ -101,6 +115,7 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
a_router.handle ("/user/{uid}", create {CMS_USER_HANDLER}.make (a_api), a_router.methods_get)
end
feature -- Security
@@ -117,6 +132,54 @@ feature -- Security
Result.force ("edit path_alias")
end
feature {CMS_EXECUTION} -- Administration
webapi: CMS_CORE_MODULE_WEBAPI
do
create Result.make (Current)
end
feature -- Hooks
setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
do
a_hooks.subscribe_to_form_alter_hook (Current)
end
feature -- Hook
form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_response: CMS_RESPONSE)
-- Hook execution on form `a_form' and its associated data `a_form_data',
-- for related response `a_response'.
local
fset: WSF_FORM_FIELD_SET
tf: WSF_FORM_TEXT_INPUT
do
if
attached a_form.id as fid and then
fid.same_string ("roccms-user-view")
then
if
attached a_response.user as u and then
attached a_response.api.user_api as l_user_profile_api and then
attached l_user_profile_api.user_profile (u) as l_profile and then
not l_profile.is_empty
then
create fset.make
fset.set_legend ("User-Profile")
a_form.extend (fset)
across
l_profile as ic
loop
create tf.make_with_text (ic.key.to_string_32, ic.item)
tf.set_label (ic.key.to_string_32)
a_form.extend (tf)
end
end
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)"

View File

@@ -0,0 +1,188 @@
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

View File

@@ -8,12 +8,34 @@ class
inherit
CMS_MODULE_API
redefine
initialize
end
CMS_USER_PROFILE_API
redefine
initialize
end
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
initialize
do
Precursor {CMS_MODULE_API}
Precursor {CMS_USER_PROFILE_API}
user_storage := storage
end
feature -- Storage
user_storage: CMS_USER_STORAGE_I
-- User storage.
feature -- Validation
is_valid_username (a_name: READABLE_STRING_32): BOOLEAN
@@ -87,43 +109,43 @@ feature -- Access: user
user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
-- User by id `a_id', if any.
do
Result := storage.user_by_id (a_id)
Result := user_storage.user_by_id (a_id)
end
user_by_name (a_username: READABLE_STRING_GENERAL): detachable CMS_USER
-- User by name `a_user_name', if any.
do
Result := storage.user_by_name (a_username)
Result := user_storage.user_by_name (a_username)
end
user_by_email (a_email: READABLE_STRING_GENERAL): detachable CMS_USER
-- User by email `a_email', if any.
do
Result := storage.user_by_email (a_email)
Result := user_storage.user_by_email (a_email)
end
user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- User by activation token `a_token'.
do
Result := storage.user_by_activation_token (a_token)
Result := user_storage.user_by_activation_token (a_token)
end
user_by_password_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- User by password token `a_token'.
do
Result := storage.user_by_password_token (a_token)
Result := user_storage.user_by_password_token (a_token)
end
users_count: INTEGER
-- Number of users.
do
Result := storage.users_count
Result := user_storage.users_count
end
recent_users (params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_USER]
-- List of the `a_rows' most recent users starting from `a_offset'.
do
Result := storage.recent_users (params.offset.to_integer_32, params.size.to_integer_32)
Result := user_storage.recent_users (params.offset.to_integer_32, params.size.to_integer_32)
end
admin_user: detachable CMS_USER
@@ -149,8 +171,8 @@ feature -- Change User
if
attached a_user.email as l_email
then
storage.new_user (a_user)
error_handler.append (storage.error_handler)
user_storage.new_user (a_user)
error_handler.append (user_storage.error_handler)
else
error_handler.add_custom_error (0, "bad new user request", "Missing password or email to create new user!")
end
@@ -164,8 +186,8 @@ feature -- Change User
user_by_name (a_new_username) = Void
do
reset_error
storage.update_username (a_user, a_new_username)
error_handler.append (storage.error_handler)
user_storage.update_username (a_user, a_new_username)
error_handler.append (user_storage.error_handler)
end
update_user (a_user: CMS_USER)
@@ -174,8 +196,8 @@ feature -- Change User
has_id: a_user.has_id
do
reset_error
storage.update_user (a_user)
error_handler.append (storage.error_handler)
user_storage.update_user (a_user)
error_handler.append (user_storage.error_handler)
end
delete_user (a_user: CMS_USER)
@@ -184,8 +206,8 @@ feature -- Change User
has_id: a_user.has_id
do
reset_error
storage.delete_user (a_user)
error_handler.append (storage.error_handler)
user_storage.delete_user (a_user)
error_handler.append (user_storage.error_handler)
end
feature -- Status report
@@ -193,7 +215,7 @@ feature -- Status report
is_valid_credential (a_auth_login, a_auth_password: READABLE_STRING_32): BOOLEAN
-- Is the credentials `a_auth_login' and `a_auth_password' valid?
do
Result := storage.is_valid_credential (a_auth_login, a_auth_password)
Result := user_storage.is_valid_credential (a_auth_login, a_auth_password)
end
user_has_permission (a_user: detachable CMS_USER; a_permission: detachable READABLE_STRING_GENERAL): BOOLEAN
@@ -229,7 +251,7 @@ feature -- Status report
if l_roles = Void then
-- Fill user with its roles.
create {ARRAYED_LIST [CMS_USER_ROLE]} l_roles.make (0)
l_roles := storage.user_roles_for (a_user)
l_roles := user_storage.user_roles_for (a_user)
end
Result := l_roles
end
@@ -262,13 +284,13 @@ feature -- User roles.
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
-- Retrieve a `Role' represented by an id `a_id' if any.
do
Result := storage.user_role_by_id (a_id)
Result := user_storage.user_role_by_id (a_id)
end
user_role_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_USER_ROLE
-- Retrieve a `Role' represented by a name `a_name' if any.
do
Result := storage.user_role_by_name (a_name)
Result := user_storage.user_role_by_name (a_name)
end
role_permissions: HASH_TABLE [LIST [READABLE_STRING_8], STRING_8]
@@ -278,12 +300,16 @@ feature -- User roles.
do
create Result.make (cms_api.enabled_modules.count + 1)
l_used_permissions := storage.role_permissions
l_used_permissions := user_storage.role_permissions
across
cms_api.enabled_modules as ic
loop
lst := ic.item.permissions
if attached {CMS_ADMINISTRABLE} ic.item as adm then
if
attached {CMS_ADMINISTRABLE} ic.item as adm and then
attached adm.module_administration.permissions as adm_permissions and then
not adm_permissions.is_empty
then
create {ARRAYED_LIST [READABLE_STRING_8]} l_full_lst.make (lst.count)
l_full_lst.compare_objects
-- l_full_lst.append (lst)
@@ -294,14 +320,38 @@ feature -- User roles.
l_full_lst.extend (lst_ic.item)
end
end
-- l_full_lst.append (adm.module_administration.permissions)
lst := adm.module_administration.permissions
-- l_full_lst.append (adm_permissions)
across
adm_permissions as lst_ic
loop
if not l_full_lst.has (lst_ic.item) then
l_full_lst.extend (lst_ic.item)
end
end
lst := l_full_lst
end
if
attached {CMS_WITH_WEBAPI} ic.item as wapi and then
attached wapi.module_webapi.permissions as wapi_permissions and then
not wapi_permissions.is_empty
then
create {ARRAYED_LIST [READABLE_STRING_8]} l_full_lst.make (lst.count)
l_full_lst.compare_objects
-- l_full_lst.append (lst)
across
lst as lst_ic
loop
if not l_full_lst.has (lst_ic.item) then
l_full_lst.extend (lst_ic.item)
end
end
-- l_full_lst.append (wapi_permissions)
across
wapi_permissions as lst_ic
loop
if not l_full_lst.has (lst_ic.item) then
l_full_lst.extend (lst_ic.item)
end
end
lst := l_full_lst
end
@@ -331,7 +381,7 @@ feature -- User roles.
roles: LIST [CMS_USER_ROLE]
-- List of possible roles.
do
Result := storage.user_roles
Result := user_storage.user_roles
end
effective_roles: LIST [CMS_USER_ROLE]
@@ -340,7 +390,7 @@ feature -- User roles.
l_roles: like roles
r: CMS_USER_ROLE
do
l_roles := storage.user_roles
l_roles := user_storage.user_roles
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (l_roles.count)
across
l_roles as ic
@@ -357,7 +407,7 @@ feature -- User roles.
roles_count: INTEGER
-- Number of roles
do
Result := storage.user_roles.count
Result := user_storage.user_roles.count
end
feature -- Change User role
@@ -365,31 +415,31 @@ feature -- Change User role
save_user_role (a_user_role: CMS_USER_ROLE)
do
reset_error
storage.save_user_role (a_user_role)
error_handler.append (storage.error_handler)
user_storage.save_user_role (a_user_role)
error_handler.append (user_storage.error_handler)
end
unassign_role_from_user (a_role: CMS_USER_ROLE; a_user: CMS_USER; )
-- Unassign user_role `a_role' to user `a_user'.
do
reset_error
storage.unassign_role_from_user (a_role, a_user)
error_handler.append (storage.error_handler)
user_storage.unassign_role_from_user (a_role, a_user)
error_handler.append (user_storage.error_handler)
end
assign_role_to_user (a_role: CMS_USER_ROLE; a_user: CMS_USER; )
-- Assign user_role `a_role' to user `a_user'.
do
reset_error
storage.assign_role_to_user (a_role, a_user)
error_handler.append (storage.error_handler)
user_storage.assign_role_to_user (a_role, a_user)
error_handler.append (user_storage.error_handler)
end
delete_role (a_role: CMS_USER_ROLE)
do
reset_error
storage.delete_role (a_role)
error_handler.append (storage.error_handler)
user_storage.delete_role (a_role)
error_handler.append (user_storage.error_handler)
end
feature -- User Activation
@@ -397,7 +447,7 @@ feature -- User Activation
new_activation (a_token: READABLE_STRING_32; a_id: INTEGER_64)
-- Save activation token `a_token', for the user with the id `a_id'.
do
storage.save_activation (a_token, a_id)
user_storage.save_activation (a_token, a_id)
end
feature -- User Password Recovery
@@ -405,13 +455,13 @@ feature -- User Password Recovery
new_password (a_token: READABLE_STRING_32; a_id: INTEGER_64)
-- Save password token `a_token', for the user with the id `a_id'.
do
storage.save_password (a_token, a_id)
user_storage.save_password (a_token, a_id)
end
remove_password (a_token: READABLE_STRING_32)
-- Remove password token `a_token', from the storage.
-- Remove password token `a_token', from the user_storage.
do
storage.remove_password (a_token)
user_storage.remove_password (a_token)
end
feature -- User status
@@ -423,7 +473,7 @@ feature -- User status
-- The user is active
Trashed: INTEGER = -1
-- The user is trashed (soft delete), ready to be deleted/destroyed from storage.
-- The user is trashed (soft delete), ready to be deleted/destroyed from user_storage.
feature -- Access - Temp User
@@ -431,36 +481,36 @@ feature -- Access - Temp User
-- Number of pending users.
--! to be accepted or rehected
do
Result := storage.temp_users_count
Result := user_storage.temp_users_count
end
temp_user_by_name (a_username: READABLE_STRING_GENERAL): detachable CMS_USER
-- User by name `a_user_name', if any.
do
Result := storage.temp_user_by_name (a_username.as_string_32)
Result := user_storage.temp_user_by_name (a_username.as_string_32)
end
temp_user_by_email (a_email: READABLE_STRING_8): detachable CMS_USER
-- User by email `a_email', if any.
do
Result := storage.temp_user_by_email (a_email)
Result := user_storage.temp_user_by_email (a_email)
end
temp_user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- User by activation token `a_token'.
do
Result := storage.temp_user_by_activation_token (a_token)
Result := user_storage.temp_user_by_activation_token (a_token)
end
temp_recent_users (params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_TEMP_USER]
-- List of the `a_rows' most recent users starting from `a_offset'.
do
Result := storage.temp_recent_users (params.offset.to_integer_32, params.size.to_integer_32)
Result := user_storage.temp_recent_users (params.offset.to_integer_32, params.size.to_integer_32)
end
token_by_temp_user_id (a_id: like {CMS_USER}.id): detachable STRING
do
Result := storage.token_by_temp_user_id (a_id)
Result := user_storage.token_by_temp_user_id (a_id)
end
feature -- Change Temp User
@@ -477,8 +527,8 @@ feature -- Change Temp User
attached a_temp_user.salt as l_salt and then
attached a_temp_user.email as l_email
then
storage.new_user_from_temp_user (a_temp_user)
error_handler.append (storage.error_handler)
user_storage.new_user_from_temp_user (a_temp_user)
error_handler.append (user_storage.error_handler)
else
error_handler.add_custom_error (0, "bad new user request", "Missing password or email to create new user!")
end
@@ -495,17 +545,17 @@ feature -- Change Temp User
attached a_temp_user.password as l_password and then
attached a_temp_user.email as l_email
then
storage.new_temp_user (a_temp_user)
error_handler.append (storage.error_handler)
user_storage.new_temp_user (a_temp_user)
error_handler.append (user_storage.error_handler)
else
error_handler.add_custom_error (0, "bad new user request", "Missing password or email to create new user!")
end
end
remove_activation (a_token: READABLE_STRING_32)
-- Remove activation token `a_token', from the storage.
-- Remove activation token `a_token', from the user_storage.
do
storage.remove_activation (a_token)
user_storage.remove_activation (a_token)
end
delete_temp_user (a_temp_user: CMS_TEMP_USER)
@@ -514,10 +564,38 @@ feature -- Change Temp User
has_id: a_temp_user.has_id
do
reset_error
storage.delete_temp_user (a_temp_user)
error_handler.append (storage.error_handler)
user_storage.delete_temp_user (a_temp_user)
error_handler.append (user_storage.error_handler)
end
--feature -- Access: User profile
-- user_profile (a_user: CMS_USER): detachable CMS_USER_PROFILE
-- -- User profile for `a_user'.
-- require
-- valid_user: a_user.has_id
-- do
-- Result := user_profile_storage.user_profile (a_user)
-- end
-- user_profile_item (a_item_name: READABLE_STRING_GENERAL; a_user: CMS_USER): detachable READABLE_STRING_32
-- -- User profile item `a_item_name` for `a_user`.
-- require
-- valid_user: a_user.has_id
-- do
-- Result := user_profile_storage.user_profile_item (a_user, a_item_name)
-- end
--feature -- Change: User profile
-- save_user_profile (a_user: CMS_USER; a_user_profile: CMS_USER_PROFILE)
-- -- Save `a_user' profile `a_user_profile'.
-- require
-- valid_user: a_user.has_id
-- do
-- user_profile_storage.save_user_profile (a_user, a_user_profile)
-- 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)"

View File

@@ -0,0 +1,78 @@
note
description: "API to handle user profiles."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_PROFILE_API
inherit
CMS_MODULE_API
redefine
initialize
end
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
initialize
-- <Precursor>
do
Precursor
-- Storage initialization
if attached cms_api.storage.as_sql_storage as l_storage_sql then
create {CMS_USER_PROFILE_STORAGE_SQL} user_profile_storage.make (l_storage_sql)
else
-- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_USER_PROFILE_STORAGE_NULL} user_profile_storage
end
end
feature {CMS_MODULE} -- Access nodes storage.
user_profile_storage: CMS_USER_PROFILE_STORAGE_I
feature -- Access: profile
user_profile (a_user: CMS_USER): detachable CMS_USER_PROFILE
-- User profile for `a_user'.
require
valid_user: a_user.has_id
do
Result := user_profile_storage.user_profile (a_user)
end
user_profile_item (a_item_name: READABLE_STRING_GENERAL; a_user: CMS_USER): detachable READABLE_STRING_32
-- User profile item `a_item_name` for `a_user`.
require
valid_user: a_user.has_id
do
Result := user_profile_storage.user_profile_item (a_user, a_item_name)
end
feature -- Change: profile
save_user_profile (a_user: CMS_USER; a_user_profile: CMS_USER_PROFILE)
-- Save `a_user' profile `a_user_profile'.
require
valid_user: a_user.has_id
do
user_profile_storage.save_user_profile (a_user, a_user_profile)
end
save_user_profile_item (a_user: CMS_USER; a_user_profile_name, a_user_profile_value: READABLE_STRING_GENERAL)
-- Save `a_user' profile item `a_user_profile_name=a_user_profile_value`.
require
valid_user: a_user.has_id
do
user_profile_storage.save_user_profile_item (a_user, a_user_profile_name, a_user_profile_value)
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

View File

@@ -0,0 +1,105 @@
note
description: "[
Handler for a CMS user in the CMS interface
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_HANDLER
inherit
CMS_HANDLER
WSF_URI_HANDLER
rename
execute as uri_execute,
new_mapping as new_uri_mapping
end
WSF_URI_TEMPLATE_HANDLER
rename
execute as uri_template_execute,
new_mapping as new_uri_template_mapping
select
new_uri_template_mapping
end
WSF_RESOURCE_HANDLER_HELPER
redefine
do_get
end
REFACTORING_HELPER
create
make
feature -- execute
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
execute_methods (req, res)
end
uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
execute (req, res)
end
uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
execute (req, res)
end
feature -- Query
user_path_parameter (req: WSF_REQUEST): detachable CMS_USER
-- User id (uid or username) passed as path parameter for request `req'.
local
s: STRING
l_uid: INTEGER_64
do
if attached {WSF_STRING} req.path_parameter ("uid") as p_nid then
s := p_nid.value
if s.is_integer_64 then
l_uid := s.to_integer_64
if l_uid > 0 then
Result := api.user_api.user_by_id (l_uid)
end
else
Result := api.user_api.user_by_name (s)
end
end
end
feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor>
local
l_user: detachable CMS_USER
l_uid: INTEGER_64
do
if api.has_permission ("view user") then
-- Display existing node
l_user := user_path_parameter (req)
if
l_user /= Void
then
(create {CMS_USER_VIEW_RESPONSE}.make_with_user (l_user, req, res, api)).execute
else
send_not_found (req, res)
end
else
send_access_denied (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

View File

@@ -0,0 +1,137 @@
note
description: "Summary description for {CMS_USER_VIEW_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_VIEW_RESPONSE
inherit
CMS_RESPONSE
create
make_with_user
feature {NONE} -- Initialization
make_with_user (u: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
make (req, res, a_api)
associated_user := u
end
feature -- Access
associated_user: CMS_USER
feature -- Query
user_id_path_parameter (req: WSF_REQUEST): INTEGER_64
-- User id passed as path parameter for request `req'.
local
s: STRING
do
if attached {WSF_STRING} req.path_parameter ("uid") as p_nid then
s := p_nid.value
if s.is_integer_64 then
Result := s.to_integer_64
end
end
end
feature -- Process
process
-- Computed response message.
local
b: STRING_8
f: CMS_FORM
do
create b.make_empty
if
attached associated_user as l_user
then
if
api.has_permission ("view user")
or l_user.same_as (user) -- Same user
then
f := new_view_form (l_user, request.request_uri, "view-user")
f.append_to_html (wsf_theme, b)
else
b.append ("You don't have the permission to view this user!")
end
else
b.append ("User not found!")
end
set_main_content (b)
end
feature -- Process Edit
new_view_form (a_user: detachable CMS_USER; a_url: READABLE_STRING_8; a_name: STRING): CMS_FORM
-- Create a web form named `a_name' for user `a_user' (if set), using form action url `a_url'.
local
th: WSF_FORM_HIDDEN_INPUT
do
create Result.make (a_url, a_name)
create th.make ("user-id")
if a_user /= Void then
th.set_text_value (a_user.id.out)
else
th.set_text_value ("0")
end
Result.extend (th)
populate_form (Result, a_user)
end
populate_form (a_form: CMS_FORM; a_user: detachable CMS_USER)
-- Fill the web form `a_form' with data from `a_node' if set,
-- and apply this to content type `a_content_type'.
local
ti: WSF_FORM_TEXT_INPUT
fs: WSF_FORM_FIELD_SET
l_new_access_token_form: WSF_FORM
l_access_token: detachable READABLE_STRING_32
do
if a_user /= Void then
create fs.make
fs.set_legend ("User Information")
create ti.make_with_text ("profile_name", a_user.name)
if attached a_user.profile_name as l_profile_name then
ti.set_text_value (l_profile_name)
end
ti.set_label ("Profile name")
ti.set_is_readonly (True)
fs.extend (ti)
a_form.extend (fs)
if api.setup.webapi_enabled then
create fs.make
fs.set_legend ("Web API")
l_access_token := api.user_api.user_profile_item ("access_token", a_user)
if l_access_token /= Void then
create ti.make_with_text ("api_access_token", a_user.name)
ti.set_text_value (l_access_token)
ti.set_label ("Access Token")
ti.set_is_readonly (True)
fs.extend (ti)
end
create l_new_access_token_form.make (api.webapi_path ("access_token"), Void)
l_new_access_token_form.set_method_post
if l_access_token /= Void then
l_new_access_token_form.extend (create {WSF_FORM_SUBMIT_INPUT}.make_with_text ("access_token_op", "Refresh Access Token"))
else
l_new_access_token_form.extend (create {WSF_FORM_SUBMIT_INPUT}.make_with_text ("access_token_op", "Create Access Token"))
end
l_new_access_token_form.extend (create {WSF_FORM_HIDDEN_INPUT}.make_with_text ("destination", request.percent_encoded_path_info))
a_form.put_widget_after_form (l_new_access_token_form)
a_form.extend (fs)
end
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

View File

@@ -800,7 +800,7 @@ feature -- Change: User activation
sql_begin_transaction
write_information_log (generator + ".save_activation")
create l_utc_date.make_now_utc
create l_parameters.make (2)
create l_parameters.make (3)
l_parameters.put (a_token, "token")
l_parameters.put (a_id, "uid")
l_parameters.put (l_utc_date, "utc_date")

View File

@@ -0,0 +1,57 @@
note
description: "Interface for accessing user profile contents from the database."
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_USER_PROFILE_STORAGE_I
feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
deferred
end
feature -- Access
user_profile (a_user: CMS_USER): detachable CMS_USER_PROFILE
-- User profile for `a_user'.
require
has_id: a_user.has_id
deferred
end
user_profile_item (a_user: CMS_USER; a_item_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
require
valid_user: a_user.has_id
do
if attached user_profile (a_user) as pf then
Result := pf.item (a_item_name)
end
end
feature -- Change
save_user_profile (a_user: CMS_USER; a_profile: CMS_USER_PROFILE)
-- Save user profile `a_profile' for `a_user'.
require
user_has_id: a_user.has_id
deferred
end
save_user_profile_item (a_user: CMS_USER; a_profile_item_name: READABLE_STRING_GENERAL; a_profile_item_value: READABLE_STRING_GENERAL)
require
user_has_id: a_user.has_id
local
pf: detachable CMS_USER_PROFILE
do
pf := user_profile (a_user)
if pf = Void then
create pf.make
end
pf.force (a_profile_item_value, a_profile_item_name)
save_user_profile (a_user, pf)
end
end

View File

@@ -0,0 +1,34 @@
note
description: "Summary description for {CMS_USER_PROFILE_STORAGE_NULL}."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_PROFILE_STORAGE_NULL
inherit
CMS_USER_PROFILE_STORAGE_I
feature -- Error handler
error_handler: ERROR_HANDLER
-- Error handler.
do
create Result.make
end
feature -- Access
user_profile (a_user: CMS_USER): detachable CMS_USER_PROFILE
-- <Precursor>
do
end
feature -- Change
save_user_profile (a_user: CMS_USER; a_profile: CMS_USER_PROFILE)
-- <Precursor>
do
end
end

View File

@@ -0,0 +1,153 @@
note
description: "Interface for accessing user profile contents from SQL database."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_PROFILE_STORAGE_SQL
inherit
CMS_USER_PROFILE_STORAGE_I
redefine
user_profile_item,
save_user_profile_item
end
CMS_PROXY_STORAGE_SQL
CMS_STORAGE_SQL_I
create
make
feature -- Access
user_profile_item (a_user: CMS_USER; a_item_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
-- User profile for `a_user'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
reset_error
create l_parameters.make (2)
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_item_name, "key")
sql_query (sql_select_user_profile_item, l_parameters)
if not has_error then
Result := sql_read_string_32 (2)
end
sql_finalize
end
user_profile (a_user: CMS_USER): detachable CMS_USER_PROFILE
-- User profile for `a_user'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
reset_error
create l_parameters.make (1)
l_parameters.put (a_user.id, "uid")
sql_query (sql_select_user_profile_items, l_parameters)
if not has_error then
create Result.make
from
sql_start
until
sql_after or has_error
loop
if
attached sql_read_string_32 (1) as l_key and
attached sql_read_string_32 (2) as l_val
then
Result.force (l_val, l_key)
end
sql_forth
end
end
sql_finalize
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")
l_parameters.put (a_item_name, "key")
l_parameters.put (a_item_value, "value")
reset_error
if user_profile_item (a_user, a_item_name) = Void then
sql_insert (sql_insert_user_profile_item, l_parameters)
else
sql_modify (sql_update_user_profile_item, l_parameters)
end
sql_finalize
end
save_user_profile (a_user: CMS_USER; a_profile: CMS_USER_PROFILE)
-- Save user profile `a_profile' for `a_user'.
local
l_parameters: STRING_TABLE [detachable ANY]
p: detachable CMS_USER_PROFILE
l_item: like user_profile_item
l_is_new: BOOLEAN
l_has_diff: BOOLEAN
do
p := user_profile (a_user)
create l_parameters.make (3)
reset_error
across
a_profile as ic
until
has_error
loop
l_item := ic.item
-- No previous profile, or no item with same name, or same value
l_has_diff := True
if p = Void then
l_is_new := True
elseif p.has_key (ic.key) then
l_is_new := False
l_has_diff := attached p.item (ic.key) as l_prev_item and then not l_prev_item.same_string (l_item)
else
l_is_new := True
end
if l_has_diff then
l_parameters.put (a_user.id, "uid")
l_parameters.put (ic.key, "key")
l_parameters.put (l_item, "value")
if l_is_new then
sql_insert (sql_insert_user_profile_item, l_parameters)
else
sql_modify (sql_update_user_profile_item, l_parameters)
end
l_parameters.wipe_out
end
end
sql_finalize
end
feature {NONE} -- Queries
sql_select_user_profile_items: STRING = "SELECT key, value FROM user_profiles WHERE uid=:uid;"
-- user profile items for :uid;
sql_select_user_profile_item: STRING = "SELECT key, value FROM user_profiles WHERE uid=:uid AND key=:key"
-- user profile items for :uid;
sql_insert_user_profile_item: STRING = "INSERT INTO user_profiles (uid, key, value) VALUES (:uid, :key, :value);"
-- new user profile item for :uid;
sql_update_user_profile_item: STRING = "UPDATE user_profiles SET value = :value WHERE uid = :uid AND key = :key;"
-- user profile items for :uid;
end

View File

@@ -6,29 +6,8 @@ note
deferred class
CMS_ADMINISTRABLE
feature -- Administration
module_administration: like administration
-- Associated administration module.
do
Result := internal_module_administration
if Result = Void then
Result := administration
internal_module_administration := Result
end
end
feature {NONE} -- Implementation
internal_module_administration: detachable like module_administration
-- Cached version of `module_administration`.
feature {NONE} -- Administration
administration: CMS_MODULE_ADMINISTRATION [CMS_MODULE]
-- Administration module.
deferred
end
inherit
CMS_WITH_MODULE_ADMINISTRATION
note
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"

View File

@@ -54,6 +54,10 @@ feature {NONE} -- Initialize
s := setup.administration_base_path
administration_base_path_location := s.shared_substring (2, s.count)
-- Webapi backend
s := setup.webapi_base_path
webapi_base_path_location := s.shared_substring (2, s.count)
-- Initialize contents.
initialize_content_types
@@ -398,6 +402,55 @@ feature -- Access: url
site_url: IMMUTABLE_STRING_8
-- Site url
feature -- Access: WebAPI
is_webapi_request (req: WSF_REQUEST): BOOLEAN
do
Result := setup.webapi_enabled and then req.percent_encoded_path_info.starts_with_general (setup.webapi_base_path)
end
webapi_path (a_relative_path: detachable READABLE_STRING_8): STRING_8
require
is_webapi_enabled: setup.webapi_enabled
do
create Result.make_from_string (setup.webapi_base_path)
if a_relative_path /= Void then
if a_relative_path.is_empty then
Result.append_character ('/')
else
if a_relative_path[1] /= '/' then
Result.append_character ('/')
end
Result.append (a_relative_path)
end
end
end
webapi_path_location (a_relative_location: detachable READABLE_STRING_8): STRING_8
require
is_webapi_enabled: setup.webapi_enabled
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
do
create Result.make_from_string (webapi_base_path_location)
if a_relative_location /= Void then
if a_relative_location.is_empty then
Result.append_character ('/')
else
if a_relative_location[1] /= '/' then
Result.append_character ('/')
end
Result.append (a_relative_location)
end
end
end
feature {NONE} -- Implementation/WebAPI.
webapi_base_path_location: IMMUTABLE_STRING_8
-- Webapi path without first slash!
feature -- Access: Administration
is_administration_request (req: WSF_REQUEST): BOOLEAN
do
Result := req.percent_encoded_path_info.starts_with_general (setup.administration_base_path)
@@ -435,13 +488,20 @@ feature -- Access: url
end
end
feature {NONE} -- Url implementation.
feature {NONE} -- Implementation/ Administration
administration_base_path_location: IMMUTABLE_STRING_8
-- Administration path without first slash!
feature -- CMS links
webapi_link (a_title: READABLE_STRING_GENERAL; a_relative_location: detachable READABLE_STRING_8): CMS_LOCAL_LINK
require
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
do
Result := local_link (a_title, webapi_path_location (a_relative_location))
end
administration_link (a_title: READABLE_STRING_GENERAL; a_relative_location: detachable READABLE_STRING_8): CMS_LOCAL_LINK
require
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
@@ -512,7 +572,15 @@ feature -- Settings
do
if is_administration_mode then
setup.set_site_mode
is_administration_mode := False
mode := mode_site
end
end
switch_to_webapi_mode
do
if is_webapi_mode then
setup.set_webapi_mode
mode := mode_webapi
end
end
@@ -520,12 +588,32 @@ feature -- Settings
do
if not is_administration_mode then
setup.set_administration_mode
is_administration_mode := True
mode := mode_administration
end
end
mode: NATURAL_8
mode_site: NATURAL_8 = 0
mode_administration: NATURAL_8 = 1
mode_webapi: NATURAL_8 = 2
is_site_mode: BOOLEAN
do
Result := mode = mode_site
end
is_administration_mode: BOOLEAN
-- Is administration mode?
do
Result := mode = mode_administration
end
is_webapi_mode: BOOLEAN
-- Is webapi mode?
do
Result := mode = mode_webapi
end
is_debug: BOOLEAN
-- Is debug mode enabled?
@@ -969,6 +1057,12 @@ feature {CMS_EXECUTION} -- Hooks
else
l_module := Void
end
elseif is_webapi_mode then
if attached {CMS_WITH_WEBAPI} l_module as wapi then
l_module := wapi.module_webapi
else
l_module := Void
end
end
if l_module /= Void then
if attached {CMS_HOOK_AUTO_REGISTER} l_module as l_auto then

View File

@@ -147,6 +147,35 @@ feature -- Settings: router
configure_api_file_handler (l_router)
end
setup_router_for_webapi
local
l_api: like api
l_router: like router
l_module: CMS_MODULE
do
l_api := api
l_router := router
l_api.logger.put_debug (generator + ".setup_router_for_webapi", Void)
-- Configure root of api handler.
l_router.set_base_url (l_api.webapi_path (Void))
-- Include routes from modules.
across
modules as ic
loop
l_module := ic.item
if
l_module.is_initialized and then
attached {CMS_WITH_WEBAPI} l_module as l_webapi and then
attached l_webapi.module_webapi as wapi
then
wapi.setup_router (l_router, l_api)
end
end
end
setup_router_for_administration
-- <Precursor>
local
@@ -168,11 +197,19 @@ feature -- Settings: router
loop
l_module := ic.item
if
l_module.is_initialized and then
attached {CMS_ADMINISTRABLE} l_module as l_administration and then
attached l_administration.module_administration as adm
l_module.is_initialized
then
adm.setup_router (l_router, l_api)
if
attached {CMS_ADMINISTRABLE} 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)
end
end
end
map_uri ("/install", create {CMS_ADMIN_INSTALL_HANDLER}.make (api), l_router.methods_head_get)
@@ -234,6 +271,8 @@ feature -- Request execution
request.set_uploaded_file_path (api.temp_location)
if api.is_administration_request (request) then
initialize_administration_execution
elseif api.is_webapi_request (request) then
initialize_webapi_execution
else
initialize_site_execution
end
@@ -247,6 +286,14 @@ feature -- Request execution
setup_router
end
initialize_webapi_execution
-- Initialize for site execution.
do
api.switch_to_webapi_mode
api.initialize_execution
setup_router_for_webapi
end
initialize_administration_execution
-- Initialize for administration execution.
do

View File

@@ -0,0 +1,80 @@
note
description: "[
Objects that ...
]"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_MODULE_WEBAPI [G -> CMS_MODULE]
inherit
CMS_MODULE
rename
is_initialized as module_is_initialized,
is_enabled as module_is_enabled
end
feature {NONE} -- Initialization
make (a_module: G)
-- Initialize `Current'.
do
module := a_module
version := a_module.version
description := a_module.description
package := a_module.package
module_is_initialized := a_module.is_initialized
module_is_enabled := a_module.is_enabled
end
feature -- Access
module: G
name: STRING
do
Result := module.name
end
feature -- Status
is_initialized: BOOLEAN
-- Is Current module initialized?
do
Result := module.is_initialized
end
is_enabled: BOOLEAN
-- Is Current module enabled?
do
Result := module.is_enabled
end
feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
if a_router.base_url /= Void then
setup_webapi_router (a_router, a_api)
end
end
feature {NONE} -- Router/administration
setup_webapi_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- Setup url dispatching for Current module web API.
-- (note: `a_router` is already based with webapi path prefix).
require
is_initialized: is_initialized
router_has_base_url: a_router.base_url /= Void
deferred
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

View File

@@ -0,0 +1,36 @@
note
description: "Interface providing administration module."
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_WITH_MODULE_ADMINISTRATION
feature -- Administration
module_administration: like administration
-- Associated administration module.
do
Result := internal_module_administration
if Result = Void then
Result := administration
internal_module_administration := Result
end
end
feature {NONE} -- Implementation
internal_module_administration: detachable like module_administration
-- Cached version of `module_administration`.
feature {NONE} -- Administration
administration: CMS_MODULE_ADMINISTRATION [CMS_MODULE]
-- Administration module.
deferred
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

View File

@@ -0,0 +1,36 @@
note
description: "Interface providing webapi module."
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_WITH_WEBAPI
feature -- Administration
module_webapi: like webapi
-- Associated web api module.
do
Result := internal_module_webapi
if Result = Void then
Result := webapi
internal_module_webapi := Result
end
end
feature {NONE} -- Implementation
internal_module_webapi: detachable like module_webapi
-- Cached version of `module_webapi`.
feature {NONE} -- Web API
webapi: CMS_MODULE_WEBAPI [CMS_MODULE]
-- Web API module.
deferred
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

View File

@@ -1,6 +1,6 @@
note
description: "[
Generic CMS Response.
Generic CMS Web Response.
It builds the content to get process to render the output.
]"
date: "$Date$"
@@ -10,64 +10,33 @@ deferred class
CMS_RESPONSE
inherit
CMS_URL_UTILITIES
CMS_RESPONSE_I
redefine
make, initialize
end
REFACTORING_HELPER
CMS_URL_UTILITIES
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
status_code := {HTTP_STATUS_CODE}.ok
api := a_api
request := req
response := res
create header.make
create values.make (3)
site_url := a_api.site_url
if attached a_api.base_url as l_base_url then
base_url := l_base_url
end
base_path := a_api.base_path
initialize
Precursor (req, res, a_api)
end
initialize
local
s: READABLE_STRING_8
do
Precursor
get_theme
create menu_system.make
initialize_block_region_settings
s := request.percent_encoded_path_info
if not s.is_empty and then s[1] = '/' then
create location.make_from_string (s.substring (2, s.count))
else
create location.make_from_string (s)
end
end
feature -- Access
request: WSF_REQUEST
response: WSF_RESPONSE
status_code: INTEGER
header: WSF_HEADER
main_content: detachable STRING_8
feature -- Settings
is_administration_mode: BOOLEAN
-- Is administration mode?
do
Result := api.is_administration_mode
end
feature -- Access: metadata
title: detachable READABLE_STRING_32
@@ -77,96 +46,19 @@ feature -- Access: metadata
description: detachable READABLE_STRING_32
keywords: detachable READABLE_STRING_32
publication_date: detachable DATE_TIME
-- Optional publication date.
modification_date: detachable DATE_TIME
-- Optional modification date.
additional_page_head_lines: detachable LIST [READABLE_STRING_8]
-- HTML>head>...extra lines
redirection: detachable READABLE_STRING_8
-- Location for eventual redirection.
redirection_delay: NATURAL
-- Optional redirection delay in seconds.
feature -- Access: query
location: IMMUTABLE_STRING_8
-- Associated cms local location.
request_url (opts: detachable CMS_API_OPTIONS): STRING_8
-- Current request location as a url.
do
Result := url (location, opts)
end
feature -- API
api: CMS_API
-- Current CMS API.
setup: CMS_SETUP
-- Current setup
do
Result := api.setup
end
formats: CMS_FORMATS
-- Available content formats.
do
Result := api.formats
end
feature -- URL utilities
is_front: BOOLEAN
-- Is current response related to "front" page?
local
l_path_info: READABLE_STRING_8
do
l_path_info := request.percent_encoded_path_info
if attached setup.front_page_path as l_front_page_path then
Result := l_front_page_path.same_string (l_path_info)
else
if base_path.same_string (l_path_info) then
Result := True
else
Result := l_path_info.is_empty or else l_path_info.same_string ("/")
end
end
end
site_url: IMMUTABLE_STRING_8
-- Absolute site url.
-- Always ends with '/'
base_url: detachable IMMUTABLE_STRING_8
-- Base url if any.
--| Usually it is Void, but it could be
--| /project/demo/
base_path: IMMUTABLE_STRING_8
-- Base path, default to "/".
-- Always ends with '/'
-- Could be /project/demo/
feature -- Access: CMS
site_name: STRING_32
do
Result := setup.site_name
end
front_page_url: READABLE_STRING_8
do
Result := absolute_url ("/", Void)
end
values: CMS_VALUE_TABLE
-- Associated values indexed by string name.
@@ -177,72 +69,6 @@ feature -- Specific values
Result := values.item ("optional_content_type")
end
feature -- User access
is_authenticated: BOOLEAN
-- Is user authenticated?
do
Result := user /= Void
end
user: detachable CMS_USER
-- Active user if authenticated.
do
Result := api.user
end
set_user (u: CMS_USER)
-- Set active user to `u'.
require
attached_u: u /= Void
do
api.set_user (u)
end
unset_user
-- Unset active user.
do
api.unset_user
end
feature -- Permission
has_permission_on_link (a_link: CMS_LINK): BOOLEAN
-- Does current user has permission to access link `a_link'?
do
Result := True
if
attached {CMS_LOCAL_LINK} a_link as lnk and then
attached lnk.permission_arguments as l_perms
then
Result := has_permissions (l_perms)
end
end
has_permission (a_permission: READABLE_STRING_GENERAL): BOOLEAN
-- Does current user has permission `a_permission' ?
do
Result := user_has_permission (user, a_permission)
end
has_permissions (a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
-- Does current user has any of the permissions `a_permission_list' ?
do
Result := user_has_permissions (user, a_permission_list)
end
user_has_permission (a_user: detachable CMS_USER; a_permission: READABLE_STRING_GENERAL): BOOLEAN
-- Does `a_user' has permission `a_permission' ?
do
Result := api.user_has_permission (a_user, a_permission)
end
user_has_permissions (a_user: detachable CMS_USER; a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
-- Does `a_user' has any of the permissions `a_permission_list' ?
do
Result := api.user_has_permissions (a_user, a_permission_list)
end
feature -- Head customization
add_additional_head_line (s: READABLE_STRING_8; a_allow_duplication: BOOLEAN)
@@ -322,27 +148,6 @@ feature -- Element change
description := d
end
set_keywords (s: like keywords)
do
keywords := s
end
set_publication_date (dt: like publication_date)
do
publication_date := dt
if dt /= Void and modification_date = Void then
modification_date := dt
end
end
set_modification_date (dt: like modification_date)
do
modification_date := dt
if dt /= Void and publication_date = Void then
publication_date := dt
end
end
set_main_content (s: like main_content)
do
main_content := s
@@ -365,34 +170,6 @@ feature -- Element change
values.remove (k)
end
set_redirection (a_location: READABLE_STRING_8)
-- Set `redirection' to `a_location'.
do
redirection := a_location
end
set_redirection_delay (nb_secs: NATURAL)
do
redirection_delay := nb_secs
end
feature -- Logging
log (a_category: READABLE_STRING_8; a_message: READABLE_STRING_8; a_level: INTEGER; a_link: detachable CMS_LINK)
local
-- l_log: CMS_LOG
do
debug
to_implement ("Add implementation")
end
-- create l_log.make (a_category, a_message, a_level, Void)
-- if a_link /= Void then
-- l_log.set_link (a_link)
-- end
-- l_log.set_info (request.http_user_agent)
-- service.storage.save_log (l_log)
end
feature -- Menu
menu_system: CMS_MENU_SYSTEM
@@ -904,16 +681,6 @@ feature -- Blocks
Result.set_is_raw (True)
end
feature -- Hooks
hooks: CMS_HOOK_CORE_MANAGER
-- Manager handling hook subscriptions.
obsolete
"Use api.hooks [2017-05-31]"
do
Result := api.hooks
end
feature -- Menu: change
add_to_main_menu (lnk: CMS_LINK)
@@ -938,22 +705,6 @@ feature -- Menu: change
m.extend (lnk)
end
feature -- Internationalization (i18n)
translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32
-- Translated text `a_text' according to expected context (lang, ...)
-- and adapt according to options eventually set by `opts'.
do
Result := api.translation (a_text, opts)
end
formatted_string (a_text: READABLE_STRING_GENERAL; args: TUPLE): STRING_32
-- Format `a_text' using arguments `args'.
--| ex: formatted_string ("hello $1, see page $title.", ["bob", "contact"] -> "hello bob, see page contact"
do
Result := api.formatted_string (a_text, args)
end
feature -- Message
add_message (a_msg: READABLE_STRING_8; a_category: detachable READABLE_STRING_8)
@@ -1068,19 +819,6 @@ feature {NONE} -- Theme helpers
internal_wsf_theme: detachable WSF_THEME
-- Once per object for `wsf_theme'.
feature -- Element Change
set_status_code (a_status: INTEGER)
-- Set `status_code' with `a_status'.
note
EIS: "src=eiffel:?class=HTTP_STATUS_CODE"
do
to_implement ("Feature to test if a_status is a valid status code!!!.")
status_code := a_status
ensure
status_code_set: status_code = a_status
end
feature -- Cache managment
clear_cache (a_cache_id_list: detachable ITERABLE [READABLE_STRING_GENERAL])
@@ -1366,32 +1104,8 @@ feature -- Generation
a_lnk.set_is_forbidden (not has_permission_on_link (a_lnk))
end
feature -- Helpers: cms link
administration_link (a_title: READABLE_STRING_GENERAL; a_relative_location: detachable READABLE_STRING_8): CMS_LOCAL_LINK
require
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
do
Result := api.administration_link (a_title, a_relative_location)
end
local_link (a_title: READABLE_STRING_GENERAL; a_location: READABLE_STRING_8): CMS_LOCAL_LINK
do
Result := api.local_link (a_title, a_location)
end
user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
do
Result := api.user_local_link (u, a_opt_title)
end
feature -- Helpers: html links
user_profile_name, user_display_name (u: CMS_USER): READABLE_STRING_32
do
Result := api.user_display_name (u)
end
user_html_link (u: CMS_USER): STRING
require
u_with_name: not u.name.is_whitespace
@@ -1399,43 +1113,6 @@ feature -- Helpers: html links
Result := api.user_html_link (u)
end
feature -- Helpers: URLs
location_absolute_url (a_location: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
-- Absolute URL for `a_location'.
--| Options `opts' could be
--| - absolute: True|False => return absolute url
--| - query: string => append "?query"
--| - fragment: string => append "#fragment"
do
Result := api.location_absolute_url (a_location, opts)
end
location_url (a_location: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
-- URL for `a_location'.
--| Options `opts' could be
--| - absolute: True|False => return absolute url
--| - query: string => append "?query"
--| - fragment: string => append "#fragment"
do
Result := api.location_url (a_location, opts)
end
module_resource_url (a_module: CMS_MODULE; a_path: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING_8
-- Url for resource `a_path` associated with module `a_module`.
require
a_valid_valid: a_path.is_empty or else a_path.starts_with ("/")
do
Result := url ("/module/" + a_module.name + a_path, opts)
end
user_url (u: CMS_USER): like url
require
u_with_id: u.has_id
do
Result := api.user_url (u)
end
feature -- Execution
execute
@@ -1499,7 +1176,6 @@ feature {NONE} -- Execution
on_terminated
do
end
note

View File

@@ -0,0 +1,376 @@
note
description: "[
Generic CMS Response.
It builds the content to get process to render the output.
]"
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_RESPONSE_I
inherit
CMS_URL_UTILITIES
REFACTORING_HELPER
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
status_code := {HTTP_STATUS_CODE}.ok
api := a_api
request := req
response := res
create header.make
site_url := a_api.site_url
if attached a_api.base_url as l_base_url then
base_url := l_base_url
end
base_path := a_api.base_path
initialize
end
initialize
local
s: READABLE_STRING_8
do
s := request.percent_encoded_path_info
if not s.is_empty and then s[1] = '/' then
create location.make_from_string (s.substring (2, s.count))
else
create location.make_from_string (s)
end
end
feature -- Access
request: WSF_REQUEST
response: WSF_RESPONSE
status_code: INTEGER
header: WSF_HEADER
feature -- Settings
is_site_mode: BOOLEAN
-- Is site mode?
do
Result := api.is_site_mode
end
is_webapi_mode: BOOLEAN
-- Is Web API mode?
do
Result := api.is_webapi_mode
end
is_administration_mode: BOOLEAN
-- Is administration mode?
do
Result := api.is_administration_mode
end
feature -- Access: metadata
keywords: detachable READABLE_STRING_32
publication_date: detachable DATE_TIME
-- Optional publication date.
modification_date: detachable DATE_TIME
-- Optional modification date.
redirection: detachable READABLE_STRING_8
-- Location for eventual redirection.
redirection_delay: NATURAL
-- Optional redirection delay in seconds.
feature -- Access: query
location: IMMUTABLE_STRING_8
-- Associated cms local location.
request_url (opts: detachable CMS_API_OPTIONS): STRING_8
-- Current request location as a url.
do
Result := url (location, opts)
end
feature -- API
api: CMS_API
-- Current CMS API.
setup: CMS_SETUP
-- Current setup
do
Result := api.setup
end
feature -- URL utilities
is_front: BOOLEAN
-- Is current response related to "front" page?
local
l_path_info: READABLE_STRING_8
do
l_path_info := request.percent_encoded_path_info
if attached setup.front_page_path as l_front_page_path then
Result := l_front_page_path.same_string (l_path_info)
else
if base_path.same_string (l_path_info) then
Result := True
else
Result := l_path_info.is_empty or else l_path_info.same_string ("/")
end
end
end
site_url: IMMUTABLE_STRING_8
-- Absolute site url.
-- Always ends with '/'
base_url: detachable IMMUTABLE_STRING_8
-- Base url if any.
--| Usually it is Void, but it could be
--| /project/demo/
base_path: IMMUTABLE_STRING_8
-- Base path, default to "/".
-- Always ends with '/'
-- Could be /project/demo/
feature -- Access: CMS
site_name: STRING_32
do
Result := setup.site_name
end
front_page_url: READABLE_STRING_8
do
Result := absolute_url ("/", Void)
end
feature -- User access
is_authenticated: BOOLEAN
-- Is user authenticated?
do
Result := user /= Void
end
user: detachable CMS_USER
-- Active user if authenticated.
do
Result := api.user
end
set_user (u: CMS_USER)
-- Set active user to `u'.
require
attached_u: u /= Void
do
api.set_user (u)
end
unset_user
-- Unset active user.
do
api.unset_user
end
feature -- Permission
has_permission_on_link (a_link: CMS_LINK): BOOLEAN
-- Does current user has permission to access link `a_link'?
do
Result := True
if
attached {CMS_LOCAL_LINK} a_link as lnk and then
attached lnk.permission_arguments as l_perms
then
Result := has_permissions (l_perms)
end
end
has_permission (a_permission: READABLE_STRING_GENERAL): BOOLEAN
-- Does current user has permission `a_permission' ?
do
Result := user_has_permission (user, a_permission)
end
has_permissions (a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
-- Does current user has any of the permissions `a_permission_list' ?
do
Result := user_has_permissions (user, a_permission_list)
end
user_has_permission (a_user: detachable CMS_USER; a_permission: READABLE_STRING_GENERAL): BOOLEAN
-- Does `a_user' has permission `a_permission' ?
do
Result := api.user_has_permission (a_user, a_permission)
end
user_has_permissions (a_user: detachable CMS_USER; a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
-- Does `a_user' has any of the permissions `a_permission_list' ?
do
Result := api.user_has_permissions (a_user, a_permission_list)
end
feature -- Element change
set_keywords (s: like keywords)
do
keywords := s
end
set_publication_date (dt: like publication_date)
do
publication_date := dt
if dt /= Void and modification_date = Void then
modification_date := dt
end
end
set_modification_date (dt: like modification_date)
do
modification_date := dt
if dt /= Void and publication_date = Void then
publication_date := dt
end
end
set_redirection (a_location: READABLE_STRING_8)
-- Set `redirection' to `a_location'.
do
redirection := a_location
end
set_redirection_delay (nb_secs: NATURAL)
do
redirection_delay := nb_secs
end
feature -- Hooks
hooks: CMS_HOOK_CORE_MANAGER
-- Manager handling hook subscriptions.
obsolete
"Use api.hooks [2017-05-31]"
do
Result := api.hooks
end
feature -- Internationalization (i18n)
translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32
-- Translated text `a_text' according to expected context (lang, ...)
-- and adapt according to options eventually set by `opts'.
do
Result := api.translation (a_text, opts)
end
formatted_string (a_text: READABLE_STRING_GENERAL; args: TUPLE): STRING_32
-- Format `a_text' using arguments `args'.
--| ex: formatted_string ("hello $1, see page $title.", ["bob", "contact"] -> "hello bob, see page contact"
do
Result := api.formatted_string (a_text, args)
end
feature -- Element Change
set_status_code (a_status: INTEGER)
-- Set `status_code' with `a_status'.
note
EIS: "src=eiffel:?class=HTTP_STATUS_CODE"
do
status_code := a_status
ensure
status_code_set: status_code = a_status
end
feature -- Helpers: cms link
webapi_link (a_title: READABLE_STRING_GENERAL; a_relative_location: detachable READABLE_STRING_8): CMS_LOCAL_LINK
require
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
do
Result := api.webapi_link (a_title, a_relative_location)
end
administration_link (a_title: READABLE_STRING_GENERAL; a_relative_location: detachable READABLE_STRING_8): CMS_LOCAL_LINK
require
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
do
Result := api.administration_link (a_title, a_relative_location)
end
local_link (a_title: READABLE_STRING_GENERAL; a_location: READABLE_STRING_8): CMS_LOCAL_LINK
do
Result := api.local_link (a_title, a_location)
end
user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
do
Result := api.user_local_link (u, a_opt_title)
end
feature -- Helpers: html links
user_profile_name, user_display_name (u: CMS_USER): READABLE_STRING_32
do
Result := api.user_display_name (u)
end
feature -- Helpers: URLs
location_absolute_url (a_location: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
-- Absolute URL for `a_location'.
--| Options `opts' could be
--| - absolute: True|False => return absolute url
--| - query: string => append "?query"
--| - fragment: string => append "#fragment"
do
Result := api.location_absolute_url (a_location, opts)
end
location_url (a_location: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
-- URL for `a_location'.
--| Options `opts' could be
--| - absolute: True|False => return absolute url
--| - query: string => append "?query"
--| - fragment: string => append "#fragment"
do
Result := api.location_url (a_location, opts)
end
module_resource_url (a_module: CMS_MODULE; a_path: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING_8
-- Url for resource `a_path` associated with module `a_module`.
require
a_valid_valid: a_path.is_empty or else a_path.starts_with ("/")
do
Result := url ("/module/" + a_module.name + a_path, opts)
end
user_url (u: CMS_USER): like url
require
u_with_id: u.has_id
do
Result := api.user_url (u)
end
feature -- Execution
execute
deferred
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

View File

@@ -7,7 +7,6 @@ class
BAD_REQUEST_ERROR_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare
@@ -37,6 +36,6 @@ feature -- Execution
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
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

View File

@@ -7,7 +7,6 @@ class
FORBIDDEN_ERROR_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare

View File

@@ -7,7 +7,6 @@ class
INTERNAL_SERVER_ERROR_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare
@@ -36,7 +35,7 @@ feature -- Execution
set_main_content ("<em>Internal Server Error</em>")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
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

View File

@@ -7,7 +7,6 @@ class
NOT_FOUND_ERROR_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare
@@ -36,7 +35,7 @@ feature -- Execution
set_main_content ("<em>The requested page %"" + request.request_uri + "%"could not be found.</em>")
end
note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
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

View File

@@ -7,7 +7,6 @@ class
NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare
@@ -38,7 +37,7 @@ feature -- Execution
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
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

View File

@@ -19,7 +19,7 @@ feature -- Execution
do
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
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

View File

@@ -0,0 +1,37 @@
note
description: "Summary description for Hyper media {HM_WEBAPI_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
deferred class
HM_WEBAPI_RESPONSE
inherit
WEBAPI_RESPONSE
feature -- Element change
add_self (a_href: READABLE_STRING_8)
deferred
end
add_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)
deferred
end
feature -- Execution
execute
deferred
end
invariant
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

View File

@@ -7,7 +7,6 @@ class
HOME_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare
@@ -32,5 +31,8 @@ feature -- Execution
set_title (Void)
set_page_title (Void)
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

View File

@@ -0,0 +1,74 @@
note
description: "Summary description for JSON {JSON_WEBAPI_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
class
JSON_WEBAPI_RESPONSE
inherit
HM_WEBAPI_RESPONSE
redefine
initialize
end
create
make
feature {NONE} -- Initialization
initialize
do
Precursor
create resource.make_empty
end
feature -- Access
resource: JSON_OBJECT
feature -- Element change
add_self (a_href: READABLE_STRING_8)
do
add_field ("self", a_href)
end
add_field (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL)
do
resource.put_string (a_value, a_name)
end
add_link (rel: READABLE_STRING_8; a_attname: READABLE_STRING_8 ; a_att_href: READABLE_STRING_8)
local
lnks: JSON_OBJECT
lnk: JSON_OBJECT
do
if attached {JSON_OBJECT} resource.item ("links") as j_links then
lnks := j_links
else
create lnks.make_with_capacity (1)
end
create lnk.make_with_capacity (2)
lnk.put_string (a_attname, "name")
lnk.put_string (a_att_href, "href")
lnks.put (lnk, rel)
end
feature -- Execution
execute
local
m: WSF_PAGE_RESPONSE
do
create m.make_with_body (resource.representation)
m.header.put_content_type ("application/json")
response.send (m)
end
invariant
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

View File

@@ -0,0 +1,70 @@
note
description: "Summary description for Microdata {MD_WEBAPI_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
class
MD_WEBAPI_RESPONSE
inherit
HM_WEBAPI_RESPONSE
redefine
initialize
end
create
make
feature {NONE} -- Initialization
initialize
do
Precursor
create resource.make
end
feature -- Access
resource: MD_DOCUMENT
feature -- Element change
add_self (a_href: READABLE_STRING_8)
do
add_field ("self", a_href)
end
add_field (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL)
local
p: MD_PROPERTY
do
create p.make ("self", a_value, Void)
resource.put (p)
end
add_link (rel: READABLE_STRING_8; a_attname: READABLE_STRING_8 ; a_att_href: READABLE_STRING_8)
local
i: MD_ITEM
do
-- TODO
end
feature -- Execution
execute
local
m: WSF_PAGE_RESPONSE
do
-- TODO
create m.make_with_body ("NOT IMPLEMENTED")
m.set_status_code ({HTTP_STATUS_CODE}.not_implemented)
m.header.put_content_type ("application/xhtml+xml")
response.send (m)
end
invariant
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

View File

@@ -0,0 +1,17 @@
note
description: "[
Generic Web API Response.
]"
date: "$Date$"
revision: "$Revision$"
deferred class
WEBAPI_RESPONSE
inherit
CMS_RESPONSE_I
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