Compare commits

..

224 Commits

Author SHA1 Message Date
Jocelyn Fiat
112be64095 Reverted after EiffelWeb reverted the change that made WSF_URI_HANDLER and WSF_URI_TEMPLATE_HANDLER inheriting from WSF_EXECUTE_HANDLER. 2017-11-07 23:14:11 +01:00
Jocelyn Fiat
aa1443cb8f Fixed conflicts between versions of repeatedly inherited feature. 2017-11-07 15:54:20 +01:00
Jocelyn Fiat
6b2e256fa7 Use absolute URL for href value in webapi json response. 2017-10-27 12:27:05 +02:00
Jocelyn Fiat
f8715d54a8 Improved credential validation.
- added `CMS_USER_API.user_with_credential (...): detachable CMS_USER` that check if credential is valid, and return associated user.
  - replaced use of `is_valid_credential` by new function `user_with_credential` .
  - revisited the session auth, to allow other credential validations (other than ROC CMS auth).
  - added CMS_USER_API.credential_validations to allow authenticating with system other than ROC CMS.
Added new permission to allow by-passing the default ROC-CMS user login/register management:
  - new permission to edit its own account.
  - new permission to edit its own password.
  - new permission to view users details (mostly for user managers).
2017-10-27 12:26:21 +02:00
Jocelyn Fiat
49b9ba3f86 Updated ROC CMS package.iron file. 2017-10-17 13:48:12 +02:00
Jocelyn Fiat
84fe861cdc Updated (s)css files for wikitext module. 2017-10-17 13:47:45 +02:00
Jocelyn Fiat
e8f024ede5 Added debug purpose class to collect info about cms setup. 2017-10-17 13:47:00 +02:00
Jocelyn Fiat
95d2306b1f Made initialization safer,
by reporting errors reported during CMS_API initialization
2017-10-17 13:46:43 +02:00
Jocelyn Fiat
60fbba5a70 Added CMS_WEBAPI_HANDLER.new_permissions_access_denied_error_response (..) to provide the required permissions. 2017-10-17 13:45:32 +02:00
Jocelyn Fiat
be258c73e9 Added system info admin page. 2017-10-17 13:44:58 +02:00
Jocelyn Fiat
68ddd41fb7 added a way to set user password for the admin, or user managers 2017-10-17 13:44:17 +02:00
Jocelyn Fiat
72c35fd0f7 Reuse constant string value instead of using manifest string.
Use proper form id.
2017-10-17 13:43:41 +02:00
Jocelyn Fiat
40855d73d3 Report error during execute_sql_script routine. 2017-10-17 13:43:06 +02:00
Jocelyn Fiat
1c149f9daf Fixed sql for user profile installation.
Escape "key" with backquote to be compatible with MySQL.
2017-10-17 13:42:44 +02:00
Jocelyn Fiat
e445696698 Improved the sqlite3 sql statement converter. 2017-10-17 13:40:32 +02:00
Jocelyn Fiat
375b53c677 Improved a few ecf file for tests.
Cosmetic.
2017-10-17 13:39:59 +02:00
Jocelyn Fiat
ccf108a35e Accept env.json for the app environment file, if the $system_name.json is not found. 2017-10-17 13:38:11 +02:00
Jocelyn Fiat
d00dd46187 roc can be compiled in SCOOP mode. 2017-10-04 18:29:51 +02:00
Jocelyn Fiat
7845240bf4 Inline code uses radius 4px to look nicer. 2017-10-04 18:29:37 +02:00
Jocelyn Fiat
6b4b3f3539 Display verbose output only if --verbose is set.
Report at the end, a quick summary of the installation.
2017-10-04 18:20:48 +02:00
Jocelyn Fiat
92925169b4 no border on inline code 2017-10-03 10:59:56 +02:00
Jocelyn Fiat
3088468332 Allow to login with username or email.
Removed useless and unimplemented feature from CMS_FORM .
SCOOP is default for demo.ecf
Made blog and page module self administrable, i.e administration module is same as module.
This fixes the export hook for page and blog modules.
Improved sql instructions to ease debugging and catch missing sql_finalize... call.
Cleaned sql code.
2017-10-02 15:46:40 +02:00
Jocelyn Fiat
208a35cb73 Removed svn keyword expanded values. 2017-09-21 12:49:38 +02:00
Jocelyn Fiat
bc561b1a48 Fix authenticated role permissions, now it also has all anonymous permissions.
Added permissions on basic auth, to have more control on who can authenticate with basic auth.
Use webapi version of basic auth filter.
For webapi, when authenticated /api/user/ is the same as /api/user/{uid} where uid is the id of current logged in user.
2017-09-21 12:49:17 +02:00
Jocelyn Fiat
9d7d43073d Moved activation implementation into authentication api.
Improved core webapi, added registration link, support redirection.
Use error webapi response, rather than `send_...` routines.
2017-09-19 21:21:30 +02:00
Jocelyn Fiat
e04138c89e Added auth_api: CMS_AUTHENTICATION_API, and for now moved registration instructions inside.
Added authentication module webapi, to provide registration via webapi.
Improved the roles display by providing table of permissions if asked.
Added various links in primary tabs to navigate back to roles or users, depending on the page.
Added datetime to-from string converters in CMS_ENCODERS.
Start removing CMS_ADMINISTRABLE.
Added permission to use simple core access token.
Added webapi for users: list, new, register.
2017-09-12 23:07:45 +02:00
Jocelyn Fiat
b83a050a1d use roc name in install.bat 2017-09-11 22:33:11 +02:00
Jocelyn Fiat
6b4668ec6b Cleaned demo.ecf
Fixed modules admin handler permission checking from "admin.installation_access" to "administration.installation_access".
Use constants for known form id.
Invoke hook form alter for user view response.
Include theme when installing roc cms library.
2017-09-11 22:31:23 +02:00
Jocelyn Fiat
5f7eb82def Use real user display name when possible for messaging module. 2017-09-06 22:02:17 +02:00
Jocelyn Fiat
e9c028b94e Improved node feed and recent changes feed by setting proper feed id and feed item id, and set expected author name. 2017-09-06 16:58:42 +02:00
Jocelyn Fiat
f0180cc682 Cleaned many .ecf files. 2017-09-06 15:52:33 +02:00
Jocelyn Fiat
0c119b6b5a Added better id in feed item.
In node recent changes, return only the published entries.
2017-09-06 12:45:42 +02:00
Jocelyn Fiat
69894e8397 Added missing space in not found error message. 2017-09-06 10:44:30 +02:00
Jocelyn Fiat
50a54ba519 Restored debug.tpl for admin page. 2017-09-06 10:44:10 +02:00
Jocelyn Fiat
2fcbcf1938 Added store_mysql_fake persistence solution, to compile a ROC CMS system with mysql interface, but no real mysql driver.
This is mainly during dev using sqlite, to include the mysql interfaces without depending on related C .lib files that are not always compiled.
2017-09-06 10:26:47 +02:00
Jocelyn Fiat
b6a5b4bc7f Removed unused thread library. 2017-09-05 17:59:55 +02:00
Jocelyn Fiat
b732b20da8 Cleaned all.ecf and store odbc ecf file. 2017-09-05 17:50:19 +02:00
Jocelyn Fiat
c87b70a3ae removed unwanted file. 2017-09-05 17:26:03 +02:00
Jocelyn Fiat
dcf5132773 Added travis CI config. 2017-09-05 16:13:47 +02:00
Jocelyn Fiat
82bf9a4294 Converted ecf files to 1-16-0, to use a single ecf file for all variants (void-safe, non-void-safe, ...). Keep *-safe.ecf as redirection to avoid breaking existing -safe.ecf projects. 2017-09-05 16:08:10 +02:00
Jocelyn Fiat
af3698ba5e Edit the path alias as url-decoded value, to avoid issue with %20 percent-encoded again and again as %25%20... 2017-09-05 15:55:47 +02:00
Jocelyn Fiat
71721ea00b Updated css for feed aggregator in demo example.
cleaning.
2017-09-05 15:55:34 +02:00
Jocelyn Fiat
ac9d29b971 Added basic webapi system to ROC CMS system.
Added sql_delete routine to replace sql_modify with "DELETE FROM .." sql statement.
Fixed filter setup when a module has more than one filter.
Fixed filter setup for site,admin and webapi modes.
Added CMS_AUTH_FILTER, and check if user is already authenticated, then skip following auth filters.
Added specific webapi handler classes for root, user, access token, ...
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.
2017-09-05 15:54:40 +02:00
Jocelyn Fiat
34f0aa5844 Improved feed aggregation module.
Added support to choose either atom or rss for the "/feed" format.
  Added support for feed format view to feed aggregation.
  Use proper content type for RSS and ATOM response.
  For feed aggregation  use `?view=feed` or `?view=feed.atom` or `?view=feed.rss`
  Improved sized feed view.
  Use site name for recent changes feed title.
  Better name for node feeds (include the site name).
  Use current date when a feed aggregation is converted to a new feed, to set the last build date.
  Fixed category filter per feed location for the feed aggregation module.
Fixed authentication module, where a potential case (but not probable) had no response content.
Cosmetic and minor changes on messaging module.
2017-06-12 09:36:29 +02:00
Jocelyn Fiat
78ef7af5f8 Removed obsolete calls, harmonized predefine response, added non admin user pages.
When access is denied, also provide when possible and wanted, the needed
permissions so that in the future, user will be able to ask for
permission easily.
Renamed previous user handlers as admin user handlers.
Added non admin user handler /user/{uid} .
Add new `send_...` response to `CMS_API.response_api`, and use them
instead of `create {...RESPONSE}.... ; execute`.
Fixed potential issue with storage mailer initialization if folder does
not exist.
Added utf_8_encoded helpers function on CMS_API interface.
Fixed a few unicode potential issues.
Removed a few obsolete calls.
2017-06-09 09:29:41 +02:00
Jocelyn Fiat
359344c9dd Fixed link for Oauth sign with.
Added administration pages for OAuth20 module.
2017-06-08 22:16:12 +02:00
Jocelyn Fiat
b814c91e91 Updated obsolete message with expected timestamp.
Removed a few obsolete calls or implicit conversions.
2017-05-12 15:59:31 +02:00
Jocelyn Fiat
1aad62ed52 Added CMS_RESPONSE.request_url (...)
Update a few callers of CMS_RESPONSE.url (...).
Renamed the demo files using "server" instead of "demo".
2017-04-11 13:19:39 +02:00
Jocelyn Fiat
1f6fce1278 Improved theming for admin vs site.
- Added $theme_path, $base_path
- Added CMS_RESPONSE.module_resource_url (...) instead of using hardcoded "/module/" + name + ...
- Use base_path rather than base_url  (note ROC CMS is not yet working with EWF standalone "base" url option)
2017-04-11 11:56:04 +02:00
Jocelyn Fiat
3dc478b4a0 Fixed user registration activation workflow.
- Fixed new user insertion in SQL database.
 - Removed temp user when activated.
 - Renamed local variable names related to temp users.
 - More information when error occurs during user registration.
2017-04-10 21:51:41 +02:00
Jocelyn Fiat
85ac9f7366 Cosmetic. 2017-04-10 18:30:27 +02:00
Jocelyn Fiat
09a902d469 Make user activation procedure safer. 2017-04-10 18:27:19 +02:00
Jocelyn Fiat
d26fc98492 Simplified the ecf for the google search 2.0 module.
Updated the install.bat (dev tool).
2017-04-10 18:20:13 +02:00
Jocelyn Fiat
f67116980d If gcse settings are not set, do not generate the gcse search form. 2017-04-07 11:27:01 +02:00
Jocelyn Fiat
5915af6a9c Added masquerade dev module and disabled it by default.
- it allows to login as a given user by passing security check.
  - it must be used only during development!
  - disabled by default!
Updated the session auth module to make it easier to be reused.
  - masquerade module is based on the session auth module.
2017-04-06 15:33:51 +02:00
Jocelyn Fiat
ad2b30f52b Changed the way search modules get integrated with the theme via a new region "search".
Improved current module for google search 2.0.
2017-04-06 14:02:20 +02:00
Jocelyn Fiat
e062429871 Merge remote-tracking branch 'jvelilla/roc_google_search2.0' into roc_gs2.0 2017-04-05 17:40:04 +02:00
jvelilla
1eae3b7413 Removed secret key from google search version 2.0 since is not needed. 2017-04-03 11:34:02 -03:00
jvelilla
72cfd1d652 Initial import Google Custom Search 2.0
Updated demo to use it.
2017-03-30 22:05:35 -03:00
Jocelyn Fiat
3d2c30ea5f Fixed published node access. 2017-03-30 19:15:12 +02:00
Jocelyn Fiat
12089d7945 Use an advanced maintenance filter that supports #allow-user: and #allow-ip: . 2017-03-30 18:17:58 +02:00
Jocelyn Fiat
9d59f37138 Change a fixme into a comment. 2017-03-30 18:17:39 +02:00
Jocelyn Fiat
5273940b82 Fixed access to non published nodes (and also for the related revisions if any)! 2017-03-30 17:32:15 +02:00
Jocelyn Fiat
e547279016 Implemented save/publish/unpublish control on nodes.
Display on published blogs (except for admin, or author of the related blog).
2017-03-30 17:16:02 +02:00
Jocelyn Fiat
230ef8ed18 Fixed video filter to support STRING_GENERAL . 2017-03-30 16:48:11 +02:00
Jocelyn Fiat
d61fd85ea6 Item("") now returns the value itself (can be used to get all keys of specific object). 2017-03-30 15:43:07 +02:00
Jocelyn Fiat
a01d161864 Improved video content filter to be more flexible, and allow custom template. 2017-03-30 15:41:04 +02:00
Jocelyn Fiat
0d5630bb58 allow copy error during install 2017-03-30 14:47:02 +02:00
Jocelyn Fiat
e3dd6cc8e8 Committed missing change for the cms formats administration. 2017-03-30 14:45:34 +02:00
Jocelyn Fiat
cd48fe182a Always set the content type when it is known for node view. 2017-03-30 14:28:00 +02:00
Jocelyn Fiat
3072b99151 Fixed installation access permission using administration.installation_access instead of previous admin.installation_access. 2017-03-30 11:58:53 +02:00
Jocelyn Fiat
0ce7d11e52 Implemented custom cms format, and associated administration pages.
Applied to existing filter and format.
Added embedded_video filter (initially contribute by Javier Velilla).
2017-03-30 11:58:44 +02:00
Jocelyn Fiat
134f876e62 Display the full url for uploaded files via the CMS_FILES_MODULE.
Keep db/mails in checkout.
2017-03-28 22:26:21 +02:00
307a87eaf4 Better handling of path or location for administration links. 2017-03-24 21:56:48 +01:00
21e75a6492 Splitted administration and normal web site interfaces.
This optimises a bit the routing map, and make cleaner separation.
Make the base url for admin pages customizable via `administration.base_path` variable in cms.ini
   note: could be /admin, /roc-admin, or ..
It is possible to have a specific theme for administration via the variable "administration.admin"
2017-03-24 18:38:58 +01:00
13cbb7d987 Fixed code by checking for file existence before checking if this is a directory. 2017-03-22 10:26:36 +01:00
dbfe14e77e Fixed cms execution initialization (avoid setting up twice router and filter). 2017-03-17 11:21:21 +01:00
b263e4a1b9 Support http caching on sitemap.xml . 2017-03-08 20:55:28 +01:00
a9581eff01 Added support for directory output email notification. 2017-03-08 10:46:29 +01:00
941f50e4fb Removed obsolete calls. 2017-03-08 10:43:27 +01:00
67f6591851 Better control on path alias.
If user has permission to edit, provide a text input, otherwise just a label if path are required.
Reviewed html generated for taxonomy field in node edit form.
Improved the blog entries list by providing (if permitted) link to blog entry creation, and link to the user entries or all entries.
2017-03-06 21:27:35 +01:00
7cde24a439 Protected again sql error.
Return better sql error message for sqlite3 storage.
2017-03-03 18:53:11 +01:00
2fc0c6f7b7 Fixed wrong initial offset. 2017-03-03 13:36:56 +01:00
bb25a8b12e Added feed ordered by publication on /nodes/{type}/feed. 2017-03-03 13:16:04 +01:00
0febe3418b (Breaking change) added notion of editor vs author.
The table nodes and node_revisions have an extra "editor" field.
Update the sql table with:
  ALTER TABLE nodes ADD editor INTEGER ;
  UPDATE nodes SET editor = author;
  ALTER TABLE node_revisions ADD editor INTEGER ;
  UPDATE node_revisions SET editor = author;
2017-03-03 11:16:46 +01:00
6cb6dd1609 Added notion of author (owner) and editor to allow the editing of node by non owner users. 2017-03-03 11:12:51 +01:00
4cbdfeff06 Improved the user selection for messaging module. 2017-03-03 11:08:38 +01:00
f5671bc190 Display associated tags in blogs listing. 2017-03-02 16:02:45 +01:00
a611b27ad9 Fixed node preview. 2017-03-01 16:33:17 +01:00
8ff638d62e Fixed CMS_USER.creation_date retrieval.
Improved the admin users listing.
2017-03-01 15:36:58 +01:00
e89b04cbd2 Support profile_firstname and profile_lastname value when importing user records. 2017-03-01 12:34:08 +01:00
0ab318a43d Updated messaging ecf files. 2017-03-01 11:20:39 +01:00
13d0927c58 Added default path alias for node.
Fixed set path alias, when alias already exists in the history.
2017-02-28 17:35:18 +01:00
a341bd98eb Improved node management.
- List node by node types
- fixed the trash/restore/delete workflow
Added messaging module to send message to cms users (by email for now).
Added early protection for cache, export and import functionalities.
2017-02-28 11:24:48 +01:00
dc84e79952 Wrap with double quote only if term has a comma. 2017-02-10 19:03:34 +01:00
ccf1040513 Added sitemap support on node module.
code cleaning.
2017-02-10 13:34:49 +01:00
1c902db377 added sitemap to demo example. 2017-02-10 12:18:06 +01:00
b47d631095 Html escape cms_search_query variable. 2017-02-10 12:16:09 +01:00
bef99dd762 Added support for sitemap.xml . 2017-02-10 12:08:33 +01:00
ca4d975715 Removed obsolete features:
- CMS_RESPONSE.add_variable (..)
 - CMS_MODULE.register_hooks (..)
And related code.
2017-02-08 23:13:56 +01:00
b0b92c2d36 Added finer control on path_alias.
- added a permission to edit path alias.
 - added an admin handler to manage path aliases.
When path alias is changed on node, always keep previous path alias.
  (can be unset from the related admin section).
CMS_API.storage.path_aliases returns the list of path aliases (recents aliases come first).
2017-02-08 23:01:46 +01:00
d8291e91ac Merge branch 'master' of https://github.com/EiffelWebFramework/ROC 2017-02-08 19:37:59 +01:00
4f4a838504 Allow user to edit its own profile name. 2017-02-08 19:36:23 +01:00
jvelilla
09b5cc752c Rename variable to cms_search_query.
Updated code to use CMS_RESPONSE.set_value, to set the value instead of
CMS_HOOK_VALUE_TABLE_ALTER
2017-02-08 15:00:00 -03:00
a1e8cc5128 Make sure to use the user profile name whenever it is possible. 2017-02-08 18:41:17 +01:00
jvelilla
bb3e2abf55 Updated google search module to keep the search input using an alter value.
Updated feature description.
2017-02-08 10:31:40 -03:00
f75dde457d Added SQL script to update existing ROC CMS installation. 2017-02-07 19:19:40 +01:00
d97542f797 Added CMS_CORE_MODULE which is the mandatory module for ROC CMS.
Added CMS_USER.profile_name .
Improved module managements with install vs enable.
  - enabled/disabled status can also be stored in database.
Install procedure do not install all available modules anymore.
2017-02-07 16:52:08 +01:00
f0a3b2bd3a Collapse expanded keywords ($Date$, $Author$, ...) 2017-02-06 18:45:44 +01:00
784891705f Added possibility to change its own username. 2017-02-06 18:40:20 +01:00
1c829e16ff Fixed testing codes that were not compliant with search user by email signature. 2017-02-01 18:57:15 +01:00
fae444c238 Better syntax formating for SQL query related to comments module.
Display import link from admin page.
Removed unused local variables.
2017-02-01 10:29:15 +01:00
c10faceaf6 Better log message during import.
Fixed SQL storage for comments.
2017-01-27 23:53:27 +01:00
32a47fbba3 When importing, do not change modification date.
Display /nodes sorted by changed date.
Improved the import form, and report wrong import folder. Only import from folder inside site/import for security reason.
2017-01-27 23:12:02 +01:00
2568e85c59 Remove %R from wikitext source, otherwise this may cause parsing issue. 2017-01-27 19:13:30 +01:00
38b4713276 Updated blog design to use ?page=123&size=456.
Use  /blog/{user} url to list blog from a specific user.
Fixed bad xhtml rendering (missing closing tag).
2017-01-27 19:12:37 +01:00
456770ca3e Remove extra argument for the creation procedure of some modules (node and wikitext) as this is useless. 2017-01-27 17:02:28 +01:00
7c398a9f33 Added support for user, user_roles, page, blog export and import.
Added basic support for comments, for now mainly viewing comments from database (no submission forms yet).
Added first simple wikitext filter (render wikitext content as xhtml).
Ensure response content type is text/html with utf-8 charset.
2017-01-27 11:57:52 +01:00
2d698f604b Extracted page support from cms_node_module, and add a proper CMS_PAGE_MODULE.
- now, the CMS_PAGE_MODULE has to be declared in the related CMS_SETUP via CMS_EXECUTION.
   (See demo for example)

Improved the export facilities.
  Implemented blog and page export.
Added import facilities.
  Implemented blog and page import.

Improved node revision web interface (allow to edit a past revision, in order to restore it as latest revisionm i.e current).
Removed specific tag from blog module, and reuse the taxonomy module for that purpose.

Added WIKITEXT module that provide a WIKITEXT_FILTER, so now we can have wikitext content.
   - for now, no support for wiki links such as [[Foobar]].
2017-01-20 16:05:40 +01:00
3bcfb0a44a Added the possibility to have feed aggregation as embedded view using "?view=embedded".
Convenient to include the feed aggregation in a page with for instance jquery load(..) function.
2017-01-02 18:10:40 +01:00
219969cae4 Use .json extension for the exported blog post data. 2017-01-02 18:10:27 +01:00
18d26a765a Made cms uploading file safer. 2016-11-30 21:50:06 +01:00
7d50973fd5 Ensure that cms page always has a non empty html page title. 2016-11-30 21:49:47 +01:00
73572a3e1c updated roc tool ecf file. 2016-11-30 21:49:02 +01:00
84e0ddf50c propagate error for taxonomy handler. 2016-11-30 21:48:49 +01:00
5e98d82934 Added category support for feed aggregation. 2016-11-30 21:48:13 +01:00
31d4c8dc5b Removed nino from launcher.
Updated ecf files.
2016-11-30 21:47:35 +01:00
3bbe6a50b7 New installation procedure for roc demo example. 2016-11-30 17:22:51 +01:00
1fb9640d9c Added feed aggregations ids.
This is used to avoid computing the whole feed aggregation to decide if a feed block is included or not.
2016-11-30 17:09:59 +01:00
41fb8d5730 Added summary and categories to recent change item. 2016-11-30 17:07:46 +01:00
ff58c6aff9 Added support for configuration to Roc.
The installer can now use a roc.cfg file to define the various needed modules.
Format:
{ "name": "demo", "location": ".",
  "modules": {
      "foo": { "location": "path-to-source-of-module-foo"; },
      "bar": { "location": "path-to-source-of-module-bar"; }
  }
}
2016-11-30 16:48:46 +01:00
76cf815477 ROC CMS libraries are SCOOP capable. 2016-11-30 15:42:02 +01:00
410903ff5c Make favicon.ico expires after 24 hours. 2016-11-30 15:41:12 +01:00
19eb5113e9 Added ssl files to allow cms SSL support (disabled by default).
Fixed typo in auth post password message.
Make sure to keep site_destination set in login form, so that the user is redirected to previous location.
Use default http client in the feel aggregator component, instead of forcing libcurl usage.
2016-11-30 10:43:09 +01:00
0c3b85bb37 Set the uploaded file path to site/temp by default. Can be set via configuration with "temp-dir" variable.
(This is important, otherwise it uses the current working directory, but for fcgi, this is not always obvious where it is.)
Allow advanced upload, and also basic html upload, in case the dropzone.js has trouble.
Split get and post handling for files module upload request.
2016-09-26 10:37:41 +02:00
b1478cfb8a Fixed typo "We have sent you .." (instead of ... send ...). 2016-09-16 20:21:24 +02:00
d1ca6eb311 Get GCSE module accepts /gcse or /gcse/ . 2016-06-01 13:48:49 +02:00
88b3ca1d2f Avoid using old path for http_authorization. 2016-05-23 21:24:09 +02:00
6a61c30689 Fixed session logout by setting expiration date in the past and empty content. 2016-05-18 12:13:25 +02:00
88aaf9ed4c Made compilable with version before 16.05 2016-05-18 11:58:16 +02:00
167ac563aa List user roles for each users in the admin list of users. 2016-05-18 11:02:16 +02:00
f4ac4be684 Fixed role changes for an user. 2016-05-18 11:01:54 +02:00
12a3898487 Decode url for redirection purpose during authentication. 2016-04-27 16:07:24 +02:00
0e3419fea0 Do not try to redirect to previous page or destination on logout! 2016-04-13 23:12:11 +02:00
816f0eb820 Improved session auth module routing. 2016-04-13 12:53:10 +02:00
bd3fe63976 Fixed "destination" support when login.
(i.e when visitor click on signin from page A, one he is signed, he will be redirected to the initial page A.)
2016-04-13 10:56:28 +02:00
0c7d8af9d7 Added support for CMS_BLOCK.is_raw in custom block module. 2016-02-19 00:53:47 +01:00
f80268c1ac Updated CMS_HOOK_BLOCK, to provide a better block_identifiers (CMS_RESPONSE): detachable ITERABLE [READABLE_STRING_8] query, to be implemented by CMS_HOOK_RESPONSE_BLOCK descendants.
Added CONFIG_READER.table_keys: detachable LIST [READABLE_STRING_32].
2016-02-19 00:10:09 +01:00
77e2c28d18 Added logs admin viewer.
Added CMS_SETUP.is_debug: BOOLEAN  (see cms.ini   site.debug setting)
2016-02-19 00:03:15 +01:00
af137629e0 Restored previous template_block* function signatures and made them obsolete.
Added smarty_template_block* functions as new recommended functions.
2016-02-18 16:26:00 +01:00
a7f1f14b8a Added missing change to installed file for demo example. 2016-02-18 16:14:58 +01:00
fbda2c9eb2 Reuse improved CMS_HOOK_BLOCK_HELPER to help creation of block templates.
Fixed typo in basic auth login form.
2016-02-18 16:13:58 +01:00
ff58593bff Added functions to get link from menu or link composite.
Improved management menu, but using sub menu.
2016-02-18 12:47:21 +01:00
c65f5765d6 Removed unwanted auth.json file (wrong directory). 2016-02-17 16:11:50 +01:00
19565b9c98 Updated registration form. 2016-02-17 16:07:20 +01:00
6716cb5575 Protected cache, export and feeds menu link. 2016-02-17 15:20:38 +01:00
75332c148d Added protection/permissions. 2016-02-17 12:24:58 +01:00
b54fd85172 Added files module, with for now, a focus on upload files facility.
Contribution from Fabian Murer, as part of an ETH student project.
Supervised, refactorized and merged by Jocelyn Fiat.

Signed-off-by: Fabian Murer <fmurer@student.ethz.ch>
Signed-off-by: Jocelyn Fiat <git@djoce.net>
2016-02-17 12:03:24 +01:00
bc07aad01b Restored iron package name to "roc" 2016-02-12 09:03:56 +01:00
ce4bb551d2 Updated package.iron . 2016-02-04 00:01:32 +01:00
5ceb9d3dd3 Fixed new account admin message.
- the rejection url was badly formatted in the template.
2016-02-03 23:59:55 +01:00
c1a5838320 Fixed auth email messages code and template. 2016-02-03 23:51:20 +01:00
db697cec3e Fixed auth mail template text and code. 2016-02-03 23:33:52 +01:00
892f2331de Do not set destination query parameter to any account/auth url.
Set "site_sign_in_url" and "site_sign_out_url" as variables (so it could be used by template).
2016-02-03 23:16:05 +01:00
3496536751 Added CMS_API.request: WSF_REQUEST to ease dev of ROC CMS code.
- Removed CMS_REQUEST_UTIL
  - centralize a few request related code into CMS_API
Added CMS_API.user, CMS_API.set_user (CMS_USER), ... and user related routines.

Refactored Auth related code
  - added various abstractions to factorize implementation and harmonize solutions.
  - revisited the logout strategy.
  - updated the account info page, and remove info user should not care about.
  - simplified the process, and encourage auth module to follow same design.

Added CMS_LINK helper routines to modify the related query string.
Removed CMS_USER.profile (and related routines)
   - It was not used so far.
   - it will probably a specific module later, if needed.

Update various module to avoid fetching user from sql directly, and let this task to CMS_USER_API.

Removed CMS_NODE_API.node_author (a_node: CMS_NODE): detachable CMS_USER,
   - as the info is already in CMS_NODE.author

Added CMS_RESPONSE.redirection_delay, if ever one code want to redirect after a few seconds.
Added the request uri info to the not found cms response.
2016-01-29 21:58:49 +01:00
41ac45d07b Fixed various CMS_MODULE.install, by not marked module installed if an error occurred!
Improved Auth related module implementation by having a way to change settings like token, max age.
  - use CMS_SETUP.site_id and related "auth.$module.token" ... configuration values.
  - removed related CMS_..._CONSTANTS classes.

For auth session module, use auth_session as table name, and use VARCHAR(64).
Extracted sql from blog module, and store it under site/scripts/install.sql .
Renamed a few $modulename.sql as install.sql
2016-01-27 18:22:20 +01:00
d3b485f4d3 Removed unused local variable. 2016-01-22 22:19:24 +01:00
2b1d5f9693 Updated to new routine type. 2016-01-22 21:41:56 +01:00
59c03c5f4d Added CMS_STRING_EXPANDER.
For now with basic implementation.
  It will be improved later

Added SEO related attribute in CMS_RESPONSE.
Added improved Contact module.
Added basic SEO module.
2016-01-22 21:33:06 +01:00
39ab19d20e Eiffel code and ECFs update to support new agent notations.
Accepts /account and /account/ .
2016-01-19 16:15:13 +01:00
fd5e396b72 Code cleaning. 2016-01-15 18:35:53 +01:00
5bd28326c2 Added source for sql scripts. 2016-01-15 17:59:21 +01:00
eef2a52f48 Integrated new registration workflow.
Added optional "mailer.subject_prefix" configuration item.
Added CMS_SETUP.utf_8_site_name for convenience.
Fixed a few potential unicode issues.
Fixed various typos.
2016-01-15 17:46:56 +01:00
a6642e9f3e Fixed location of library "http_client_extension" in recaptcha library. 2016-01-15 14:11:51 +01:00
affe3beb27 Merge branch 'roc_register' of https://github.com/jvelilla/ROC into roc_register 2016-01-15 13:30:58 +01:00
a013efd6f7 Cosmetic in DEMO_CMS_EXECUTION
Removed persistence/mysql which is not used.
2016-01-15 13:30:07 +01:00
jvelilla
2f95c66295 Removed unneeded template
Updated Sql sentence.
2016-01-14 08:39:35 -03:00
f6885ff581 remove roc.exe 2016-01-13 22:05:49 +01:00
de443a2163 Do not use ODBC by default.
(bad for default, since it depends on odbc drivers to be installed)
2016-01-13 17:30:38 +01:00
a179ee3239 Reverted executable name to "demo" 2016-01-13 10:38:27 +01:00
ed0d9c8d07 Use {CMS_LOG}.level_notice and related constant when using api.log(..) 2016-01-12 16:14:54 +01:00
67fbee737d Keep only sqlite3 persistence as default.
To include mysql and other, uncomment related code in demo-safe.ecf and demo_cms_execution.
2016-01-12 16:14:18 +01:00
jvelilla
f244e86f13 Updated user.sql added tabled auth_temp_users.
Added CMS_TEMP_USER as part of the core.
Moved the code from CMS_TEMP_USER_API and CMS_TEMP_USER_STORAGE_* to
CMS_USER_API and CMS_USER_STORAGE_*.
2016-01-12 09:34:39 -03:00
jvelilla
0cf6e59a76 Updated templates and fixed typos.
Renamed classes
2016-01-08 20:26:34 -03:00
56b9355f3c Updated email messaging of Auth modules to use the CMS_API.process_email (..) system.
as a consequence, removed usage of email_service library.
Updated the meaning for site.email to be sender email addressed.
Added notification.email to set the email address that will received system email notification.
2016-01-08 22:24:52 +01:00
jvelilla
0ca336d467 Updated templates
Replaced hardcoded name "ROC CMS" for placeholder $sitename, and
missing href's with $host.
Renamed database script and database table for temporal users.
Renamed CMS_AUTH_API AS CMS_USER_TEMP_API.
Revert design to use CMS_TEMPORAL_USER and clean CMS_USER.
Refactor rename cms_auth_storage_* classes to CMS_TEMPORAL_USER_STORAGE_*
Added Pending Registrations to the admin menu to show the list of pending registrarions
added CSS to display temporal users
2016-01-06 21:29:21 -03:00
jvelilla
5d8ea2065e Rename script name and table name for
temporary users.
Updated message, after account reactivation.
Updated message, post account application.
Updated Form name, Registration instead of Registration Form.
Updated CMS_USER to have two optional features used for temporary users.
Updated CMS_AUTH_API to user CMS_USER instead of CMS_TEMPORAL_USER
Removed CMS_TEMPORAL_USER
Updateed CMS_AUTHENTICATION_MODULE, with new permission to enable
activate, reject or reactivate a pending user registration.
Updated User Storage and API to create a new user from a temporal user.
2016-01-04 21:14:13 -03:00
jvelilla
682193d116 Updated Register Module.
Worlflow

1- Register
1.1 Create a new temporal user
1.2 Email to the new User
1.3 Email to Web Master
2 Web Master Review th Account Application
2.1 Accept and Send an confirmation email to the user and remove the temporal user
2.2 Reject the application send a rejection email to the user and remove the temporal

Added a new table to save temporal users to review their Application to the site.
Updated Register Form with an new input Application and Recaptcha validation.
Updated Emails templates and messages. (TODO improve messages)
Updated mails templates. Simple messages (Todo improve messages).
Added a new handler to reject a user
Updated existing hanlders to handler the new workflow.
2015-12-30 12:32:00 -03:00
0813abe0bb Fixed ROC CMS library compilation. 2015-12-18 15:29:43 +01:00
1094acb3ec Removed unused local variable 2015-12-16 21:05:57 +01:00
e7c9a54f3f Removed unused local. 2015-12-16 21:03:15 +01:00
bbbdac12c8 Moved taxonomy html generation to CMS_TAXONOMY_API. 2015-12-16 21:03:03 +01:00
jvelilla
22528315cb Removed unneeded file. 2015-12-16 16:01:02 +01:00
jvelilla
090a48eb85 Updated class CMS_TOKEN_GENERATOR.
Remove once in sha1 feature.
Updated encoded_base_64 to base_64
2015-12-16 16:01:01 +01:00
jvelilla
e05c4dca3a Fixed typos
Renamed class CMS_SESSION_CONSTANT to CMS_SESSION_CONSTANTS
Removed unneeded classes and files.
Update SQL implementation.
2015-12-16 16:00:59 +01:00
jvelilla
2255fcc0f6 Added Module Session Authentication with Cookies.
Updated Demo example with the Module Session (Authentication with Cookies)
Fixed little issue with SQL query in OpenID module.
2015-12-16 16:00:58 +01:00
e50fb6959e Moved taxonomy integration for web form inside CMS_TAXONOMY_API.
Moved a few helpers routine from CMS_RESPONSE to CMS_API.
Added CMS_CONTENT.identifier: detachable READABLE_STRING_32 .
2015-12-16 15:59:22 +01:00
jvelilla
3b88c746a1 Removed unneeded file. 2015-12-16 10:43:21 -03:00
jvelilla
fa8ef44a4a Merge branch 'jvelilla-roc_login_session' 2015-12-16 10:11:55 -03:00
jvelilla
068943734f Updated class CMS_TOKEN_GENERATOR.
Remove once in sha1 feature.
Updated encoded_base_64 to base_64
2015-12-16 10:03:35 -03:00
jvelilla
089179e60e Fixed typos
Renamed class CMS_SESSION_CONSTANT to CMS_SESSION_CONSTANTS
Removed unneeded classes and files.
Update SQL implementation.
2015-12-15 15:32:31 -03:00
jvelilla
c25590c9cd Added Module Session Authentication with Cookies.
Updated Demo example with the Module Session (Authentication with Cookies)
Fixed little issue with SQL query in OpenID module.
2015-12-13 18:19:25 -03:00
23d266497b Made the SQL storage more flexible with INTEGER_32, by allowing to retrieve INTEGER_64 and convert to INTEGER_32 if value can be converted to integer 32. 2015-12-10 11:26:28 +01:00
ce8de442e9 Implemented taxonomy administration pages
- create term, vocabulary, add or remove term from vocabularies, ...
Fixed content editing related to taxonomy  (especially with multiple terms vs tags).
Fixed various SQL storage issue related to taxonomy and vocabularies.
Added CMS_RESPONSE.wsf_theme as helper.
2015-12-10 11:21:20 +01:00
e3ae564746 Removed an obsolete call to CMS_RESPONSE.hooks . 2015-12-07 22:08:37 +01:00
b0626d5250 Use + instead of concat(..) in javascript. 2015-12-07 21:36:24 +01:00
276dcc6fcd Added back CMS_MODULE.register_modules (CMS_RESPONSE) as obsolete, to avoid breaking existing modules.
Note: all module SHOULD migrate to new hook setup!
2015-12-07 21:24:48 +01:00
6313007fbf Refactored and update CMS hooks design. (Move from CMS_RESPONSE to CMS_API).
Moved content_types and content_type_webform_managers from CMS_RESPONSE to CMS_API.
Updated the way to output content (node, ...) to html page.
   See CMS_CONTENT_TYPE_WEBFORM_MANAGER.append_cointent_as_html_to (...).
   Added notion of "teaser" (short version of the content), as opposed to full content.
One can use CMS_API.html_encoder ... when possible, same for `formats', ...
Added bridge from CMS_MODULE_API to CMS_API's encoders.
Added new CMS_TAXONOMY_HOOK used to retrieve list of content associated with a specific term.
Moved up to CMS_RESPONSE a few features which was available only in specific descendants.

Added /taxonomy/term/{termid} implementation.
2015-12-07 18:21:40 +01:00
ecbcb6a5cb Added notion of CMS_CONTENT as ancestor of CMS_NODE.
Moved CMS_CONTENT_TYPE to core library.
Added basic and limited taxonomy query /taxonomy/term/{termid} .
2015-12-03 23:01:31 +01:00
a5c117e46e Merge branch 'taxonomy' 2015-12-03 19:26:43 +01:00
20dfce1396 Improved taxonomy by supporting tags, multiple terms allowed, and required kind of vocabulary for specific content type.
Updated node web form, to support taxonomy editing if allowed (specific support for CMS_VOCABULARY.is_tags: BOOLEAN).
Added notion of required or optional module dependencies.
2015-12-03 19:24:58 +01:00
jvelilla
1bfc4a6741 Merge branch 'jvelilla-roc_delete_trash' 2015-12-03 06:51:37 -03:00
jvelilla
3fdbcb2eef Merge branch 'roc_delete_trash' of https://github.com/jvelilla/ROC into jvelilla-roc_delete_trash 2015-12-03 06:50:59 -03:00
jvelilla
a11a93c285 Update code to use CMS_API.unset_path_alias
Updated CMS_NODE_STORAGE_SQL renamed sql_restore_node as sql_update_note_status, updated
related code.
2015-12-02 16:14:54 -03:00
jvelilla
fade19bbee Added precondition to NODE_FORM_RESPONSE.new_delete_form
Added transaction support to CMS_NODE_STORAGE_SQL.delete_node_base
2015-12-02 12:10:03 -03:00
jvelilla
d10612f94b Made test.ecf compilable. 2015-12-02 10:56:18 -03:00
jvelilla
9da8b8a025 Fixed: delete-trash a node.
Added code to remove path_aliase when we delete a node.
2015-12-01 19:20:16 -03:00
f1f3c126dd Use module site files system for the (un)install SQL scripts.
Changed CMS_TERM.id type to INTEGER_64 .
Removed CMS_TERM.parent_id .
Implemented CMS_TERM saving.
2015-11-23 18:05:53 +01:00
1d4ce37ebf Added CMS_STORAGE.as_sql_storage: detachable CMS_STORAGE_SQL_I to ease development based on SQL database. 2015-11-23 18:03:55 +01:00
Jocelyn Fiat
10102e80fa Fixed a few grammar and style errors. 2015-11-23 16:57:49 +01:00
3791ffacdc Added first steps toward Taxonomy module. 2015-11-23 15:27:04 +01:00
b8920ee8b3 Added module administration from /admin/modules/ 2015-11-23 11:08:06 +01:00
2cf2b1da8c Merge branch 'master' of https://github.com/EiffelWebFramework/ROC 2015-11-17 22:19:34 +01:00
17ae27df40 Updated ROC CMS documentation.
Cosmetic, comments, typo.
2015-11-17 22:18:02 +01:00
696 changed files with 42187 additions and 7654 deletions

2
.gitignore vendored
View File

@@ -4,4 +4,6 @@ EIFGENs
*.rc
*.bak
*.sqlite
.*.swo
Thumbs.db
*.dll

19
.travis.yml Normal file
View File

@@ -0,0 +1,19 @@
language: eiffel
before_script:
- export current_dir=$PWD ; echo current_dir=$current_dir ; cd ..
- export ISE_VERSION=17.05; export ISE_BUILD=100416
- curl -sSL http://downloads.sourceforge.net/eiffelstudio/Eiffel_${ISE_VERSION}_gpl_${ISE_BUILD}-linux-x86-64.tar.bz2 | tar -x --bzip2
- export ISE_EIFFEL=$PWD/Eiffel_${ISE_VERSION} ; export ISE_PLATFORM=linux-x86-64
- export PATH=$PATH:$ISE_EIFFEL/studio/spec/$ISE_PLATFORM/bin:$PATH:$ISE_EIFFEL/tools/spec/$ISE_PLATFORM/bin
- echo `ec -version`
- cd $current_dir
- echo Check projects compilation status...
branches:
only:
- master
- v1
script: compile_all -ecb -melt -list_failures -log_verbose -clean -options dotnet=false
group: stable
os: linux

View File

@@ -1 +0,0 @@
{}

View File

@@ -1,37 +1,3 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<target name="cms">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<mapping old_name="CMS_LAYOUT" new_name="CMS_ENVIRONMENT"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
<library name="cms_app_env" location=".\library\app_env\app_env-safe.ecf"/>
<library name="cms_config" location=".\library\configuration\config-safe.ecf"/>
<library name="cms_model" location=".\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="i18n" location="$ISE_LIBRARY\library\i18n\i18n-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="kmp_matcher" location="$ISE_LIBRARY\library\text\regexp\kmp_matcher\kmp_matcher-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<library name="notification_mailer" location="$ISE_LIBRARY\contrib\library\runtime\process\notification_email\notification_email-safe.ecf"/>
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty-safe.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="uri_template" location="$ISE_LIBRARY\contrib\library\text\parser\uri_template\uri_template-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>
<redirection xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" message="Obsolete: use cms.ecf !" location="cms.ecf">
</redirection>

12
cms.ecf
View File

@@ -1,16 +1,12 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<description>ROC CMS library</description>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<target name="cms">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" void_safety="none" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<mapping old_name="CMS_LAYOUT" new_name="CMS_ENVIRONMENT"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
@@ -21,6 +17,7 @@
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization.ecf"/>
<library name="i18n" location="$ISE_LIBRARY\library\i18n\i18n.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="kmp_matcher" location="$ISE_LIBRARY\library\text\regexp\kmp_matcher\kmp_matcher.ecf"/>
@@ -30,6 +27,7 @@
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="uri_template" location="$ISE_LIBRARY\contrib\library\text\parser\uri_template\uri_template.ecf"/>
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>

View File

@@ -0,0 +1,87 @@
note
description: "API to manage CMS User session authentication"
date: "$Date$"
revision: "$Revision$"
class
MASQUERADE_API
inherit
CMS_AUTH_API_I
REFACTORING_HELPER
create {MASQUERADE_AUTH_MODULE}
make_with_session_api
feature {NONE} -- Initialization
make_with_session_api (a_api: CMS_API; a_session_api: CMS_SESSION_API)
do
session_api := a_session_api
make (a_api)
end
feature -- Access
session_api: CMS_SESSION_API
feature -- Status report
has_permission_to_masquerade (a_user: detachable CMS_USER): BOOLEAN
local
v: STRING
do
if attached cms_api.setup.string_8_item_or_default ("dev.masquerade", "permission") as s then
v := s
v.left_adjust
v.right_adjust
if v.is_case_insensitive_equal_general ("none") then
elseif v.is_case_insensitive_equal_general ("all") then
Result := True
elseif v.is_case_insensitive_equal_general ("permission") then
Result := cms_api.user_has_permission (a_user, "masquerade")
else
-- no!
end
end
end
is_authenticating (a_response: CMS_RESPONSE): BOOLEAN
do
if
a_response.is_authenticated and then
attached a_response.request.cookie (session_api.session_token)
then
Result := True
end
end
feature -- Basic operation
process_user_login (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE)
do
session_api.process_user_login (a_user, req, res)
end
process_user_logout (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE)
do
session_api.process_user_logout (a_user, req, res)
end
feature -- Access
-- user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- -- Retrieve user by token `a_token', if any.
-- do
-- Result := session_auth_storage.user_by_session_token (a_token)
-- end
-- has_user_token (a_user: CMS_USER): BOOLEAN
-- -- Has the user `a_user' and associated session token?
-- do
-- Result := session_auth_storage.has_user_token (a_user)
-- end
end

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<redirection xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" uuid="73DA3649-BA18-426C-91CD-5892D52C811C" message="Obsolete: use masquerade_auth.ecf !" location="masquerade_auth.ecf">
</redirection>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="masquerade_auth" uuid="73DA3649-BA18-426C-91CD-5892D52C811C" library_target="masquerade_auth">
<target name="masquerade_auth">
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\..\cms.ecf"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model.ecf" readonly="false"/>
<library name="cms_session_auth_module" location="..\..\modules\session_auth\cms_session_auth.ecf" readonly="false"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,268 @@
note
description: "[
This module allows the use Session Based Authentication using Cookies to restrict access
by looking up users in the given providers.
]"
date: "$Date$"
revision: "$Revision$"
class
MASQUERADE_AUTH_MODULE
inherit
CMS_AUTH_MODULE_I
rename
module_api as masquerade_api
redefine
make,
setup_hooks,
initialize,
install,
permissions,
masquerade_api,
menu_system_alter
end
CMS_HOOK_BLOCK
CMS_HOOK_MENU_SYSTEM_ALTER
create
make
feature {NONE} -- Initialization
make
do
Precursor
version := "1.0"
description := "Service to easily log as user at development time"
package := "debug"
disable -- Disabled by default
add_dependency ({CMS_SESSION_AUTH_MODULE})
end
feature -- Access
name: STRING = "masquerade_auth"
permissions: LIST [READABLE_STRING_8]
-- List of permission ids, used by this module, and declared.
do
Result := Precursor
Result.extend ("masquerade")
end
feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API)
-- <Precursor>
do
Precursor (a_api)
if attached {CMS_SESSION_API} a_api.module_api ({CMS_SESSION_AUTH_MODULE}) as l_session_api then
-- API initialization
create masquerade_api.make_with_session_api (a_api, l_session_api)
end
end
feature {CMS_API} -- Module management
install (api: CMS_API)
do
Precursor {CMS_AUTH_MODULE_I} (api) -- Mark it as installed.
end
feature {CMS_API} -- Access: API
masquerade_api: detachable MASQUERADE_API
-- <Precursor>
feature -- Access: auth strategy
login_title: STRING = "Masquerade"
-- Module specific login title.
login_location: STRING = "account/auth/roc-masquerade-login"
logout_location: STRING = "account/auth/roc-masquerade-logout"
is_authenticating (a_response: CMS_RESPONSE): BOOLEAN
-- <Precursor>
do
if attached masquerade_api as l_masquerade_api then
Result := l_masquerade_api.is_authenticating (a_response)
end
end
feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
if attached masquerade_api as l_masquerade_api then
a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/" + logout_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_masquerade_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login_with_masquerade (a_api, l_masquerade_api,?, ?)), a_router.methods_post)
end
end
feature {NONE} -- Implementation: routes
handle_login (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if
attached masquerade_api as l_masquerade_api and then
l_masquerade_api.has_permission_to_masquerade (api.user)
then
if api.user_is_authenticated then
r.add_warning_message ("You are signed.")
end
r.add_block (login_block ("login", Void, r), "content")
else
r.add_error_message ("You are not allowed to use masquerade authentication!")
end
r.execute
end
handle_logout (api: CMS_API; a_masquerade_api: MASQUERADE_API ; req: WSF_REQUEST; res: WSF_RESPONSE) local
r: CMS_RESPONSE
do
if attached api.user as l_user then
a_masquerade_api.process_user_logout (l_user, req, res)
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
else
-- Not loggued in ... redirect to home
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.set_status_code ({HTTP_CONSTANTS}.found)
end
if
attached {WSF_STRING} req.item ("destination") as p_destination and then
attached p_destination.value as v and then
v.is_valid_as_string_8
then
r.set_redirection (v.to_string_8)
else
r.set_redirection (req.absolute_script_url (""))
end
r.execute
end
handle_login_with_masquerade (api: CMS_API; a_masquerade_api: MASQUERADE_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
do
if a_masquerade_api.has_permission_to_masquerade (api.user) then
if
attached {WSF_STRING} req.form_parameter ("username") as l_username
then
if
attached api.user_api.user_by_name (l_username.value) as l_user
then
a_masquerade_api.process_user_login (l_user, req, res)
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if
attached {WSF_STRING} req.item ("destination") as p_destination and then
attached p_destination.value as v and then
v.is_valid_as_string_8
then
r.set_redirection (v.to_string_8)
else
r.set_redirection ("")
end
else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.add_block (login_block ("login", Void, r), "content")
end
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.add_block (login_block ("login", "Wrong username", r), "content")
end
r.execute
else
api.response_api.send_access_denied (Void, req, res)
end
end
feature -- Hooks configuration
setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration.
do
Precursor (a_hooks)
a_hooks.subscribe_to_block_hook (Current)
a_hooks.subscribe_to_menu_system_alter_hook (Current)
end
feature -- Hooks
block_list: ITERABLE [like {CMS_BLOCK}.name]
do
Result := <<"?login">>
end
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do
if a_block_id.is_case_insensitive_equal_general ("login") then
a_response.add_block (login_block (a_block_id, Void, a_response), "content")
end
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
-- Hook execution on collection of menu contained by `a_menu_system'
-- for related response `a_response'.
local
u: detachable CMS_USER
do
u := a_response.api.user
if
attached masquerade_api as l_masquerade_api and then
l_masquerade_api.has_permission_to_masquerade (u)
then
Precursor (a_menu_system, a_response)
if u /= Void then
a_menu_system.navigation_menu.extend (a_response.local_link ("Masquerade", login_location))
end
end
end
feature {NONE} -- Block views
login_block (a_block_id: READABLE_STRING_8; a_err: detachable READABLE_STRING_8; a_response: CMS_RESPONSE): CMS_CONTENT_BLOCK
do
create Result.make (a_block_id, Void, login_html (a_err, a_response), Void)
end
login_html (a_err: detachable READABLE_STRING_8; a_response: CMS_RESPONSE): STRING
local
params: CMS_DATA_QUERY_PARAMETERS
u: CMS_USER
do
create Result.make_from_string ("<div class=%"login-box%">")
if a_err /= Void then
Result.append ("<div class=%"error%">")
Result.append (a_err)
Result.append ("</div>")
end
Result.append ("<form name=%"masquerade_auth%" action=%"" + a_response.site_url + login_location + "%" method=%"POST%">%N")
Result.append ("<div><input type=%"text%" name=%"username%" id=%"username%" required value=%"%"><label>Username</label></div>")
Result.append ("<button type=%"submit%">Login</button>")
create params.make (0, a_response.api.user_api.users_count.as_natural_32)
across
a_response.api.user_api.recent_users (params) as ic
loop
u := ic.item
Result.append ("<li>")
Result.append (a_response.html_encoded (a_response.api.user_display_name (u)))
Result.append ("</li>%N")
end
Result.append ("</form></div>")
end
end

View File

@@ -1,93 +0,0 @@
CMS Concepts
============
>Current implemented concepts
##### Table of Contents
1. [**Theme**](#theme)
2. [**Regions**](#regions)
- [**Default Page Layout**](#page_layout)
- [**Regions Holds blocks**](#regions_blocks)
3. [**Blocks**](#blocks)
4. [**Modules**](#modules)
5. [**Hooks**](#hooks)
<a name="theme"/>
Theme
-----
In a CMS , a theme is a collection of templates files (HTML, CSS, Images, etc ) that determine how a CMS web site looks. The goal of a theme is to let you change the look and feel of the site.
Eiffel CMS is inspired by Drupal, and use the same default region names as default drupal theme.
#### Important Classes
* [CMS_THEME] (/library/src/theme/cms_theme.e): Abstraction defining the interface of a CMS theme.
* [SMARTY_CMS_THEME] (/library/src/theme/smarty_theme/smarty_cms_theme.e): Theme implemented using the [Eiffel Smarty library] (https://github.com/eiffelhub/template-smarty).
* [CMS_TEMPLATE] (/library/src/theme/cms_template.e): Template Abstraction that contains theme, variables needed by template when rendering page as html. At the moment there is only one implementation SMARTY_CMS_PAGE_TEMPLATE. At the moment there is only one implementation [SMARTY_CMS_PAGE_TEMPLATE] (/library/src/theme/smarty_theme/smarty_cms_page_template.e).
<a name="regions"/>
Regions
-------
The layout of a CMS web page has predefined area called **regions**. The Eiffel CMS uses the same default regions as Drupal, so let's see them in the following image.
<a name="page_layout"/>
![default page layout](http://themery.com/sites/default/files/figure-15-10.png)
```
regions[page_top] = Top
regions[header] = Header
regions[content] = Content
regions[highlighted] = Highlighted
regions[help] = Help
regions[footer] = Footer
regions[first_sidebar] = first sidebar
regions[second_sidebar] = second sidebar
regions[page_bottom] = Bottom
```
<a name="regions_blocks"/>
**A Region holds blocks**
**What goes inside regions?**
Generally, regions hold smaller piece of content called blocks. Blocks hold chunks of content, like the user login form, navigation menu or the information for the footer.
Regions are defined in a configuration file theme.info.
<a name="blocks"/>
CMS_BLOCK
---------
**What is a cms block?**
Blocks are chunk of content that can be created to display whatever you want, and then can be placed in various resgions in your template (theme) layout.
#### Important Classes
* [CMS_BLOCK] (/library/src/kernel/content/cms_block.e): The deferred class CMS_BLOCK provides an abstraction to describe content to be placed inside Regions.
* [CMS_CONTENT_BLOCK] (/library/src/kernel/content/cms_content_block.e): The class CMS_CONTENT_BLOCK describe how to provide generic content.
* [CMS_MENU_BLOCK](/library/src/kernel/content/cms_menu_block.e): The class CMS_MENU_BLOCK describe how to provides a menu of navigational links.
* [CMS_SMARTY_TEMPLATE_BLOCK] (/library/src/kernel/content/cms_smarty_templateblock.e) The class CMS_SMARTY_TEMPLATE_BLOCK describe how to use a CMS block with smarty template file content.
<a name="modules"/>
CMS_MODULES
-----------
**What is a cms module?**
Modules are piece of code that adds one or more features to your web site.
Modules can be plugged and combined to provide a web site customized to your needs. There are modules for many purposes, for example Administratiton, Basic Authentication, etc.
#### Important Classes
* [CMS_MODULE] (/library/src/modules/cms_module.e): The deferred class CMS_MODULE provides an abstraction to describe a generic module that add features to your web site.
* [CMS_RESPONSE](/library/src/service/response/cms_response.e). The deferred class CMS_RESPONSE provide an abstraction to builds the content to get process to render the output.
<a name="hooks">
CMS_HOOK
--------
Hooks is a mechanism which provide a way for modules to interact with each other and extending blocks of the current CMS.
* [CMS_HOOK] (/library/src/hooks/cms_hook.e): The deferred class CMS_HOOK is a marker interface for CMS Hook
* [CMS_HOOK_AUTO_REGISTER] (/library/src/hooks/cms_hook_auto_register.e): The deferred class provides an abstraction that when inheriting from this class, the declared hooks are automatically registered, otherwise, each descendant has to add it to the cms service itself.
* [CMS_HOOK_BLOCK](/library/src/hooks/cms_hook_block.e): The class CMS_HOOK_BLOCK describe a hook providing a way to alter a generic block.
* [CMS_HOOK_FORM_ALTER](/library/src/hooks/cms_hook_form_alter.e): The class CMS_HOOK_FORM_ATLER describe a hook providing a way to alter a form.
* [CMS_HOOK_MENU_ALTER](/library/src/hooks/cms_hook_menu_alter.e): The class CMS_HOOK_MENU_ATLER describe a hook providing a way to alter a menu.
* [CMS_HOOK_MENU_SYSTEM_ALTER](/library/src/hooks/cms_hook_menu_system_alter.e): The class CMS_HOOK_MENU_SYSTEM_ALTER describe a hook providing a way to alter the CMS menu system.
* [CMS_HOOK_VALUE_TABLE_ALTER](/library/src/hooks/cms_hook_value_table_alter.e):: The class CMS_HOOK_VALUE_TABLE_ALTER describe a hook providing a way to alter the value table for a response.

BIN
doc/img_diagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,396 @@
ROC CMS Documentation
=====================
[TOC]
## Overview
**ROC CMS** stands for "REST On CMS", however, until now, no particular focus was done on the REST API approach, and so far a more pragmatic approach dominated.
Part of the design is inspired by Drupal (blocks, hooks, Role-based access control, ...), and other parts related to Eiffel. Priorities, modules and related have been driven by concrete need, in order to fulfill the https://eiffel.org/ websites. Also a contribution (as student projects, or others) helped build various modules or functionality.
Currently, **ROC CMS** is a library or **framework** that provides components, tools and resources to build a CMS (Content Management System). It is not currently a CMS product, one can install and customize without any code.
Thus, it will be interesting for people willing to build a website using **Eiffel**. This will enable to reuse other Eiffel components, better integration with other Eiffel projects, and of course benefit from all the goodies of the Eiffel technologies (Eiffel language, DbC, re-usability, portability, IDE, debugger,...).
It depends on the **Eiffel Web Framework** (known as "Eiffel Web" or "EWF"), and thus can be executed as standalone, or CGI, libFCGI mode on Apache2 for instance, and on any Windows or Linux platform).
The main notions are:
- CMS Execution
- CMS APIs
- CMS Response
- CMS Modules
- CMS Hooks
- CMS Theme, blocks, links, ...
Those points will be described later in appropriated sections.
## Setup
The ROC CMS source is available either with the latest EiffelStudio release under the locations:
- $ISE_LIBRARY\unstable\library\web\cms
- or from github project https://github.com/EiffelWebFramework/ROC branch v0 for now.
```
git clone https://github.com/EiffelWebFramework/ROC -b v0
```
Note that if you use the source code from the github repository, you will need to use the latest release of EiffelStudio as it relieѕ on recent version of various libraries such as EWF, sqlite3, ....
And using the "master" branch, even the trunk version of EiffelStudio libraries. So for now, we encourage you to use the ROC CMS shipped with your EiffelStudio.
Once you have the source code, you should compile project <code>cms/example/demo/demo-safe.ecf</code> target "demo_standalone".
```
# from Command line
cd example
cd demo
ec -config demo-safe.ecf -c_compile -finalize
cp ./EIFGENs/demo_standalone/F_Code/demo.exe demo.exe
demo.exe
# or launch EiffelStudio, and open that project, compile and execute it inside the debugger for instance.
````
This demo includes all the official ROC CMS modules, files, and use libsqlite3 as default storage engine. So you should be able to execute it easily. The **standalone** target is configured to listen on port 9090 by default. (Mostly to avoid conflict on other app that my listen on port 80 or 8080).
In the directory <code>site</code> you will find all the expected files that should be in the root directory.
* config/ : it contains the various configuration files, especially the **cms.ini**.
* modules/ : files associated with each installed ROC CMS module.
* scripts/ : common scripts used mainly to initialize SQL databases.
* themes/ : folder containing the available ROC CMS themes.
* files/ : folder containing files available from the ROC CMS app.
* And also demo.ini that contains the settings for the web launcher, (in our case, the standalone Eiffel server), such as port_number.
Now that you know how to compile, execute, and see the related configuration files, let's describes the main notions of the ROC CMS, first from
* an admin point of view (dev using ROC CMS to build its site),
* and then from a developer point of view (in case you want to contribute to ROC CMS).
## Usage
### Main entries
As a CMS administrator, you will need to setup your CMS application (here the demo example). For this purpose, the main entry points are the CMS_EXECUTION interface, and then the <code>site/</code> files (configuration, themes, templates, ...).
### CMS initialization/Execution
The `CMS_EXECUTION` interface is deferred, and your CMS application needs to inherit from it and define `setup_storage`, `initial_cms_setup` and `setup_modules`. See for instance `DEMO_CMS_EXECUTION`.
So, the descendant of `CMS_EXECUTION` (`DEMO_CMS_EXECUTION` in the example), is creating the `CMS_SETUP`, declares the available **storage** builders (for persistency), and declares the available **modules**.
#### Persistence/Storage
Depending on the **configuration**, the CMS engine will instantiate and use a specific **CMS_STORAGE** (the default is based on `Eiffel sqlite3`, otherwise `EiffelStore+MySQL` and `EiffelStore+ODBC` are available). The storage solution is used to implement the persistence layer, and thus store and load CMS data to disk, or database.
The CMS provides, for now, storage based on
* EiffelStore + MySQL
* EiffelStore + ODBC (could be used for MySQL, sqlite, SQLserver, ...)
* Eiffel sqlite3 : that one is the default storage, since it is convenient for testing, but it is recommended to use EiffelStore+MySQL in production CMS site.
A typical implementation of <code>setup_storage</code> is:
```eiffel
setup_storage (a_setup: CMS_SETUP)
do
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE3_BUILDER}.make, "sqlite3")
-- a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_ODBC_BUILDER}.make, "odbc")
end
```
And the CMS decides which storage should be used. It depends on the application configuration. See the **configuration** section.
Those data could be user information (login, email, password, ...), custom values, logs, emails, path aliases, ... and any data modules may need to store (for instance node content, for the `node` module.)
#### Modules
The `setup_module` is used to declare available **modules** (instances of `CMS_MODULE` effective types).
The modular design provides a simple way to extend or alter the CMS functionalities/behaviors.
Most of the CMS features are implemented by modules, and each module relies on the core of the CMS core.
This **core** contains the `CMS_API`, `CMS_USER_API`, and various internal mechanisms such as mailer, logger, ...
Use `setup_module (a_setup: CMS_SETUP)` to customize the `CMS_SETUP` object created by `initial_cms_setup`.
For your convenience, ROC CMS provides a `CMS_DEFAULT_SETUP` that import configuration from `site/config/cms.ini`
So far, what you need to remember is `CMS_EXECUTION` class and descendants are used to set up the ROC CMS application, for storage, modules, and also how to load configuration.
Note that a module can have 3 states:
- not installed,
- installed and enabled,
- installed and disabled.
At first, to install the modules, open your browser at location `https://hostname:port/admin/install` and click the associated button.
(Note: for new module addition, you also need to install them, using the same link, in the future, there will be a proper module management interface, in the admin front-end.)
To enable or disable a module, you will need to use the `cms.ini` configuration file, please see the **configuration** section.
Existing modules:
- **admin**: basic administration pages, to manage modules, roles, permissions, users, caches, ... (note: it is still very basic, and need effort to improve it.)
- authentication modules based on **auth**:
- **basic_auth**: account signing using basic HTTP Authorization solution
- **oauth20**: sign using a thirdparty OAuth2.0 account (such as Google, Facebook, github, ...)
- **openid**: sign using an OpenID account.
- **node**: the base of node management, include **Page** content type.
- **blog**: extends the **node** module with a **blog** content type.
- **recent_changes**: compute recent changes of CMS (integration with **node** management, and any modules that implement the `CMS_RECENT_CHANGES_HOOK`).
- **feed_aggregator**: aggregate one or many feeds (rss, atom, ...), and provide associated pages or blocks.
- **google_search**: provides search facilities using the Google Custom Search API.
### Configuration
When `CMS_DEFAULT_SETUP` is used, the CMS configuration is loaded from `site/config/cms.ini`.
That file contains a few sections:
- **site**: to set the `name`, `email` and the name of the `theme`. (See "Themes" section pour information.)
- **layout**: the application layout (or environment) can precise the `root-dir`, `themes-dir`, `modules-dir`. If not defined, the values are computed from Current working directory.
- **mailer**: the CMS can send email notification for various reasons, such as new users, or reset password functionalities, ... In this section, you can use
- `smtp` settings to precise an SMTP server (+ port),
- or `sendmail` to use an external script using the sendmail usage,
- or just an `output` file such as @stderr, or a path to a file on disk.
- **modules**: used to enable or disable modules.
- `*=on` -> modules are enabled by default
- `*=off` -> modules are disabled by default
- Note the default value is `on`
- For each module, this can be overwritten with `module_name=on|off`
- **blocks**: settings for blocks (See Themes, Blocks sections for more information on the block). A few parameters are available to customize blocks. The general form is `block-name.param=value` (note that "foo.bar" is a value block name.)
- `block-name.region`: assign the block `block-name` to a specific region. A block can be assigned to **only one region**.
- `block-name.title`: used to overwrite the block title (with <none> , the title is hidden).
- `block-name.weight`: used to order blocks in the same region (blocks with lower weight goes first).
- `block-name.expiration`: used to provide a basic cache system based on expiration. The value is a number of seconds before the cache expires (-1: never expires, 0: never cache, n: cache expires after `n` seconds).
- `block-name.condition`, or `block-name.conditions[]`: include `block-name` only under specific condition(s). The condition can be
- `is_front`: which is True only for the front page, usually at url "/"
- `path:foo/bar`, `path:foo/*/bar`: True only for CMS location matching the patterns after "path:"
- `<none>`: related block is disabled.
- *note: There can be multiple conditions processed as any of the conditions (i.e: "or").*
- `block-name.options[varname]: pass a table of options `varname => value` to the related block. This can be used to pass parameters for block builder (for instance, recent_changes modules accept parameters "size" to know how many changes should be included.)
- To be able to include a block content into multiple region, it is possible to use aliases feature. For instance `&aliases[new_block]=block-name`, in this case, a `new_block` is declared, and it has same content as `block-name`, on this alias, the parameters `region, condition(s), title, weight` are supported, but not `options[]`.
- **admin**: various admin related settings such as
- `installation_access` which accepts 3 values: "all", "none" or "permission", to precise who has access to the modules installation page; either "all" for anyone, "none" to disable installation of new modules, or "permission" to use the CMS permissions solution to determine if the current user can install a new module.
Then, the configuration `cms.ini` can also define other parameters, and sections, that may be used by specific modules.
Note it is also possible to include another ini file with instruction `@include=path-to-file.ini`.
Check the `example/demo/site/cms.ini` for example.
### User management
The CMS core includes the notion of user, via interface `CMS_USER`, which has an id, a name, a password, ... and profile. Without any module, the CMS does not include any mean to authenticate, but still the CMS has the support for user management, and permissions system for current user. To be able to sign into the CMS, the site should include the module `auth`, and one or many of:
- `basic_auth`: authentication using the HTTP Authorization header.
- `oauth20`: being able to sign with an OAuth2.0 account (such as Google, Facebook, ...)
- `OpenID`: being able to sign with an OpenID account.
Whatever authentication solution is used, when a user is signed-in, there is an instance of `CMS_USER` representing the associated CMS user account.
There is a predefined user `admin` who is the administrator of the CMS, and by definition, this **admin** has all the permissions. It is initialized by default with username `admin` and password `istrator#`.
The access control is role-based permissions system. This means, a user can have one or many *roles*, and each *role* includes a list of *permissions*.
There are two built-in roles:
- **anonymous**: when no user is signed in (typically anonymous visitors).
- **authenticated**: when a user is signed in the CMS.
With those 2 built-ins roles, and any custom role the admin will create, it is possible to give specific permissions, to a group of users.
The CMS core defines a few permissions, and each module can also define their own permissions, for instance: "view any page", "create page", "edit page", "delete page", "clear cache", "install modules", ... (when the administrator is signed-in, go to url `/admin/role/1/edit` to see all the available permissions).
### Modules
A module is the way to extend the CMS engine.
First via the inherited `CMS_MODULE` interface that enables a module to:
- have a custom `install` and `uninstall` procedure by redefining the related routines.
- add its **routes** via `setup_router`. (i.e associated url or template of url with a specific request handler).
- register itself to hooks via `register_hooks`.
- declare new permissions by redefining `permissions`.
- provide a specific module api by redefining `module_api`.
- add its **filters** by redefining `filters`.
Using the `hooks` system, a module can be deeply integrated with the CMS engine, and even alter behaviors (for instance, add link, add css, javascript, ...). See related developer documentation on hooks.
It is simple to create your own modules (check the developer documentation).
The ROC CMS library provides a few modules for now, for instance: basic_auth, oauth20, openid, node, blog, feed_aggregator, recent_changes, google_search, ... and others (the list keeps growing...).
**Reminder**: to include a module to your CMS site, you need to
- include the associated .ecf file in your CMS site .ecf file.
- and also declare them in your descendant of CMS_EXECUTION.
- copy the eventual resources, configuration, ... files in the corresponding `site`.
Note: a tool **roc** is under development to ease such operations, for now it only copies needed files from module to site location. In the future, it should also update .ecf files, associated CMS_EXECUTION effective class.
### Themes
When talking about CMS, a major topic is how a request is rendered in a web browser. Here comes the notion of **theme** which is a collection of templates, accepting various values as input (including the content of the blocks), and renders as an html5 page. It also includes various assets such as css, javascript, icons, images, ...
The ROC CMS theming is inspired by Drupal, with the notion of **region** and **block**.
Note: for now, there is no simple "theme" module or similar, and the common way to start your CMS site is to copy an existing project such as the one available with the demo example (i.e: copying the source code, but also the `site` folder).
Currently the default theme of the demo example `SMARTY_CMS_THEME` is based on Eiffel **smarty** template library (Check [smarty doc](https://svn.eiffel.com/eiffelstudio/trunk/Src/contrib/library/text/template/smarty/README.md) for syntax and functionalities).
The layout of a CMS web page has predefined area called **regions**. The Eiffel CMS uses the same default regions as Drupal, so let's see them in the following image.
```
+----------------------------------------------------------+
| Page_top |
+----------------------------------------------------------+
| Header |
+---------------+-------------------------+----------------+
| | Highlighted | |
| Sidebar_first +-------------------------+ Sidebar_second |
| | Help | |
| +-------------------------+ |
| | | |
| | Content | |
| | | |
+---------------+-------------------------+----------------+
| Footer |
+----------------------------------------------------------+
| Page_bottom |
+----------------------------------------------------------+
```
The regions available for a theme, are defined in a configuration file `theme.info` located in the theme directory. For example:
```
name=default_theme
engine=smarty
version=0.1
regions[page_top] = Top
regions[header] = Header
regions[content] = Content
regions[highlighted] = Highlighted
regions[help] = Help
regions[footer] = Footer
regions[sidebar_first] = first sidebar
regions[sidebar_second] = second sidebar
regions[page_bottom] = Bottom
```
Note: the value for each region is the human readable region name.
Note the regions may be disposed with other layout (two sidebars on the left, or right, ... and so on), responsive design or not, and so on. But on the CMS side, a *block* can be inserted into a *region*, and depending if the region is included in the theme, the related block content will be displayed or not.
To sort *block* inside a region, the CMS is using the `weight` property (that can be set via code, and/or overridden via configuration, i.e: `cms.ini`).
This is how a site can support many themes, using the region as content holders, and theme for the layout and style.
Internally the block contents are stored in the values associated with each region.
The theme also has access to specific `values` such as
- `site_url`: the absolute url of the CMS website.
- `host`: the host name.
- `is_https`: True if the connection is using https://
- `user`: contains the username of the signed user, if any.
- `site_title`: site title.
- `page_title`: per page title.
- and also `page: CMS_HTML_PAGE` which represents the CMS page to render with the theme.
- `page` provides values via expression, such as `$page.type`, `$page.is_front`, `$page.is_https`, `$page.title`, ...
- and also a smart expression for region via `$page.region_xyz` for region `xyz` if any, ... (note the region are also available with expression like `$region_xyz` or `$page.region_xyz` ...)
==Note for developers: internally, the deferred class `CMS_RESPONSE` provides an abstraction to render the response for the request using the **theme**, in fact, the theme is controlled by the CMS_RESPONSE implementation (to set value, build expected theme, and finally render as html).==
### Blocks
As previously said, a region holds smaller piece of content called blocks.
Blocks hold chunks of content, like the user login form, navigation menu, information for the footer, or anything provided by each module.
For instance the `feed_aggregator` module provides a block to display the latest elements of a aggregated feed.
Currently there are different kind of `CMS_BLOCK`:
- `CMS_CONTENT_BLOCK`: it holds a simple text to render as it is on the page.
- `CMS_MENU_BLOCK`: it holds a `CMS_MENU` as a collection of `CMS_LINK` generally used to hold a menu, or set of links such as navigation or management menus.
- `CMS_SMARTY_TEMPLATE_BLOCK`: it holds a simple text to render as it is in the page.
Internally, there are two other kinds of block:
- `CMS_ALIAS_BLOCK`: being the alias of another block, but with specific properties.
- `CMS_CACHE_BLOCK`: there is a simple cache solution for blocks, based on expiration. See the configuration section to know how to define the expiration for a block.
For now, creating a block is only possible via block, an evolution of ROC CMS should allow the administrator to add new block without coding.
### Persistence
The persistence or storage layer is used by the CMS to store custom values, path aliases, logs, emails, user information, but it is also used by module (unless a module wants to use its own persistence solution, disk, cloud, ...).
Currently, there are only SQL based implementations of that `CMS_STORAGE`, but nothing prevents to implement it with other solutions (plain text file, NoSQL db, ...).
The current implementation are using either:
- EiffelStore + MySQL: recommended for production, however Eiffel MySQL requires to configure your environment by setting, for instance MYSQL variable on Windows, and MYSQLINC on Linux.
- EiffelStore + ODBC: via ODBC, there is a large range of available database (MySQL, SQLite, SQLserver, ...), but it requires to set up your environment (for instance install sqliteODBC driver to use SQLite database).
- Eiffel sqlite3 wrapper: it is very convenient for development, but maybe not recommended for production websites. It does not require any environment setup, so this is a simple solution to build tests for instance.
In practice, how to use a storage or another?
The project needs to include the expected storage, the following instructions explains how to include sqlite3, EiffelStore+ODBC and EiffelStore+MYSQL storage.
1. First the associated .ecf file need to be included in your project file (.ecf)
For instance
```xml
<library name="persistence_sqlite3" location="$ISE_LIBRARY\unstable\library\web\cms\library\persistence\sqlite3\sqlite3-safe.ecf"/>
<library name="persistence_store_odbc" location="$ISE_LIBRARY\unstable\library\web\cms\library\persistence\store_odbc\store_odbc-safe.ecf"/>
<library name="persistence_store_mysql" location="$ISE_LIBRARY\unstable\library\web\cms\library\persistence\store_mysql\store_mysql-safe.ecf"/>
```
2. Then in the descendant of `CMS_EXECUTION`, in the demo `DEMO_CMS_EXECUTION`, see the code of `setup_storage`:
```eiffel
setup_storage (a_setup: CMS_SETUP)
do
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE3_BUILDER}.make, "sqlite3")
a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_MYSQL_BUILDER}.make, "mysql")
a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_ODBC_BUILDER}.make, "odbc")
end
```
3. And finally, in the configuration file `site/config/demo.json` (in fact, the executable name + ".json"), define the driver and environment of the datasource. For instance the following code defines **sqlite3** as default CMS storage, and environment *sqlite3* that defines the path of SQLite database as "site/database.sqlite3". Note the way to declare sqlite with ODBC, mysql with ODBC, or mysql directly with EiffelStore.
```json
{
"database": {
"datasource": {
"driver": "sqlite3",
"environment": "sqlite3",
},
"environments": {
"sqlite3": {
"connection_string":"Database=./site/database.sqlite3;"
},
"odbc-sqlite": {
"connection_string":"Driver=SQLite3 ODBC Driver;Database=./site/database.sqlite;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
},
"odbc-mysql": {
"connection_string":"Driver=mysql ODBC Driver;Server=localhost;Port=3306;Database=roc;Uid=roc;Pwd=roc;"
},
"mysql": {
"connection_string":"Driver=mysql;Server=localhost;Port=3306;Database=roc;Uid=roc;Pwd=roc;"
}
}
}
}
```
To use EiffelStore+MySQL, just change the "driver" to be "mysql" and "environment" to "mysql". The connection string for server database defines the credentials with "Uid" and "Pwd".
### How to run the CMS site?
As any Eiffel Web application (EWF), it can be executed as
- **standalone**: using Eiffel standalone httpd server included in the "standalone" connector, and then no setup is needed.
- **CGI** or **libFCGI** server: using, for instance, Apache2. Please refer to the Eiffel Web Framework documentation.
### Conclusion
At this point, you know enough to build and administrate a ROC CMS site.
However, for a real site, it is likely that you will need to build your own modules, you will learn how doing that in the Developer Documentation.
***
## Developper Documentation
This diagram shows the main interfaces, they will be described in this documentation, but for now, it introduces those class names.
![Diagram](img_diagram.png)
### CMS APIs
An instance of CMS_API is available either via argument, or via attribute / function of various CMS components.
It provides routine specific to the ROC CMS engine (access to setup, modules, logs, custom values, ...).
### CMS Hooks
Hooks is a mechanism which provides a way for modules to interact with each other and extending blocks of the current CMS.
- [CMS_HOOK](../library/src/hooks/cms_hook.e): deferred class CMS_HOOK is a marker interface for CMS Hook
- [CMS_HOOK_AUTO_REGISTER](../library/src/hooks/cms_hook_auto_register.e): when inheriting from this deferred class, the declared hooks are automatically registered (note only the CMS core hooks are supported, as opposed to hook a module may propose). Otherwise, each descendant has to register itself to the associated hook manager.
- [CMS_HOOK_BLOCK](../library/src/hooks/cms_hook_block.e): it provides a way to declare and build blocks.
- [CMS_HOOK_FORM_ALTER](../library/src/hooks/cms_hook_form_alter.e): it provides a way to alter a web form `CMS_FORM`.
- [CMS_HOOK_MENU_ALTER](../library/src/hooks/cms_hook_menu_alter.e): it provides a way to alter a menu, and thus add or remove a link. This is how a module can add a link into a specific `CMS_MENU`.
- [CMS_HOOK_MENU_SYSTEM_ALTER](../library/src/hooks/cms_hook_menu_system_alter.e): similar to CMS_HOOK_MENU_ALTER, but on built-in menu, such as management, navigation menus, and other.
- [CMS_HOOK_VALUE_TABLE_ALTER](../library/src/hooks/cms_hook_value_table_alter.e): it provides a way to alter the values table for a response (i.e: inserting custom values, or even override existing values).
- [CMS_HOOK_EXPORT](../library/src/hooks/cms_hook_export.e): it provides a simple export solution for each module. Typically used to archive data associated with a module, for instance for backup purpose. In the future, a `CMS_HOOK_IMPORT` should also be available, and it would allow importing data exported by `CMS_HOOK_EXPORT`.
- and for more hooks ... please check descendants of `CMS_HOOK`.
### Custom Module
How to build a new module?
A module is usually developed as an Eiffel library, and provide one or many implementations of `CMS_MODULE`.
It has to set or implement:
- **name**: a unique name identifying the module
- **description**: a human text to describe the purpose of the module, it will mainly be used by the administration front-end.
- **package**: put the current module into a package, mainly for admin front-end.
- **version**: version information
- **dependencies**: defines dependencies on other modules.
- **permissions**: defines permissions used by the modules (mainly for admin front-end)
- **setup_router**: associate routes with request handlers (declare various url or url template and associated request handler).
- **filters**: similar to routers setup, but for WSF Filters (See EWF documentation for more details).
- **register_hooks**: register current module with various hooks if needed.
A module can also redefine `install` and `uninstall`. This could be used during installation to create new database tables, or anything needed by the module, or clean similar resources when being uninstalled.
In addition, a module can also implement `module_api: detachable CMS_MODULE_API` in order to be integrated easily with other modules (see for instance the CMS_NODE_API defined in **node** module).
Please have a look at the [tutorial](tutorial.md) page.
## References
For the interface references, please have a look at the [ROC CMS source code](https://github.com/EiffelWebFramework/ROC).
***
*(last modified: Nov/17/2015 by Jocelyn.)*

4
examples/demo/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
site/db/*
site/files/*
site/export/*
site/import/*

View File

@@ -1,83 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<description>Example/demo for Eiffel ROC CMS library</description>
<target name="common" abstract="true">
<root class="DEMO_CMS_SERVER" feature="make_and_launch"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option debug="true" warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<debug name="dbglog" enabled="true"/>
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false">
<option>
<assertions precondition="true" postcondition="true" supplier_precondition="true"/>
</option>
</library>
<library name="cms_admin_module" location="..\..\modules\admin\admin-safe.ecf" readonly="false"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
<library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/>
<library name="cms_google_search_module" location="..\..\modules\google_search\google_search-safe.ecf" readonly="false" use_application_options="true"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
<library name="cms_openid_module" location="..\..\modules\openid\openid-safe.ecf" readonly="false"/>
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/>
<library name="persistence_sqlite3" location="..\..\library\persistence\sqlite3\sqlite3-safe.ecf" readonly="false">
<option>
<assertions/>
</option>
</library>
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" />
<!--
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" />
-->
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
</target>
<target name="demo_any" extends="common">
<setting name="concurrency" value="thread"/>
<library name="any_launcher" location="..\..\launcher\any-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_standalone" extends="common">
<option debug="true">
<debug name="dbglog" enabled="true"/>
</option>
<setting name="concurrency" value="scoop"/>
<variable name="httpd_ssl_disabled" value="true"/>
<library name="standalone_launcher" location="..\..\launcher\standalone-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_standalone_none" extends="demo_standalone">
<setting name="concurrency" value="none"/>
</target>
<target name="demo_standalone_mt" extends="demo_standalone">
<setting name="concurrency" value="thread"/>
</target>
<target name="demo_standalone_scoop" extends="demo_standalone">
<setting name="concurrency" value="scoop"/>
</target>
<target name="demo_cgi" extends="common">
<setting name="concurrency" value="none"/>
<library name="cgi_launcher" location="..\..\launcher\cgi-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_libfcgi" extends="common">
<setting name="concurrency" value="none"/>
<library name="libfcgi_launcher" location="..\..\launcher\libfcgi-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo" extends="demo_standalone">
</target>
</system>

102
examples/demo/demo.ecf Normal file
View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<description>Example/demo for Eiffel ROC CMS library</description>
<target name="common" abstract="true">
<root class="DEMO_CMS_SERVER" feature="make_and_launch"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option debug="true" warning="true">
<debug name="dbglog" enabled="true"/>
</option>
<setting name="executable_name" value="demo"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\..\cms.ecf" readonly="false">
<option>
<assertions precondition="true" postcondition="true" supplier_precondition="true"/>
</option>
</library>
<library name="cms_admin_module" location="..\..\modules\admin\admin.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth.ecf" readonly="false"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth.ecf" readonly="false"/>
<library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module.ecf" readonly="false"/>
<library name="cms_comments_module" location="..\..\modules\comments\comments.ecf" readonly="false"/>
<library name="cms_contact_module" location="..\..\modules\contact\contact.ecf" readonly="false"/>
<library name="cms_custom_block_module" location="..\..\modules\custom_block\custom_block.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module.ecf" readonly="false"/>
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator.ecf" readonly="false"/>
<library name="cms_files_module" location="..\..\modules\files\files.ecf" readonly="false"/>
<library name="cms_google_search_20_module" location="..\..\modules\google_search_20\google_search_20.ecf" readonly="false" use_application_options="true"/>
<library name="cms_messaging_module" location="..\..\modules\messaging\messaging.ecf" readonly="false"/>
<library name="cms_node_module" location="..\..\modules\node\node.ecf" readonly="false"/>
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20.ecf" readonly="false"/>
<library name="cms_openid_module" location="..\..\modules\openid\openid.ecf" readonly="false"/>
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes.ecf" readonly="false"/>
<library name="cms_seo_module" location="..\..\modules\seo\seo.ecf" readonly="false"/>
<library name="cms_session_auth_module" location="..\..\modules\session_auth\cms_session_auth.ecf" readonly="false"/>
<library name="cms_sitemap_module" location="..\..\modules\sitemap\sitemap.ecf" readonly="false"/>
<library name="cms_taxonomy_module" location="..\..\modules\taxonomy\taxonomy.ecf" readonly="false"/>
<library name="cms_wikitext_module" location="..\..\modules\wikitext\wikitext.ecf" readonly="false"/>
<library name="embedded_video_module" location="..\..\modules\embedded_video\embedded_video.ecf" readonly="false"/>
<library name="masquerade_auth_module" location="..\..\dev_modules\masquerade_auth\masquerade_auth.ecf" readonly="false"/>
<library name="persistence_sqlite3" location="..\..\library\persistence\sqlite3\sqlite3.ecf" readonly="false"/>
<!--
By default, commented, since it depends on specific environment settings.
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc.ecf"/>
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql.ecf" />
-->
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
</target>
<target name="demo_any" extends="common">
<library name="any_launcher" location="..\..\launcher\any.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_standalone" extends="common">
<variable name="httpd_ssl_disabled" value="true"/>
<library name="standalone_launcher" location="..\..\launcher\standalone.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_standalone_none" extends="demo_standalone">
<capability>
<concurrency use="none"/>
</capability>
</target>
<target name="demo_standalone_mt" extends="demo_standalone">
<capability>
<concurrency use="thread"/>
</capability>
</target>
<target name="demo_standalone_scoop" extends="demo_standalone">
<capability>
<concurrency use="scoop"/>
</capability>
</target>
<target name="demo_standalone_scoop_ssl" extends="demo_standalone_scoop">
<capability>
<concurrency use="scoop"/>
</capability>
<variable name="httpd_ssl_enabled" value="true"/>
<variable name="libcurl_http_client_disabled" value="true"/>
<variable name="net_http_client_disabled" value="false"/>
<variable name="netssl_http_client_enabled" value="true"/>
</target>
<target name="demo_cgi" extends="common">
<capability>
<concurrency use="none"/>
</capability>
<library name="cgi_launcher" location="..\..\launcher\cgi.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_libfcgi" extends="common">
<capability>
<concurrency use="none"/>
</capability>
<library name="libfcgi_launcher" location="..\..\launcher\libfcgi.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo" extends="demo_standalone">
</target>
</system>

View File

@@ -1,2 +0,0 @@
port=9090
#verbose=true

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo_no_mysql" uuid="F8399C5A-9495-4418-B4DC-F38C22EE4683" library_target="demo_no_mysql">
<target name="common" abstract="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="none"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="layout" location="..\..\library\layout\layout-safe.ecf" readonly="false"/>
<library name="persistence_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
</target>
<target name="demo_any" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_nino" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_cgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_libfcgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo" extends="demo_nino">
</target>
</system>

View File

@@ -1,14 +1,6 @@
@echo off
setlocal
set ROC_CMD=call %~dp0..\..\tools\roc.bat
set ROC_CMS_DIR=%~dp0
%ROC_CMD% install --module ..\..\modules\admin --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\basic_auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\blog --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\node --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\google_search --dir %ROC_CMS_DIR%
%ROC_CMD% install --config roc.cfg

View File

@@ -1,19 +0,0 @@
note
description: "[
Effective class for APPLICATION_LAUNCHER_I
You can put modification in this class
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
class
APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit
APPLICATION_LAUNCHER_I [G]
feature -- Custom
end

View File

@@ -1,127 +0,0 @@
note
description: "[
Specific application launcher
DO NOT EDIT THIS CLASS
you can customize APPLICATION_LAUNCHER
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
deferred class
APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
inherit
SHARED_EXECUTION_ENVIRONMENT
feature -- Execution
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
nature: like launcher_nature
do
nature := launcher_nature
if nature = Void then
launch_standalone (opts)
elseif nature = nature_standalone then
launch_standalone (opts)
elseif nature = nature_nino then
launch_nino (opts)
elseif nature = nature_cgi then
launch_cgi (opts)
elseif nature = nature_libfcgi then
launch_libfcgi (opts)
else
-- bye bye
(create {EXCEPTIONS}).die (-1)
end
end
feature {NONE} -- Access
launcher_nature: detachable READABLE_STRING_8
-- Initialize the launcher nature
-- either cgi, libfcgi, or nino.
--| We could extend with more connector if needed.
--| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time.
local
p: PATH
ext: detachable READABLE_STRING_32
do
create p.make_from_string (execution_environment.arguments.command_name)
if attached p.entry as l_entry then
ext := l_entry.extension
end
if ext /= Void then
if ext.same_string (nature_standalone) then
Result := nature_standalone
end
if ext.same_string (nature_nino) then
Result := nature_nino
end
if ext.same_string (nature_cgi) then
Result := nature_cgi
end
if ext.same_string (nature_libfcgi) or else ext.same_string ("fcgi") then
Result := nature_libfcgi
end
end
Result := default_nature
end
feature {NONE} -- standalone
nature_standalone: STRING = "standalone"
launch_standalone (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_STANDALONE_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature {NONE} -- nino
nature_nino: STRING = "nino"
launch_nino (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_NINO_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature {NONE} -- cgi
nature_cgi: STRING = "cgi"
launch_cgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_CGI_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature {NONE} -- libfcgi
nature_libfcgi: STRING = "libfcgi"
launch_libfcgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_LIBFCGI_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature -- Default
default_nature: STRING
do
Result := nature_standalone
end
end

View File

@@ -1,19 +0,0 @@
note
description: "[
Effective class for APPLICATION_LAUNCHER_I
You can put modification in this class
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
class
APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit
APPLICATION_LAUNCHER_I [G]
feature -- Custom
end

View File

@@ -1,26 +0,0 @@
note
description: "[
Specific application launcher
DO NOT EDIT THIS CLASS
you can customize APPLICATION_LAUNCHER
]"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
deferred class
APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
feature -- Execution
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_DEFAULT_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
end

View File

@@ -1,24 +1,3 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="cms_demo_module" uuid="4BB59A54-2544-4C10-BFA6-01D12E541A30" library_target="cms_demo_module">
<target name="cms_demo_module">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
<library name="cms" location="..\..\..\..\cms-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>
<redirection xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" uuid="4BB59A54-2544-4C10-BFA6-01D12E541A30" message="Obsolete: use cms_demo_module.ecf !" location="cms_demo_module.ecf">
</redirection>

View File

@@ -1,8 +1,8 @@
note
description: "Summary description for {CMS_DEMO_MODULE}."
author: ""
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
date: "$Date$"
revision: "$Revision$"
class
CMS_DEMO_MODULE
@@ -10,7 +10,7 @@ class
inherit
CMS_MODULE
redefine
register_hooks,
setup_hooks,
initialize,
install
end
@@ -70,8 +70,9 @@ CREATE TABLE tb_demo(
api.logger.put_error ("Could not initialize database for demo module", generating_type)
end
end
Precursor {CMS_MODULE}(api)
end
-- For this demo, be flexible, and do not required sql.
Precursor {CMS_MODULE}(api)
end
feature -- Access: router
@@ -85,10 +86,10 @@ feature -- Access: router
feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_hooks.subscribe_to_block_hook (Current)
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
@@ -151,7 +152,7 @@ feature -- Mapping helper: uri template
feature -- Mapping helper: uri template agent
map_uri_template_agent (a_router: WSF_ROUTER; a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
map_uri_template_agent (a_router: WSF_ROUTER; a_tpl: READABLE_STRING_8; proc: PROCEDURE [WSF_REQUEST, WSF_RESPONSE]; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'.
require
a_tpl_attached: a_tpl /= Void

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="cms_demo_module" uuid="4BB59A54-2544-4C10-BFA6-01D12E541A30" library_target="cms_demo_module">
<target name="cms_demo_module">
<root all_classes="true"/>
<file_rule>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
<library name="cms" location="..\..\..\..\cms.ecf" readonly="false"/>
<library name="cms_model" location="..\..\..\..\library\model\cms_model.ecf" readonly="false"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

36
examples/demo/roc.cfg Normal file
View File

@@ -0,0 +1,36 @@
{
"name": "demo",
"project": "demo-safe.ecf",
"location": ".",
"site_directory": "site",
"themes": {
"admin": { "location": "../../themes/admin", "mode": "link" }
},
"modules": {
"demo": { "location": "modules/demo" },
"core": { "location": "../../modules/core" },
"admin": { "location": "../../modules/admin" },
"auth": { "location": "../../modules/auth" },
"basic_auth": { "location": "../../modules/basic_auth" },
"blog": { "location": "../../modules/blog" },
"contact": { "location": "../../modules/contact" },
"feed_aggregator": { "location": "../../modules/feed_aggregator" },
"google_search": { "location": "../../modules/google_search" },
"google_search_20": { "location": "../../modules/google_search_20" },
"node": { "location": "../../modules/node" },
"oauth20": { "location": "../../modules/oauth20" },
"openid": { "location": "../../modules/openid" },
"recent_changes": { "location": "../../modules/recent_changes" },
"seo": { "location": "../../modules/seo" },
"sitemap": { "location": "../../modules/sitemap" },
"session_auth": { "location": "../../modules/session_auth" },
"taxonomy": { "location": "../../modules/taxonomy" },
"files": { "location": "../../modules/files" },
"custom_block": { "location": "../../modules/custom_block" },
"embedded_video": { "location": "../../modules/embedded_video" },
"wikitext": { "location": "../../modules/wikitext" },
"messaging": { "location": "../../modules/messaging" },
"comments": { "location": "../../modules/comments" },
"masquerade": { "location": "../../dev_modules/masquerade" }
}
}

15
examples/demo/server.crt Normal file
View File

@@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAJnXGtV+PtiYMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNDAzMjIxNTA0WhcNMTYwNDAyMjIxNTA0WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDFMK6ojzg+KlklhTossR13c51izMgGc3B0z9ttfHIcx2kxra3HtHcKIl5wSUvn
G8zmSyFAyQTs5LUv65q46FM9qU8tP+vTeFCfNXvjRcIEpouta3J53K0xuUlxz4d4
4D6qvdDWAez/0AkI4y5etW5zXtg7IQorJhsI9TmfGuruzwIDAQABo1AwTjAdBgNV
HQ4EFgQUbWpk2HoHa0YqpEwr7CGEatBFTMkwHwYDVR0jBBgwFoAUbWpk2HoHa0Yq
pEwr7CGEatBFTMkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAi+h4/
IgEocWkdRZBKHEcTrRxz5WhEDJMoVo9LhnXvCfn1G/4p6Un6sYv7Xzpi9NuSY8uV
cjfJJXhtF3AtyZ70iTAxWaRWjGaZ03PYOjlledJ5rqJEt6CCn8m+JsfznduZvbxQ
zQ6jCLXfyD/tvemB+yYEI3NntvRKx5/zt6Q26Q==
-----END CERTIFICATE-----

9
examples/demo/server.ini Normal file
View File

@@ -0,0 +1,9 @@
port=9090
#port=12345
verbose=true
socket_timeout=60
socket_recv_timeout=45
keep_alive_timeout=25
ssl_enabled=false
ssl_ca_key=server.key
ssl_ca_crt=server.crt

15
examples/demo/server.key Normal file
View File

@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDFMK6ojzg+KlklhTossR13c51izMgGc3B0z9ttfHIcx2kxra3H
tHcKIl5wSUvnG8zmSyFAyQTs5LUv65q46FM9qU8tP+vTeFCfNXvjRcIEpouta3J5
3K0xuUlxz4d44D6qvdDWAez/0AkI4y5etW5zXtg7IQorJhsI9TmfGuruzwIDAQAB
AoGAR5efMg+dieRyLU8rieJcImxVbfOPg9gRsjdtIVkXTR+RL7ow59q7hXBo/Td/
WU8cm1gXoJ/bK+71YYqWyB+BaLRIWvRWb7Gdw203tu4e136Ca5uuY+71qdbVTVcl
NQ7J+T+eAQFP+a+DdT3ZQxu9eze87SMbu6i5YSpIk2kusOECQQDunv/DQ+nc+NgR
DF+Td3sNYUVRT9a1CWi6abAG6reXwp8MS4NobWDf+Ps4JODhEEwlIdq5qL7qqYBZ
Gc1TJJ53AkEA0404Fn6vAzzegBcS4RLlYTK7nMr0m4pMmDMCI6YzAYdMmKHp1e6f
IwxSmQrmwyAgwcT01bc0+A8yipcC2BWQaQJBAJ01QZm635OGmos41KsKF5bsE8gL
SpBBH69Yu/ECqGwie7iU84FUNnO4zIHjwghlPVVlZX3Vz9o4S+fn2N9DC+cCQGyZ
QyCxGdC0r5fbwHJQS/ZQn+UGfvlVzqoXDVMVn3t6ZES6YZrT61eHnOM5qGqklIxE
Old3vDZXPt/MU8Zvk3kCQBOgUx2VxvTrHN37hk9/QIDiM62+RenBm1M3ah8xTosf
1mSeEb6d9Kwb3TgPBmA7YXzJuAQfRIvEPMPxT5SSr6Q=
-----END RSA PRIVATE KEY-----

View File

@@ -2,8 +2,8 @@
#navigation.region=sidebar_first
#navigation.condition=is_front
management.conditions[]=path:admin*
management.conditions[]=is_front
#management.conditions[]=path:admin*
#management.conditions[]=is_front
#Feeds
feed.news.weight=3

View File

@@ -4,14 +4,38 @@ root-dir=site/www
#modules-dir=site/modules
[site]
# General token that could be use for cookies, and related.
id=_EIFFEL_CMS_
#debug=true
# Name of the site, for the title, and eventual message.
name=Eiffel CMS
email=your@email.com
# Properties used for SEO.
property[headline]=Eiffel CMS -- the demo
property[description]=Demo for Eiffel ROC CMS.
property[keywords]=eiffel,cms,demo
# Email used for notification
email=noreply@example.com
# Name of website theme.
theme=bootstrap
[notification]
# By default, notification.email = site.email
# you can change here the email that will receive internal messages.
email=webmaster@example.com
[mailer]
#smtp=localhost:25
#sendmail=/usr/bin/sendmail
output=@stderr
#The mailer is used mostly used by the CMS to send email messages.
# you can change the "From:" by setting mailer.from value"
subject_prefix=[Eiffel CMS]
#from=...
smtp=localhost:25
#sendmail=site\bin\roc_sendmail.bat
output=site\db\mails
[modules]
# Module status
@@ -20,11 +44,28 @@ output=@stderr
# Default is "on"
# for each module, this can be overwritten with
# module_name= on or off
*=all
#*=on
[blocks]
@include=blocks.ini
[admin]
[auth]
# token, default is $site.id or built-in.
#token=_ROC_AUTH_TOKEN_
#session.token=
#session.max_age=86400
#openid.token=
#oauth.token=
[webapi]
mode=on
[administration]
base_path=/roc-admin
theme=admin
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
installation_access=all
[dev]
# masquerade: all, none, permission. Default is none.
masquerade=all

View File

@@ -0,0 +1 @@
This directory can be used to keep emails sent by the CMS.

View File

@@ -1,34 +1,79 @@
ul.cms-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc; }
ul.cms-users li {
border-top: dotted 1px #ccc; }
ul.cms-users li:first-child {
border-top: none; }
ul.cms-users li.cms_user a::before {
content: "[users] "; }
border: solid 1px #ccc;
}
ul.cms-users li {
border-top: dotted 1px #ccc;
display: flex;
flex-direction: row;
align-items: flex-start;
}
ul.cms-users li:first-child {
border-top: none;
}
ul.cms-users li span {
flex-grow: 1;
flex-basis: 20px;
padding-left: 2px;
text-align: left;
}
ul.cms-users li span.identifier a::before {
content: "[user] ";
}
ul.cms-users li span.roles {
color: #090;
font-weight: bold;
}
ul.cms-roles {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc; }
ul.cms-roles li {
border-top: dotted 1px #ccc; }
ul.cms-roles li:first-child {
border-top: none; }
ul.cms-roles li.cms_role a::before {
content: "[roles] "; }
border: solid 1px #ccc;
}
ul.cms-roles li {
border-top: dotted 1px #ccc;
}
ul.cms-roles li:first-child {
border-top: none;
}
ul.cms-roles li.cms_role a::before {
content: "[role] ";
}
table.cms-roles {
border: solid 1px black;
border-collapse: collapse;
}
table.cms-roles th, table.cms-roles td {
padding: 2px;
border: solid 1px black;
}
table.cms-roles td.cms_role_permission {
font-style: italic;
}
ul.cms-permissions {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc; }
ul.cms-permissions li {
border-top: dotted 1px #ccc; }
ul.cms-permissions li:first-child {
border-top: none; }
ul.cms-permissions li.cms_permission a::before {
content: "[permission] "; }
border: solid 1px #ccc;
}
ul.cms-permissions li {
border-top: dotted 1px #ccc;
}
ul.cms-permissions li:first-child {
border-top: none;
}
ul.cms-permissions li.cms_permission a::before {
content: "[permission] ";
}
/*# sourceMappingURL=admin.css.map */
form#modules_collection thead td {
font-weight: bold;
}
form#modules_collection tr {
border-bottom: dotted 1px #ccc;
}
form#modules_collection td {
padding: 3px;
}

View File

@@ -1,5 +1,4 @@
ul.cms-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
@@ -9,10 +8,22 @@ ul.cms-users {
&:first-child {
border-top: none;
}
}
li.cms_user a::before {
content: "[users] ";
display: flex;
flex-direction: row;
align-items: flex-start;
span {
flex-grow: 1;
flex-basis: 20px;
padding-left: 2px;
text-align: left;
&.identifier a::before {
content: "[user] ";
}
&.roles {
color: #090;
font-weight: bold;
}
}
}
}
@@ -31,7 +42,15 @@ ul.cms-roles {
}
li.cms_role a::before {
content: "[roles] ";
content: "[role] ";
}
}
table.cms-roles {
border: solid 1px black;
border-collapse: collapse;
th,td {padding: 2px; border: solid 1px black; }
td.cms_role_permission {
font-style: italic;
}
}
@@ -54,6 +73,16 @@ ul.cms-permissions {
}
}
form#modules_collection {
thead td {
font-weight: bold;
}
tr {
border-bottom: dotted 1px #ccc;
}
td {
padding: 3px;
}
}

View File

@@ -1,8 +0,0 @@
{
"email": "webmaster@example.com",
"subjet_register": "Thank you for regitering with us, activate account",
"subjet_activate": "New account ativation token",
"subjet_password": "Password Recovery!!!",
"subjet_oauth": "Welcome",
"smtp": "127.0.0.1"
}

View File

@@ -0,0 +1,12 @@
{
"subject": "Thank you for contacting us",
"forms": {
"registration": {
"application_description": "Present yourself in a few lines, otherwise your application is likely to be rejected."
}
},
"recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
}
}

View File

@@ -0,0 +1,28 @@
ul.cms-temp-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
}
ul.cms-temp-users li {
border-top: dotted 1px #ccc;
}
ul.cms-temp-users li:first-child {
border-top: none;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li {
border-top: dotted 1px #ccc;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child {
border-top: none;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_information::before {
content: "[personal information] ";
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_email::before {
content: "[email] ";
}

View File

@@ -0,0 +1,37 @@
ul.cms-temp-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_temp_user {
ul.cms_temp_user_details {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_temp_user_detail_information::before{
content: "[personal information] "
}
li.cms_temp_user_detail_email::before{
content: "[email] "
}
}
}
}

View File

@@ -4,15 +4,10 @@
<meta charset="utf-8">
<title>Activation</title>
<meta name="description" content="Activation">
<meta name="author" content="ROC CMS">
<meta name="author" content="$sitename">
</head>
<body>
<p>Thank you for registering at <a href="$host">ROC CMS</a></p>
<p>To complete your registration, please click on this link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
<p>"$user ($email)", thank you for applying to <a href="$host">$sitename</a>.</p>
<p>We will review your application and send you a resolution.<p>
</body>
</html>

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Activation Confirmation</title>
<meta name="description" content="Activation Confirmation">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account "$user ($email)" is confirmed at <a href="$host">$sitename</a>.</p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -4,14 +4,12 @@
<meta charset="utf-8">
<title>New Password</title>
<meta name="description" content="New Password">
<meta name="author" content="ROC CMS">
<meta name="author" content="$sitename">
</head>
<body>
<p>You have required a new password at <a href="$host">ROC CMS</a></p>
<p>To complete your request, please click on this link to genereate a new password:<p>
<p><a href="$link">$link</a></p>
<p>You have requested a new password at <a href="$host">$sitename</a>.</p>
<p>To complete your request, please click on the following link to generate a new password:
<ul><a href="$link">$link</a></ul>
</p>
</body>
</html>

View File

@@ -4,15 +4,14 @@
<meta charset="utf-8">
<title>New Activation</title>
<meta name="description" content="New Activation token">
<meta name="author" content="ROC CMS">
<meta name="author" content="$sitename">
</head>
<body>
<p>You have request a new activation token at <a href="$host">ROC CMS</a></p>
<p>You have requested a new activation token at <a href="$host">$sitename</a>.</p>
<p>To complete your registration, please click on this link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>To complete your registration, please click on the following link to re-activate your account:
<ul><a href="$link">$link</a></ul>
</p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Application Rejected</title>
<meta name="description" content="Application Rejected">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account application is rejected, it was not respecting the requirements from <a href="$host">$sitename</a>.</p>
</body>
</html>

View File

@@ -4,10 +4,16 @@
<meta charset="utf-8">
<title>Welcome</title>
<meta name="description" content="Welcome">
<meta name="author" content="ROC CMS">
<meta name="author" content="$sitename">
</head>
<body>
<p>Welcome to<a href="$host">ROC CMS</a></p>
<p>Welcome to <a href="$host">$sitename</a>.</p>
<p>Your account information:
<ul>
<li>Email address: "$email" .</li>
<li>User name: "$user" .</li>
</ul>
</p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Account Evaluation</title>
<meta name="description" content="Account Evaluation">
<meta name="author" content="$sitename">
</head>
<body>
<h2> Account Evaluation </h2>
<p>The user $user ($email) wants to register to the site <a href="$host">$sitename</a></p>
<blockquote><p>User application:</p>
<p>$application</p>
</blockquote>
<p>To complete the registration, please click on the following link to activate the user account:<p>
<p><a href="$activation_url">$activation_url</a></p>
<p>To reject the registration, please click on the following link <p>
<p><a href="$rejection_url">$rejection_url</a></p>
</body>
</html>

View File

@@ -0,0 +1 @@
{include file="block_account_info.tpl" /}

View File

@@ -1,62 +1,37 @@
<div class="primary-tabs">
{if isset="$user"}
<h3>Account Information</h3>
<div>
<div>
<div>
<label>Username:</label> {$user.name/}
</div>
<div>
<label>Email:</label> {$user.email/}
</div>
<div>
<label>Creation Date:</label> {$user.creation_date/}
</div>
<div>
<label>Last login:</label> {$user.last_login_date/}
</div>
<div>
<form method="get" action="{$site_url/}{$auth_login_strategy/}">
<button type="submit">Logout</button>
</form>
</div>
<ul class="user-information">
<div>
<label>Username:</label> {$user.name/}
</div>
</div>
<hr>
{include file="block_change_password.tpl" /}
<hr>
<h4>Roles</h4>
<div>
{foreach item="ic" from="$roles"}
<div>
<ul>
<li>
<strong>{$ic.name/}</strong>
<ul>
<li> <i>permissions</i>
<ul>
{foreach item="ip" from="$ic.permissions"}
<li>{$ip/}</li>
{/foreach}
</ul>
</li>
</ul>
</li>
</ul>
</div>
{/foreach}
</div>
<div>
<label>Email:</label> {$user.email/}
</div>
<div>
<label>Profile name:</label> {$user.profile_name/}
</div>
<div>
<label>Creation Date:</label> {$user.creation_date/} (UTC)
</div>
<div>
<label>Last login:</label> {$user.last_login_date/} (UTC)
</div>
<div>
<form method="get" action="{$site_url/}account/roc-logout">
<button type="submit">Logout</button>
</form>
</div>
</ul>
<hr>
<h4>Profile</h4>
<div>
<ul class="user-profile">
{foreach item="the_value" key="the_name" from="$user.profile"}
<div>
<label>{$the_name/}:</label> {$the_value/}
</div>
<li>
<label>{$the_name/}:</label><div>{$the_value/}</div>
</li>
{/foreach}
</div>
</ul>
{/if}
{unless isset="$user"}
<div>

View File

@@ -1,7 +1,7 @@
<div>
<form action="{$site_url/}account/change-password" method="post">
<fieldset>
<legend>Change Password Form</legend>
<legend>Change Password</legend>
<div>
<input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label>

View File

@@ -1,29 +0,0 @@
<div class="primary-tabs">
{unless isset="$user"}
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
<div>
<div>
<form action method="POST">
<div>
<input type="text" name="username" required>
<label>Username</label>
</div>
<div>
<input type="password" name="password" required>
<label>Password</label>
</div>
<button type="button" onclick="ROC_AUTH.login();">Login</button>
</form>
</div>
</div>
<div>
<div>
<p>
<a href="{$site_url/}account/new-password">Forgot password?</a>
</p>
</div>
</div>
{/unless}
</div>

View File

@@ -1,3 +1,3 @@
<div>
<p>We have send you a new token code, check your email to generate a new password</p>
<p>We have sent you a new token code, check your email to generate a new password</p>
</div>

View File

@@ -1,3 +1,3 @@
<div>
<p>We have send you a new activation code, check your email to activate your account.</p>
<p>Thanks for your application, we will review it to activate your account.</p>
</div>

View File

@@ -1,3 +1,3 @@
<div>
<p>Thanks for register, check your email to activate your account.</p>
<p>Thanks for your application, we will review it to activate your account.</p>
</div>

View File

@@ -1,28 +1,38 @@
<div>
<form action="{$site_url/}account/roc-register" method="post">
<fieldset>
<legend>Register Form</legend>
<div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label>
{if isset="$error_name"}
<span><i>{$error_name/}</i></span> <br>
{/if}
</div>
<div>
<input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label>
</div>
<div>
<input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label>
{if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br>
{/if}
</div>
<button type="submit">Register</button>
</fieldset>
</form>
<div>
<form action="{$site_url/}account/roc-register" method="post">
<fieldset>
<legend>Registration</legend>
<div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label>
{if isset="$error_name"}
<span><i>{$error_name/}</i></span> <br>
{/if}
</div>
<div>
<input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label>
</div>
<div>
<input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label>
{if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br/>
{/if}
</div>
<div>
<textarea rows="4" cols="50" name="personal_information" id="personal_information" required>{$personal_information/}</textarea>
<label for="personal_information">Tell us why you want to register an account</label>
{if isset="$error_application"}
<span><i>{$error_application/}</i></span><br/>
{/if}
{if isset="$application_description"}
<br/>
<p class="description">{$application_description/}</p>
{/if}
</div>
{unless isempty="$recaptcha_site_key"}<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div><br/>{/unless}
<button type="submit">Register</button>
</fieldset>
</form>
</div>

View File

@@ -1,307 +1,291 @@
var ROC_AUTH = ROC_AUTH || { };
var loginURL = "/basic_auth_login";
var logoutURL = "/basic_auth_logoff";
var loginURL = "/roc-basic-login";
var logoutURL = "/roc-basic-logoff";
var userAgent = navigator.userAgent.toLowerCase();
var firstLogIn = true;
ROC_AUTH.login = function() {
var form = document.forms['cms_basic_auth'];
var username = form.username.value;
var password = form.password.value;
//var host = form.host.value;
var origin = window.location.origin.concat(window.location.pathname);
var _login = function(){
var form = document.forms['cms_basic_auth'];
var username = form.username.value;
var password = form.password.value;
//var host = form.host.value;
var origin = window.location.origin + window.location.pathname;
var _login = function(){
if (document.getElementById('myModalFormId') !== null ) {
ROC_AUTH.remove ('myModalFormId');
}
if (document.getElementById('myModalFormId') !== null ) {
ROC_AUTH.remove ('myModalFormId');
}
if (username === "" || password === "") {
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".login-box").append(newdiv);
}
}else{
//Instantiate HTTP Request
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", loginURL, true, username, password);
request.send(null);
//Process Response
request.onreadystatechange = function(){
if (request.readyState == 4) {
if (request.status==200) {
delete form;
window.location=window.location.origin;
} else {
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
// .. ?
}
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".login-box").append(newdiv);
}
}
}
}
}
}
if (username === "" || password === "") {
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".primary-tabs").append(newdiv);
}
}else{
//Instantiate HTTP Request
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", loginURL, true, username, password);
request.send(null);
//Process Response
request.onreadystatechange = function(){
if (request.readyState == 4) {
if (request.status==200) {
delete form;
window.location=window.location.origin;
}
else{
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
}
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".primary-tabs").append(newdiv);
}
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("firefox") != -1) { //TODO: check version number
if (firstLogIn) {
_login();
} else {
ROC_AUTH.logoff(_login);
}
} else {
_login();
}
}
}
}
}
}
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
if (firstLogIn) _login();
else logoff(_login);
}
else{
_login();
}
if (firstLogIn) firstLogIn = false;
if (firstLogIn) {
firstLogIn = false;
}
};
ROC_AUTH.login_with_redirect = function() {
var form = document.forms[2];
var username = form.username.value;
var password = form.password.value;
var host = form.host.value;
var _login = function(){
var form = document.forms[2];
var username = form.username.value;
var password = form.password.value;
var host = form.host.value;
var _login = function(){
var redirectURL = form.redirect && form.redirect.value || "";
$("#imgProgressRedirect").show();
var redirectURL = form.redirect && form.redirect.value || "";
if (document.getElementById('myModalFormId') !== null ) {
ROC_AUTH.remove ('myModalFormId');
}
if (username === "" || password === "") {
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".login-box").append(newdiv);
$("#imgProgressRedirect").hide();
}
} else {
//Instantiate HTTP Request
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", host + loginURL, true, username, password);
request.send(null);
//Process Response
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status==200) {
if (redirectURL === "") {
window.location=host + "/";
} else {
window.location=host + redirectURL;
}
} else{
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
}
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".login-box").append(newdiv);
$("#imgProgressRedirect").hide();
}
}
}
}
}
}
$("#imgProgressRedirect").show();
if (document.getElementById('myModalFormId') !== null ) {
ROC_AUTH.remove ('myModalFormId');
}
if (username === "" || password === "") {
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".primary-tabs").append(newdiv);
$("#imgProgressRedirect").hide();
}
}else{
//Instantiate HTTP Request
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", host.concat(loginURL), true, username, password);
request.send(null);
//Process Response
request.onreadystatechange = function(){
if (request.readyState == 4) {
if (request.status==200) {
if (redirectURL === "") {
window.location=host.concat("/");
} else {
window.location=host.concat(redirectURL);
}
}
else{
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
}
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$(".primary-tabs").append(newdiv);
$("#imgProgressRedirect").hide();
}
}
}
}
}
}
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
if (firstLogIn) _login();
else logoff(_login);
}
else{
_login();
}
if (firstLogIn) firstLogIn = false;
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
if (firstLogIn) {
_login();
} else {
ROC_AUTH.logoff(_login);
}
} else{
_login();
}
if (firstLogIn) {
firstLogIn = false;
}
};
ROC_AUTH.getQueryParameterByName = function (name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? " " : decodeURIComponent(results[1].replace(/\+/g, " "));
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), results = regex.exec(location.search);
return results === null ? " " : decodeURIComponent(results[1].replace(/\+/g, " "));
}
ROC_AUTH.logoff = function(callback){
var form = document.forms[0];
var host = form.host.value;
if (userAgent.indexOf("msie") != -1) {
document.execCommand("ClearAuthenticationCache");
}
else if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
var request1 = new XMLHttpRequest();
var request2 = new XMLHttpRequest();
//Logout. Tell the server not to return the "WWW-Authenticate" header
request1.open("GET", host.concat(logoutURL) + "?prompt=false", true);
request1.send("");
request1.onreadystatechange = function(){
if (request1.readyState == 4) {
//Sign in with dummy credentials to clear the auth cache
request2.open("GET", host.concat(logoutURL), true, "logout", "logout");
request2.send("");
request2.onreadystatechange = function(){
if (request2.readyState == 4) {
if (callback!=null) { callback.call(); } else { window.location=host.concat(logoutURL);}
}
}
}
}
}
else {
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", host.concat(logoutURL), true, "logout", "logout");
request.send("");
request.onreadystatechange = function(){
if (request.status==401 || request.status==403 ) { window.location=host.concat(logoutURL);
}
}
}
var form = document.forms[0];
var host = form.host.value;
if (userAgent.indexOf("msie") != -1) {
document.execCommand("ClearAuthenticationCache");
} else if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
var request1 = new XMLHttpRequest();
var request2 = new XMLHttpRequest();
//Logout. Tell the server not to return the "WWW-Authenticate" header
request1.open("GET", host + logoutURL + "?prompt=false", true);
request1.send("");
request1.onreadystatechange = function(){
if (request1.readyState == 4) {
//Sign in with dummy credentials to clear the auth cache
request2.open("GET", host + logoutURL, true, "logout", "logout");
request2.send("");
request2.onreadystatechange = function(){
if (request2.readyState == 4) {
if (callback!=null) {
callback.call();
} else {
window.location=host + logoutURL;
}
}
}
}
}
} else {
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", host + logoutURL, true, "logout", "logout");
request.send("");
request.onreadystatechange = function(){
if (request.status==401 || request.status==403 ) {
window.location=host + logoutURL;
}
}
}
};
ROC_AUTH.remove = function (id)
{
var element = document.getElementById(id);
element.outerHTML = "";
delete element;
return;
ROC_AUTH.remove = function (id) {
var element = document.getElementById(id);
element.outerHTML = "";
delete element;
return;
};
$(document).ready(function() {
if (typeof String.prototype.contains != 'function') {
String.prototype.contains = function (str){
return this.indexOf(str) != -1;
};
}
ROC_AUTH.progressive_loging();
if (typeof String.prototype.contains != 'function') {
String.prototype.contains = function (str){
return this.indexOf(str) != -1;
};
}
ROC_AUTH.progressive_loging();
});
ROC_AUTH.progressive_loging = function () {
ROC_AUTH.login_href();
ROC_AUTH.login_href();
};
$(document).keypress(function(e) {
if ((e.which === 13) && (e.target.localName === 'input' && e.target.id === 'password')) {
ROC_AUTH.login();
}
if ((e.which === 13) && (e.target.localName === 'input' && e.target.id === 'password')) {
ROC_AUTH.login();
}
});
ROC_AUTH.OnOneClick = function(event) {
event.preventDefault();
if ( document.forms[0] === undefined ) {
ROC_AUTH.create_form();
}
return false;
event.preventDefault();
if ( document.forms[0] === undefined ) {
ROC_AUTH.create_form();
}
return false;
};
ROC_AUTH.login_href = function() {
var els = document.getElementsByTagName("a");
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
if (el.href.contains("/basic_auth_login?destination")) {
loginURL = el.href;
var OneClick = el;
OneClick.addEventListener('click', ROC_AUTH.OnOneClick, false);
}
}
var els = document.getElementsByTagName("a");
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
if (el.href.contains(loginURL + "?destination")) {
// loginURL = el.href;
var OneClick = el;
OneClick.addEventListener('click', ROC_AUTH.OnOneClick, false);
}
}
};
ROC_AUTH.create_form = function() {
// Fetching HTML Elements in Variables by ID.
var createform = document.createElement('form'); // Create New Element Form
createform.setAttribute("action", ""); // Setting Action Attribute on Form
createform.setAttribute("method", "post"); // Setting Method Attribute on Form
$("body").append(createform);
// Fetching HTML Elements in Variables by ID.
var createform = document.createElement('form'); // Create New Element Form
createform.setAttribute("action", ""); // Setting Action Attribute on Form
createform.setAttribute("method", "post"); // Setting Method Attribute on Form
$("body").append(createform);
var heading = document.createElement('h2'); // Heading of Form
heading.innerHTML = "Login Form ";
createform.appendChild(heading);
var heading = document.createElement('h2'); // Heading of Form
heading.innerHTML = "Login Form ";
createform.appendChild(heading);
var line = document.createElement('hr'); // Giving Horizontal Row After Heading
createform.appendChild(line);
var line = document.createElement('hr'); // Giving Horizontal Row After Heading
createform.appendChild(line);
var linebreak = document.createElement('br');
createform.appendChild(linebreak);
var linebreak = document.createElement('br');
createform.appendChild(linebreak);
var namelabel = document.createElement('label'); // Create Label for Name Field
namelabel.innerHTML = "Username : "; // Set Field Labels
createform.appendChild(namelabel);
var namelabel = document.createElement('label'); // Create Label for Name Field
namelabel.innerHTML = "Username : "; // Set Field Labels
createform.appendChild(namelabel);
var inputelement = document.createElement('input'); // Create Input Field for UserName
inputelement.setAttribute("type", "text");
inputelement.setAttribute("name", "username");
inputelement.setAttribute("required","required");
createform.appendChild(inputelement);
var inputelement = document.createElement('input'); // Create Input Field for UserName
inputelement.setAttribute("type", "text");
inputelement.setAttribute("name", "username");
inputelement.setAttribute("required","required");
createform.appendChild(inputelement);
var linebreak = document.createElement('br');
createform.appendChild(linebreak);
var linebreak = document.createElement('br');
createform.appendChild(linebreak);
var passwordlabel = document.createElement('label'); // Create Label for Password Field
passwordlabel.innerHTML = "Password : ";
createform.appendChild(passwordlabel);
var passwordlabel = document.createElement('label'); // Create Label for Password Field
passwordlabel.innerHTML = "Password : ";
createform.appendChild(passwordlabel);
var passwordelement = document.createElement('input'); // Create Input Field for Password.
passwordelement.setAttribute("type", "password");
passwordelement.setAttribute("name", "password");
passwordelement.setAttribute("id", "password");
passwordelement.setAttribute("required","required");
createform.appendChild(passwordelement);
var passwordelement = document.createElement('input'); // Create Input Field for Password.
passwordelement.setAttribute("type", "password");
passwordelement.setAttribute("name", "password");
passwordelement.setAttribute("id", "password");
passwordelement.setAttribute("required","required");
createform.appendChild(passwordelement);
var passwordbreak = document.createElement('br');
createform.appendChild(passwordbreak);
var passwordbreak = document.createElement('br');
createform.appendChild(passwordbreak);
var submitelement = document.createElement('button'); // Append Submit Button
submitelement.setAttribute("type", "button");
submitelement.setAttribute("onclick", "ROC_AUTH.login();");
submitelement.innerHTML = "Sign In ";
createform.appendChild(submitelement);
var submitelement = document.createElement('button'); // Append Submit Button
submitelement.setAttribute("type", "button");
submitelement.setAttribute("onclick", "ROC_AUTH.login();");
submitelement.innerHTML = "Sign In ";
createform.appendChild(submitelement);
};
@@ -310,16 +294,16 @@ var password = document.getElementById("password");
var confirm_password = document.getElementById("confirm_password");
ROC_AUTH.validatePassword =function(){
if ((password != null) && (confirm_password != null)) {
if(password.value != confirm_password.value) {
confirm_password.setCustomValidity("Passwords Don't Match");
} else {
confirm_password.setCustomValidity('');
}
}
if ((password != null) && (confirm_password != null)) {
if(password.value != confirm_password.value) {
confirm_password.setCustomValidity("Passwords Don't Match");
} else {
confirm_password.setCustomValidity('');
}
}
}
if ((password != null) && (confirm_password != null)) {
password.onchange = ROC_AUTH.validatePassword();
confirm_password.onkeyup = ROC_AUTH.validatePassword;
}
password.onchange = ROC_AUTH.validatePassword();
confirm_password.onkeyup = ROC_AUTH.validatePassword;
}

View File

@@ -1,29 +1,24 @@
<div class="primary-tabs">
{unless isset="$user"}
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
{unless isset="$user"}
<div class="login-box">
<div class="description">The "Basic Auth" relies on the HTTP basic access authentication.<br/>(see also: <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">https://en.wikipedia.org/wiki/Basic_access_authentication</a> )</div>
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
<div>
<div>
<form name="cms_basic_auth" action method="POST">
<div>
<input type="text" name="username" id="username" required>
<label>Username</label>
</div>
<div>
<input type="password" name="password" id="password" required>
<label>Password</label>
</div>
<button type="button" onclick="ROC_AUTH.login();">Login</button>
</form>
</div>
<form name="cms_basic_auth" action="{$site_url/}roc-basic-login" method="POST">
{unless isempty="$site_destination"}<input type="hidden" name="destination" value="{$site_destination/}">{/unless}
<input type="hidden" name="host" id="host" value="{$site_url/}">
<div>
<input type="text" name="username" id="username" required>
<label>Username</label>
</div>
<div>
<input type="password" name="password" id="password" required>
<label>Password</label>
</div>
<button type="button" onclick="ROC_AUTH.login();">Login</button>
</form>
</div>
<div>
<div>
<p>
<a href="{$site_url/}account/new-password">Forgot password?</a>
</p>
</div>
<a href="{$site_url/}account/new-password">Forgot password?</a>
</div>
{/unless}
</div>
{/unless}

View File

@@ -0,0 +1,18 @@
div.comments-box div.title {
font-size: x-large;
}
div.comments-box ul.comments {
border-top: solid 1px #eee;
padding: 0 0 0 20px;
border-left: solid 5px #eee;
list-style-type: none;
}
div.comments-box ul.comments li.comment {
border-bottom: solid 1px #eee;
}
div.comments-box ul.comments li.comment > span.author {
font-weight: bold;
}
div.comments-box ul.comments li.comment > span.info {
font-style: italic;
}

View File

@@ -0,0 +1,17 @@
div.comments-box {
div.title {
font-size: x-large;
}
ul.comments {
border-top: solid 1px #eee;
padding: 0 0 0 20px;
border-left: solid 5px #eee;
list-style-type: none;
li.comment {
border-bottom: solid 1px #eee;
&>span.author { font-weight: bold; }
&>span.info { font-style: italic; }
}
}
}

View File

@@ -0,0 +1,13 @@
CREATE TABLE comments(
`cid` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
`content` TEXT,
`format` VARCHAR(128),
`author` INTEGER,
`author_name` VARCHAR(255),
`created` DATETIME NOT NULL,
`changed` DATETIME NOT NULL,
`status` INTEGER,
`parent` INTEGER,
`entity` VARCHAR(255), /* Associated entity */
`entity_type` VARCHAR(255) /* Type of associated entity */
);

View File

@@ -0,0 +1,8 @@
{
"--email": "webmaster@example.com",
"subjet": "Thank you for contacting us",
"recaptcha": {
"site_key":"",
"secret_key":""
}
}

View File

@@ -0,0 +1,124 @@
.contact-box {
background-color: #F2F7F9;
width: 465px;
padding: 20px;
border: 6px solid #8FB5C1;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
position: relative;
/* Remove box shadow firefox, chrome and opera put around required fields.
* It looks rubbish.
*/
/* Normalize placeholder styles */
/* chrome, safari */
/* mozilla */
/* ie (faux placeholder) */
}
.contact-box h1 {
font-size: 42px;
}
.contact-box h2 {
margin-bottom: 15px;
font-style: italic;
font-weight: normal;
}
.contact-box label {
font-size: 15px;
margin-bottom: 2px;
display: block;
}
.contact-box input, .contact-box select, .contact-box textarea {
width: 100%;
font-size: 15px;
border: 1px solid #CEE1E8;
margin-bottom: 20px;
padding: 4px;
}
.contact-box input:focus, .contact-box select:focus, .contact-box textarea:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}
.contact-box textarea {
height: 150px;
resize: none;
}
.contact-box span.required {
font-weight: bold;
color: #F00;
}
.contact-box input[type=submit] {
width: 100px;
background-color: #333;
color: #FFF;
border: none;
display: block;
float: right;
margin-bottom: 0px;
margin-right: 6px;
background-color: #8FB5C1;
-moz-border-radius: 8px;
}
.contact-box input[type=submit]:hover {
background-color: #A6CFDD;
}
.contact-box input[type=submit]:active {
position: relative;
top: 1px;
}
.contact-box .message {
width: 95%;
margin: 25px 0px;
padding: 10px;
display: block;
border: solid 1px #ccc;
border-radius: 8px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
}
.contact-box .message.hidden {
display: none;
}
.contact-box .message.error {
border-color: #E58E8E;
background-color: #FFE6E6;
}
.contact-box .message.error li {
padding: 2px;
list-style: none;
}
.contact-box .message.error li:before {
content: ' - ';
}
.contact-box .message.error #info {
font-weight: bold;
}
.contact-box .message.error #info:before {
content: '';
}
.contact-box .message.success {
border-color: #83D186;
padding-top: 25px;
background-color: #D3EDD3;
}
.contact-box .req-field-desc {
font-style: italic;
}
.contact-box input:required, .contact-box textarea:required {
-moz-box-shadow: none;
-webkit-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
}
.contact-box ::-webkit-input-placeholder {
color: #CCC;
font-style: italic;
}
.contact-box input:-moz-placeholder, .contact-box textarea:-moz-placeholder {
color: #CCC;
font-style: italic;
}
.contact-box input.placeholder-text, .contact-box textarea.placeholder-text {
color: #CCC;
font-style: italic;
}

View File

@@ -0,0 +1,140 @@
.contact-box {
background-color:#F2F7F9;
width:465px;
padding:20px;
border: 6px solid #8FB5C1;
-moz-border-radius:15px;
-webkit-border-radius:15px;
border-radius:15px;
position:relative;
h1 {
font-size:42px;
}
h2 {
margin-bottom:15px;
font-style:italic;
font-weight:normal;
}
label {
font-size:15px;
margin-bottom:2px;
display:block;
}
input, select, textarea {
width:100%;
font-size:15px;
border: 1px solid #CEE1E8;
margin-bottom:20px;
padding:4px;
&:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}
}
textarea {
height:150px;
resize: none;
}
span.required {
font-weight:bold;
color:#F00;
}
input[type=submit] {
width: 100px;
background-color:#333;
color:#FFF;
border:none;
display:block;
float:right;
margin-bottom:0px;
margin-right:6px;
background-color:#8FB5C1;
-moz-border-radius:8px;
&:hover {
background-color: #A6CFDD;
}
&:active {
position:relative;
top:1px;
}
}
.message {
width:95%;
margin:25px 0px;
padding:10px;
display:block;
border:solid 1px #ccc;
border-radius:8px;
-webkit-border-radius:8px;
-moz-border-radius:8px;
&.hidden {
display: none;
}
&.error {
border-color: #E58E8E;
background-color:#FFE6E6;
li {
padding:2px;
list-style:none;
&:before { content: ' - '; }
}
#info {
font-weight:bold;
&:before { content: ''; }
}
}
&.success {
border-color: #83D186;
padding-top: 25px;
background-color:#D3EDD3;
}
}
.req-field-desc {
font-style:italic;
}
/* Remove box shadow firefox, chrome and opera put around required fields.
* It looks rubbish.
*/
input:required, textarea:required {
-moz-box-shadow:none;
-webkit-box-shadow:none;
-o-box-shadow:none;
box-shadow:none;
}
/* Normalize placeholder styles */
/* chrome, safari */
::-webkit-input-placeholder {
color:#CCC;
font-style:italic;
}
/* mozilla */
input:-moz-placeholder, textarea:-moz-placeholder {
color:#CCC;
font-style:italic;
}
/* ie (faux placeholder) */
input.placeholder-text, textarea.placeholder-text {
color:#CCC;
font-style:italic;
}
}

View File

@@ -0,0 +1,25 @@
<div class="contact-box clearfix">
<h1>Contact us!</h1>
<form method="post" action="{$site_url/}contact" id="contact-form">
<label for="name">Name: <span class="required">*</span></label>
<input type="text" id="name" name="name" value="{$name/}" required="required" autofocus="autofocus" />
<label for="email">Email Address: <span class="required">*</span></label>
<input type="email" id="email" name="email" value="{$email/}" required="required" />
<label for="message">Message: <span class="required">*</span></label>
<textarea id="message" name="message" required="required" data-minlength="20" minlength="20" >{$message/}</textarea>
{unless isempty="$recaptcha_site_key"}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div>
<br/>
{/unless}
<input type="submit" value="Send" class="submit-button" />
<p class="req-field-desc"><span class="required">*</span> indicates a required field</p>
</form>
{unless isempty="$error_response"}
<ul class="message error">
{foreach item="item" from="$error_response"}<li class="info">{$item/}</li>{/foreach}
</ul>
<div class="notice"> Try again later </div>
{/unless}
</div>

View File

@@ -0,0 +1,15 @@
<div class="contact-box">
{if condition="$has_error"}
<div class="message error">
<strong>Internal Server Error <small>Error 500</small></strong>
<p>The page you requested could not be served because the server is down,
either contact the webmaster or try again.
Use your browser's <strong>Back</strong> button to navigate to the page you came from.</p>
<p><strong>Or you could just press this link:</strong> <a href="{$site_url/}" itemprop="home" rel="home">Take Me Home</a></p>
</div>
{/if}
{unless condition="$has_error"}
<p class="message success">Thank you for contacting the Eiffel Programming Language community.<br/>
We will get back to you promptly on your contact request.</p>
{/unless}
</div>

View File

@@ -0,0 +1,10 @@
<p>
Thank you for contacting {$sitename/}.<br/>
We will get back to you promptly about your contact message.
</p>
<h2>Your contact information:</h2>
<div>
<strong>Name<strong>: {$name/} <br/>
<strong>Email<strong>: {$email/} <br/>
<strong>Message<strong>: {$message/} <br/>
</div>

View File

@@ -0,0 +1,6 @@
<h2>Contact information:</h2>
<div>
<strong>Name<strong>: {$name/}<br/>
<strong>Email<strong>: {$email/} <br/>
<strong>Message<strong>: {$message/} <br/>
</div>

View File

@@ -1,4 +1,29 @@
CREATE TABLE `logs`(
`id` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`category` VARCHAR(255) NOT NULL,
`level` INTEGER NOT NULL,
`uid` INTEGER,
`message` TEXT NOT NULL,
`info` TEXT,
`link` TEXT,
`date` DATETIME NOT NULL
);
CREATE TABLE `custom_values`(
`type` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NOT NULL,
`value` TEXT
);
CREATE TABLE `path_aliases`(
`pid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`source` VARCHAR(255) NOT NULL,
`alias` VARCHAR(255) NOT NULL,
`lang` VARCHAR(12)
);
CREATE TABLE `users`(
`uid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`name` VARCHAR(100) NOT NULL,
@@ -8,6 +33,7 @@ CREATE TABLE `users`(
`status` INTEGER,
`created` DATETIME NOT NULL,
`signed` DATETIME,
`profile_name` VARCHAR(250) NULL,
CONSTRAINT `name`
UNIQUE(`name`)
);
@@ -46,3 +72,18 @@ CREATE TABLE `users_password_recovery` (
CONSTRAINT `token` UNIQUE (`token`)
);
CREATE TABLE `auth_temp_users` (
`uid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`name` VARCHAR(100) NOT NULL,
`password` VARCHAR(100) NOT NULL,
`salt` VARCHAR(100) NOT NULL,
`email` VARCHAR(250) NOT NULL,
`application` TEXT NOT NULL,
CONSTRAINT `name`
UNIQUE(`name`)
);

View File

@@ -0,0 +1,2 @@
ALTER TABLE users ADD profile_name VARCHAR(250) NULL;

View File

@@ -0,0 +1,6 @@
CREATE TABLE user_profiles(
`uid` INTEGER NOT NULL CHECK("uid">=0),
`key` VARCHAR(255) NOT NULL,
`value` TEXT,
CONSTRAINT PK_uid_key PRIMARY KEY (uid,key)
);

View File

@@ -0,0 +1,11 @@
{
"blocks": {
"test": {
"title": "Custom block test",
"is_raw": "yes",
"region": "footer",
"weight": 100,
"conditions": ["path:demo/*"]
}
}
}

View File

@@ -1,3 +1,10 @@
div.feed ul.nav {
list-style: none;
}
div.feed ul.nav li {
display: inline-block;
padding-right: 1em;
}
div.feed ul {
list-style: none;
position: relative;

View File

@@ -1,4 +1,11 @@
div.feed {
ul.nav {
list-style: none;
li {
display: inline-block;
padding-right: 1em;
}
}
ul {
list-style: none;
position: relative;

View File

@@ -0,0 +1,52 @@
.uploaded-files table {
width: 100%;
border-collapse: collapse;
border: 1px solid black;
}
.uploaded-files table th {
padding: 3px 0 3px 5px;
}
.uploaded-files table td {
padding: 3px 0 3px 5px;
}
.uploaded-files a.button {
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
}
.uploaded-files a.button:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
}
.upload-files .center {
text-align: center;
padding: 10px;
}
.upload-files a.button {
margin: auto;
width: 100px;
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
}
.upload-files a.button:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
}
/******************* Drop Zone *******************/
.dropzone {
width: 100%;
border: 2px dashed blue;
border-radius: 3px;
text-align: center;
padding-top: 15px;
padding-bottom: 15px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1 @@
.dropzone,.dropzone *{box-sizing:border-box}.dropzone{position:relative}.dropzone .dz-preview{position:relative;display:inline-block;width:120px;margin:0.5em}.dropzone .dz-preview .dz-progress{display:block;height:15px;border:1px solid #aaa}.dropzone .dz-preview .dz-progress .dz-upload{display:block;height:100%;width:0;background:green}.dropzone .dz-preview .dz-error-message{color:red;display:none}.dropzone .dz-preview.dz-error .dz-error-message,.dropzone .dz-preview.dz-error .dz-error-mark{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{display:block}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{position:absolute;display:none;left:30px;top:30px;width:54px;height:58px;left:50%;margin-left:-27px}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
position: relative;
.dz-preview {
position: relative;
display: inline-block;
width: 120px;
margin: 0.5em;
.dz-progress {
display: block;
height: 15px;
border: 1px solid #aaa;
.dz-upload {
display: block;
height: 100%;
width: 0;
background: green;
}
}
.dz-error-message {
color: red;
display: none;
}
&.dz-error {
.dz-error-message, .dz-error-mark {
display: block;
}
}
&.dz-success {
.dz-success-mark {
display: block;
}
}
.dz-error-mark, .dz-success-mark {
position: absolute;
display: none;
left: 30px;
top: 30px;
width: 54px;
height: 58px;
left: 50%;
margin-left: -(54px/2);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
@mixin keyframes($name) {
@-webkit-keyframes #{$name} {
@content;
}
@-moz-keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
@mixin prefix($map, $vendors: webkit moz ms o) {
@each $prop, $value in $map {
@if $vendors {
@each $vendor in $vendors {
#{"-" + $vendor + "-" + $prop}: #{$value};
}
}
// Dump regular property anyway
#{$prop}: #{$value};
}
}
@include keyframes(passing-through) {
0% {
opacity: 0;
@include prefix((transform: translateY(40px)));
}
30%, 70% {
opacity: 1;
@include prefix((transform: translateY(0px)));
}
100% {
opacity: 0;
@include prefix((transform: translateY(-40px)));
}
}
@include keyframes(slide-in) {
0% {
opacity: 0;
@include prefix((transform: translateY(40px)));
}
30% {
opacity: 1;
@include prefix((transform: translateY(0px)));
}
}
@include keyframes(pulse) {
0% { @include prefix((transform: scale(1))); }
10% { @include prefix((transform: scale(1.1))); }
20% { @include prefix((transform: scale(1))); }
}
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
$image-size: 120px;
$image-border-radius: 20px;
&.dz-clickable {
cursor: pointer;
* {
cursor: default;
}
.dz-message {
&, * {
cursor: pointer;
}
}
}
min-height: 150px;
border: 2px solid rgba(0, 0, 0, 0.3);
background: white;
padding: 20px 20px;
&.dz-started {
.dz-message {
display: none;
}
}
&.dz-drag-hover {
border-style: solid;
.dz-message {
opacity: 0.5;
}
}
.dz-message {
text-align: center;
margin: 2em 0;
}
.dz-preview {
position: relative;
display: inline-block;
vertical-align: top;
margin: 16px;
min-height: 100px;
&:hover {
// Making sure that always the hovered preview element is on top
z-index: 1000;
.dz-details {
opacity: 1;
}
}
&.dz-file-preview {
.dz-image {
border-radius: $image-border-radius;
background: #999;
background: linear-gradient(to bottom, #eee, #ddd);
}
.dz-details {
opacity: 1;
}
}
&.dz-image-preview {
background: white;
.dz-details {
@include prefix((transition: opacity 0.2s linear));
}
}
.dz-remove {
font-size: 14px;
text-align: center;
display: block;
cursor: pointer;
border: none;
&:hover {
text-decoration: underline;
}
}
&:hover .dz-details {
opacity: 1;
}
.dz-details {
$background-color: #444;
z-index: 20;
position: absolute;
top: 0;
left: 0;
opacity: 0;
font-size: 13px;
min-width: 100%;
max-width: 100%;
padding: 2em 1em;
text-align: center;
color: rgba(0, 0, 0, 0.9);
$width: 120px;
line-height: 150%;
.dz-size {
margin-bottom: 1em;
font-size: 16px;
}
.dz-filename {
white-space: nowrap;
&:hover {
span {
border: 1px solid rgba(200, 200, 200, 0.8);
background-color: rgba(255, 255, 255, 0.8);
}
}
&:not(:hover) {
span {
border: 1px solid transparent;
}
overflow: hidden;
text-overflow: ellipsis;
}
}
.dz-filename, .dz-size {
span {
background-color: rgba(255, 255, 255, 0.4);
padding: 0 0.4em;
border-radius: 3px;
}
}
}
&:hover {
.dz-image {
// opacity: 0.8;
img {
@include prefix((transform: scale(1.05, 1.05))); // Getting rid of that white bleed-in
@include prefix((filter: blur(8px)), webkit); // Getting rid of that white bleed-in
}
}
}
.dz-image {
border-radius: $image-border-radius;
overflow: hidden;
width: $image-size;
height: $image-size;
position: relative;
display: block;
z-index: 10;
img {
display: block;
}
}
&.dz-success {
.dz-success-mark {
@include prefix((animation: passing-through 3s cubic-bezier(0.770, 0.000, 0.175, 1.000)));
}
}
&.dz-error {
.dz-error-mark {
opacity: 1;
@include prefix((animation: slide-in 3s cubic-bezier(0.770, 0.000, 0.175, 1.000)));
}
}
.dz-success-mark, .dz-error-mark {
$image-height: 54px;
$image-width: 54px;
pointer-events: none;
opacity: 0;
z-index: 500;
position: absolute;
display: block;
top: 50%;
left: 50%;
margin-left: -($image-width/2);
margin-top: -($image-height/2);
svg {
display: block;
width: $image-width;
height: $image-height;
}
}
&.dz-processing .dz-progress {
opacity: 1;
@include prefix((transition: all 0.2s linear));
}
&.dz-complete .dz-progress {
opacity: 0;
@include prefix((transition: opacity 0.4s ease-in));
}
&:not(.dz-processing) {
.dz-progress {
@include prefix((animation: pulse 6s ease infinite));
}
}
.dz-progress {
opacity: 1;
z-index: 1000;
pointer-events: none;
position: absolute;
height: 16px;
left: 50%;
top: 50%;
margin-top: -8px;
width: 80px;
margin-left: -40px;
// border: 2px solid #333;
background: rgba(255, 255, 255, 0.9);
// Fix for chrome bug: https://code.google.com/p/chromium/issues/detail?id=157218
-webkit-transform: scale(1);
border-radius: 8px;
overflow: hidden;
.dz-upload {
background: #333;
background: linear-gradient(to bottom, #666, #444);
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0;
@include prefix((transition: width 300ms ease-in-out));
}
}
&.dz-error {
.dz-error-message {
display: block;
}
&:hover .dz-error-message {
opacity: 1;
pointer-events: auto;
}
}
.dz-error-message {
$width: $image-size + 20px;
$color: rgb(190, 38, 38);
pointer-events: none;
z-index: 1000;
position: absolute;
display: block;
display: none;
opacity: 0;
@include prefix((transition: opacity 0.3s ease));
border-radius: 8px;
font-size: 13px;
top: $image-size + 10px;
left: -10px;
width: $width;
background: $color;
background: linear-gradient(to bottom, $color, darken($color, 5%));
padding: 0.5em 1.2em;
color: white;
// The triangle pointing up
&:after {
content: '';
position: absolute;
top: -6px;
left: $width / 2 - 6px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid $color;
}
}
}
}

View File

@@ -0,0 +1,63 @@
.uploaded-files {
table {
width: 100%;
border-collapse: collapse;
border: 1px solid black;
th {
padding: 3px 0 3px 5px;
}
td {
padding: 3px 0 3px 5px;
}
}
a.button{
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
}
}
}
.upload-files {
.center {
text-align: center;
padding: 10px;
}
a.button{
margin: auto;
width: 100px;
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
}
}
}
/******************* Drop Zone *******************/
.dropzone {
width: 100%;
border: 2px dashed blue;
border-radius: 3px;
text-align: center;
padding-top: 15px;
padding-bottom: 15px;
}

View File

@@ -0,0 +1,5 @@
{
"gcse": {
"search_engine_id":""
}
}

View File

@@ -0,0 +1,6 @@
<form action="{$site_url/}gcse20" class="search-form" id="search-form">
<div class="form-group has-feedback">
<input type="search" class="form-control" name="q" id="search-query" placeholder="search" value="{htmlentities}{$cms_search_query/}{/htmlentities}" >
<span class="glyphicon glyphicon-search form-control-feedback"></span>
</div>
</form>

View File

@@ -0,0 +1,7 @@
<section>
<header>
<h2>Results for <kbd>{$cms_search_query/}</kbd></h2>
</header>
<gcse:searchresults-only></gcse:searchresults-only>
</section>

View File

@@ -0,0 +1,15 @@
.messaging-box fieldset {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
overflow: scroll;
height: 50ex;
line-height: 2.5ex;
}
.messaging-box fieldset div {
width: 300px;
}
.messaging-box fieldset input[type="checkbox"] {
margin-right: 5px;
margin-left: 3px;
}

View File

@@ -0,0 +1,18 @@
.messaging-box {
fieldset {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
div {
width: 300px;
}
overflow:scroll;
height:50ex;
line-height: 2.5ex;
input[type="checkbox"] {
margin-right: 5px;
margin-left: 3px;
}
}
}

View File

@@ -9,6 +9,9 @@ ul.cms-nodes li {
ul.cms-nodes li:first-child {
border-top: none;
}
ul.cms-nodes li span.author, ul.cms-nodes li span.info {
float: right;
}
ul.cms-nodes li.cms_type_page a::before {
content: "[page] ";
}

View File

@@ -3,22 +3,20 @@ ul.cms-nodes {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
span.author, span.info {
float: right;
}
}
li.cms_type_page a::before {
content: "[page] ";
}
li.cms_type_blog a::before {
content: "[blog] ";
}
}

View File

@@ -8,6 +8,7 @@ CREATE TABLE nodes (
`content` TEXT,
`format` VARCHAR(128),
`author` INTEGER,
`editor` INTEGER,
`publish` DATETIME,
`created` DATETIME NOT NULL,
`changed` DATETIME NOT NULL,
@@ -23,15 +24,9 @@ CREATE TABLE node_revisions (
`content` TEXT,
`format` VARCHAR(128),
`author` INTEGER,
`editor` INTEGER,
`changed` DATETIME NOT NULL,
`status` INTEGER,
CONSTRAINT Unique_nid_revision PRIMARY KEY (nid,revision)
);
CREATE TABLE page_nodes(
`nid` INTEGER NOT NULL,
`revision` INTEGER NOT NULL,
`parent` INTEGER,
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);

View File

@@ -0,0 +1,8 @@
CREATE TABLE page_nodes(
`nid` INTEGER NOT NULL,
`revision` INTEGER NOT NULL,
`parent` INTEGER,
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);

View File

@@ -0,0 +1,7 @@
ALTER TABLE nodes ADD editor INTEGER ;
UPDATE nodes SET editor = author;
ALTER TABLE node_revisions ADD editor INTEGER ;
UPDATE node_revisions SET editor = author;

View File

@@ -1,7 +1,7 @@
<div class="primary-tabs">
<div>
{foreach item="item" from="$oauth_consumers"}
<a href="{$site_url/}account/login-with-oauth/{$item/}">Login with {$item/}</a><br>
<a href="{$site_url/}account/auth/login-with-oauth/{$item/}">Login with {$item/}</a><br>
{/foreach}
</div>
</div>

View File

@@ -0,0 +1,9 @@
CREATE TABLE auth_session (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` VARCHAR(64) NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid` UNIQUE(`uid`),
CONSTRAINT `access_token` UNIQUE(`access_token`)
);

View File

@@ -0,0 +1,24 @@
{unless isset="$user"}
<div class="login-box">
<div class="description">The "Session" is the standard authentication system. (based on cookie)</div>
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
<div>
<form name="cms_session_auth" action="{$site_url/}account/auth/roc-session-login" method="POST">
{unless isempty="$site_destination"}<input type="hidden" name="destination" value="{$site_destination/}">{/unless}
<div>
<input type="text" name="username" id="username" required value="{$username/}">
<label>Username</label>
</div>
<div>
<input type="password" name="password" id="password" required >
<label>Password</label>
</div>
<button type="submit">Login</button>
</form>
</div>
<div>
<a href="{$site_url/}account/new-password">Forgot password?</a>
</div>
{if isset="$error"}<div class="error">{$error/}</div>{/if}
</div>
{/unless}

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>XML Sitemap</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body {
font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana;
font-size: 13px;
}
#header {
text-align: center;
padding-top: 14px;
padding-bottom: 29px;
}
h1 {
font-weight: normal;
font-size: 24px;
line-height: 20px;
color: #333333;
}
h2 {
font-weight: normal;
font-size: 13px;
color: #aaaaaa;
line-height: 10px;
}
#content {
background: #f8f8f8;
border-top: 1px solid #dddddd;
padding-top: 50px;
}
#content a:visited,
#content tr:hover a:visited {
color: #68009c;
}
table {
margin: 0 auto;
text-align: left;
}
tr#table-header:hover {
background: none;
}
tr:hover {
background: #ebebeb;
}
#content tr:hover a {
color: #6e6e6e;
}
td {
color: #6e6e6e;
font-size: 12px;
border-bottom: 1px solid #dddddd;
padding: 11px 5px 13px;
}
th {
color: #333333;
font-size: 12px;
border-bottom: 1px solid #dddddd;
padding: 5px 50px 17px 5px;
}
#footer {
background: #f8f8f8;
font-size: 13px;
color: #aaaaaa;
padding: 54px 0 20px;
text-align: center;
}
a {
color: #2384c6;
}
a:hover {
color: #6e6e6e;
text-decoration: none;
}
</style>
</head>
<body>
<div id="header">
<h1>XML Sitemap</h1>
<h2>This is a XML Sitemap which is supposed to be processed by <a href="http://www.google.com">Google search engine</a>.</h2>
</div>
<div id="content">
<table cellpadding="5" cellspacing="0">
<tr id="table-header">
<th>URL</th>
<th>Priority</th>
<th>Change Frequency</th>
<th>LastChange (GMT)</th>
</tr>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:for-each select="sitemap:urlset/sitemap:url">
<tr>
<xsl:if test="position() mod 2 != 1">
<xsl:attribute name="class">high</xsl:attribute>
</xsl:if>
<td>
<xsl:variable name="itemURL">
<xsl:value-of select="sitemap:loc"/>
</xsl:variable>
<a href="{$itemURL}">
<xsl:value-of select="sitemap:loc"/>
</a>
</td>
<td>
<xsl:value-of select="concat(sitemap:priority*100,'%')"/>
</td>
<td>
<xsl:value-of select="concat(translate(substring(sitemap:changefreq, 1, 1),concat($lower, $upper),concat($upper, $lower)),substring(sitemap:changefreq, 2))"/>
</td>
<td>
<xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)))"/>
</td>
</tr>
</xsl:for-each>
</table>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,26 @@
ul.taxonomy {
font-size: 80%;
list-style-type: none;
font-style: italic;
margin: 0;
}
ul.taxonomy li {
padding: 2px;
margin-right: 3px;
display: inline-block;
border: none;
}
ul.taxonomy li a:hover {
text-decoration: none;
}
ul.taxonomy li:hover {
padding: 1px;
border-top: solid 1px #66f;
border-bottom: solid 1px #66f;
background-color: #ddf;
}
table.taxonomy td {
border: solid 1px #ccc;
padding: 2px;
}

View File

@@ -0,0 +1,27 @@
ul.taxonomy {
font-size: 80%;
list-style-type: none;
font-style: italic;
margin: 0;
li {
a:hover {
text-decoration: none;
}
padding: 2px;
margin-right: 3px;
display: inline-block;
border: none;
&:hover {
padding: 1px;
border-top: solid 1px #66f;
border-bottom: solid 1px #66f;
background-color: #ddf;
}
}
}
table.taxonomy {
td {
border: solid 1px #ccc;
padding: 2px;
}
}

View File

@@ -0,0 +1,24 @@
CREATE TABLE taxonomy_term (
`tid` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
`text` VARCHAR(255) NOT NULL,
`weight` INTEGER,
`description` TEXT,
`langcode` VARCHAR(12)
);
CREATE TABLE taxonomy_hierarchy (
`tid` INTEGER NOT NULL,
`parent` INTEGER,
CONSTRAINT PK_tid_parent PRIMARY KEY (tid,parent)
);
/* Associate tid with unique (type,entity)
* for instance: "page" + "$nid" -> "tid"
*/
CREATE TABLE taxonomy_index (
`tid` INTEGER NOT NULL,
`entity` VARCHAR(255),
`type` VARCHAR(255) NOT NULL,
CONSTRAINT PK_tid_entity_type PRIMARY KEY (tid,entity,type)
);

Some files were not shown because too many files have changed in this diff Show More