Compare commits

..

144 Commits
0.7.2 ... 0.8.1

Author SHA1 Message Date
Romain Quetiez
63b27235e2 Release 0.8.1
SVN:0.8.1[195]
2009-10-19 16:48:29 +00:00
Romain Quetiez
be158b4673 Fixed typo on the default value of the server status (class: bizServer)
SVN:code[194]
2009-10-19 14:51:01 +00:00
Romain Quetiez
1a0ca15c1f Released 0.8 the 1st of october
SVN:code[193]
2009-10-19 14:48:20 +00:00
Romain Quetiez
280c1dde58 Added info in the log (see previous changes in the setup)
SVN:code[192]
2009-10-09 14:09:27 +00:00
Romain Quetiez
44d3e0c665 Fixed several issues in the setup (load of data) :
- stopper bug in case of reinstallation/upgrade: the file keyscache.tmp could be left in case of issue in the previous execution of the setup ; the file is now deleted prior to running a new session
- if a fatal error (e.g. call to undefined function) occured during the load of a file (ajax), then we had no clue that this happened ; a log has been added after the load so that we can get faster to the issue
- reordered data files (not the same order in MS-Explorer) to maximize ext key resolution on the first pass
- resolving external keys afterwards should work again (though the file order is avoiding this currently), as the objects are declared "dirty" and no automatic reload will be attempted during further manipulations
- added a log when an external key cannot be resolved during the final round

SVN:code[191]
2009-10-09 14:00:48 +00:00
Romain Quetiez
a1f3ac9534 Added investigation means: DB dump from the ITopConsultant page, this feature should not rely on mySQL statements that are not allowed in the OVH hosting setup. The feature is 100% new and does not interfere with any existing code. Therefore I would advise to upgrade the official build as quickly as possible.
SVN:code[190]
2009-10-02 15:07:28 +00:00
Romain Quetiez
f885fae267 Finalizing sample data: removed the unused profile
SVN:code[189]
2009-10-01 16:40:06 +00:00
Romain Quetiez
0ff9788ccb Added sample data: service calls, known errors, infra grouping, and some links (e.g. contact/team)
SVN:code[188]
2009-10-01 14:27:51 +00:00
Romain Quetiez
7461cb3fd5 Welcome menu updated with Erwan's text (quickly reviewed)
SVN:code[187]
2009-09-30 13:30:13 +00:00
Romain Quetiez
2e3bcef593 Added new sample data (forgotten from last commit)
SVN:code[186]
2009-09-30 13:00:30 +00:00
Romain Quetiez
3210573143 Integrated the latest data model and sample data
SVN:code[185]
2009-09-29 16:12:40 +00:00
Romain Quetiez
0f0113e578 Temporarily removed the TAB "OQL query", until it gets finalized with the link management
SVN:code[184]
2009-09-28 08:45:01 +00:00
Romain Quetiez
dc9707ec4b Fixed inconsistency in the CSV import : a bixServer objects had two fields (one was inherited) having the same label, leading to a high level of confusion when doing a bulk load (matching the fields was not possible)
SVN:code[183]
2009-09-22 14:13:07 +00:00
Romain Quetiez
7e7072b1ec Fixed bug in CSV import: was not working when using private keys. Also fine tuned the field matching mechanism and now the CSV export/import are 100% symmetric
SVN:code[182]
2009-09-22 13:36:29 +00:00
Romain Quetiez
2e9f13c4c5 Deletion of objects:
- automatic delete of mandatory ext keys, and if the option is set in the data model (I've set the "manual" option by default, and the "auto" option for links)
- automatic reset of optional ext keys (several keys could be updated on one single object)
- takes into account the user rights
- security against the use of page arguments when the automatic deletion is not allowed
Known limitations:
- does not check that resetting an ext key could affect the lifecycle consistency (e.g. delete a workgroup referenced by a ticket)
- does not check recursively on the automatic deletion, which should not be a problem given the current data model (TBC)

SVN:code[181]
2009-09-18 16:12:38 +00:00
Romain Quetiez
637993e7eb Fixed bug on deletion: take the inheritance into account when checking for referencing objects (eg. a ticket linked to a PC was not seen)
SVN:code[180]
2009-09-18 09:35:21 +00:00
Romain Quetiez
e176e2090c CSV import now based on the "bulk modify" user access rights
SVN:code[179]
2009-09-17 15:57:27 +00:00
Romain Quetiez
c641161e17 Fixed a security hole: any user was allowed to edit users and profiles, and therefore could give himself admin rights - now, only admins are allowed to do that
Also added a debugging capability: user rights shown for any object class, on demand in URP_Users::DisplayBareRelations()

SVN:code[178]
2009-09-17 15:50:28 +00:00
Romain Quetiez
d299fd451a Fixed regression on access control for the stimuli (also ipmlemented a workaround to a bug with the mantatory link attributes)
SVN:code[177]
2009-09-17 13:38:25 +00:00
Romain Quetiez
5e757db532 Cosmetic: Now that we request a confirmation on Delete, show the option as 'Delete...'
SVN:code[176]
2009-09-17 12:51:34 +00:00
Romain Quetiez
abbc21b0cb Fixed bug when creating a login (flush privileges = reset the data cache)
SVN:code[175]
2009-09-17 12:50:33 +00:00
Romain Quetiez
723341d94a Plugged in the allowed values management into the modification form and the stimulus form (limitation: take care with the data model and fields that depend on each other, until we replace those forms with the wizard that is currently being used for the object creation)
SVN:code[174]
2009-09-17 08:56:07 +00:00
Romain Quetiez
aea6f2e86f Forgotten from commit Nr 169
SVN:code[173]
2009-09-17 08:02:59 +00:00
Denis Flaven
d809170a51 Correct "script" tag... just in case...
SVN:code[172]
2009-09-16 16:09:46 +00:00
Denis Flaven
96e2732015 - Allowed values is now implemented, so I removed the comment !
SVN:code[171]
2009-09-16 16:08:52 +00:00
Denis Flaven
0bbe615664 - Fix for Internet Explorer: Arrays must be properly closed!
SVN:code[170]
2009-09-16 16:07:28 +00:00
Romain Quetiez
103f5e4568 User Management: removed limitation on the user rights that could not be established without a given object set, and added a feedback in the user details page (grant summary, based on the results returned by the std user management API, thus is reliable)
SVN:code[169]
2009-09-16 16:01:12 +00:00
Romain Quetiez
152b97a24a Fixed a regression: autocomplete not working due to a change in the execution of the script rendered in Ajax
SVN:code[168]
2009-09-16 15:00:40 +00:00
Denis Flaven
427a8eb596 - removed debug trace
SVN:code[167]
2009-09-16 14:14:15 +00:00
Romain Quetiez
cc8e80240f Fixed wrong file path for the graphs (lifecyle), could not work but on a Windows platform
SVN:code[166]
2009-09-16 08:48:54 +00:00
Romain Quetiez
91717f3f3b New menus (source: Erwan)
SVN:code[165]
2009-09-16 08:39:02 +00:00
Romain Quetiez
27965cc922 Fixed a regression on the management of the allowed values and attribute dependencies (symptom: Browse button not working, error when creating a ticket with no CI attached to it)
SVN:code[164]
2009-09-16 08:03:42 +00:00
Romain Quetiez
199a4865a4 Disabled the features not finalized (cloning, bookmarking, bulk operations)
SVN:code[163]
2009-09-16 07:59:11 +00:00
Romain Quetiez
7e93b35215 Fixed regression: ticket "impact" was reset ; resulting from a conflict in the form fields names (impact used both in the main detail form and into hidden links forms)
SVN:code[162]
2009-09-16 07:56:14 +00:00
Romain Quetiez
4517c61049 Fixed regression: server status was reset
SVN:code[161]
2009-09-16 07:53:12 +00:00
Denis Flaven
56c70ee33b - New cache management for the lifecycle graphs
SVN:code[160]
2009-09-14 16:50:51 +00:00
Romain Quetiez
76af2bb997 Cosmetics on the bulk load (followed new test plan)
SVN:code[159]
2009-09-14 16:06:04 +00:00
Romain Quetiez
56060ccb80 New business model (Erwan)
SVN:code[158]
2009-09-14 16:04:12 +00:00
Romain Quetiez
4496dad999 Cosmetic: display the stimulus label in the profile grants sumary
SVN:code[157]
2009-09-14 08:55:41 +00:00
Romain Quetiez
3fa3bfc260 Fixed bug: could not empty a field
SVN:code[156]
2009-09-14 08:40:28 +00:00
Romain Quetiez
f618678044 Hyperlinks in the history logs presentation
SVN:code[155]
2009-09-14 08:38:52 +00:00
Romain Quetiez
aa7e93e80c Revised the CSV import: fixed issues with the external keys, added hyperlinks to the found objects, obsoleted the word 'pkey', replaced by 'id'
SVN:code[154]
2009-09-14 08:37:10 +00:00
Denis Flaven
07af5501c5 Disabled automatic population of Zlists which was buggy. Not all ZLists are made of AttCode !
SVN:code[153]
2009-09-12 19:58:20 +00:00
Denis Flaven
07b4040c9e - Removed debug output into the console thats breaks when Firebug is not installed (or on IE)
SVN:code[152]
2009-09-12 10:08:13 +00:00
Denis Flaven
8d76f47303 - 'Add...' butotn is now grayed when there is nothing to Add
- Better handling of AllowedValues, supporting autocompletes
- Cleanup unused code in wizard.utils.js

SVN:code[151]
2009-09-11 21:23:24 +00:00
Denis Flaven
d922b4c7f3 Field validation now preserves background images
SVN:code[150]
2009-09-11 21:20:45 +00:00
Denis Flaven
be825be157 - Automatic adjustment of the width and height of the ModalDlg to fit the document's size
SVN:code[149]
2009-09-11 20:36:34 +00:00
Denis Flaven
7e57ea5365 Implementation of AllowedValues for fields that depend on other fields
SVN:code[148]
2009-09-11 20:35:16 +00:00
Romain Quetiez
40489c0821 New class: bizSubnet, implementing a dedicated view for IP management
SVN:code[147]
2009-09-11 16:38:12 +00:00
Romain Quetiez
ea59cf0fa8 Improve the UI on object deletion: added a confirmation form and do check the dependencies so as to preserve the DB integrity
SVN:code[146]
2009-09-11 15:44:24 +00:00
Romain Quetiez
e81dd420a1 Bug fix - object creation
SVN:code[145]
2009-09-11 15:34:40 +00:00
Romain Quetiez
6115797eb0 Work in progress for integration of "allowed values"
SVN:code[144]
2009-09-11 15:33:06 +00:00
Romain Quetiez
2bbcf30e2d Added INET_ATON and INET_NTOA verbs to the OQL, and allowed carrier returns chars (\r) in the OQL (same as a whitespace)
SVN:code[143]
2009-09-11 12:38:46 +00:00
Romain Quetiez
4c33a6eb81 Fixed bug in the history of tickets (incident or any other type, for which the name is based on the ticket ID, which remained undetermined until the record is created)
SVN:code[142]
2009-09-11 12:03:34 +00:00
Romain Quetiez
455c703468 Fixed a stopper bug in the display of N-N links from the default object display procedure (not using templates)
SVN:code[141]
2009-09-11 08:42:57 +00:00
Denis Flaven
7618c38a05 Added the validation of mandatory form fields before submitting the creation / modification / clone forms.
SVN:code[140]
2009-09-11 06:01:32 +00:00
Romain Quetiez
c5cc6f34f8 Fixed bug on Update / WriteLinks
SVN:code[139]
2009-09-10 16:20:35 +00:00
Romain Quetiez
874019c32a fixed interface of DisplaySet function
SVN:code[138]
2009-09-10 16:01:28 +00:00
Denis Flaven
76787fd9fb Proper handling of the parameters to DisplaySet
SVN:code[137]
2009-09-10 15:34:07 +00:00
Denis Flaven
8f2ea080d9 - Fixed the "modify" screen to have the "wizard look (thin green border)
SVN:code[136]
2009-09-10 15:33:31 +00:00
Denis Flaven
8094e3083e Proper handling of the parameters to DisplaySet
SVN:code[135]
2009-09-10 15:32:29 +00:00
Romain Quetiez
a5a1ae756f Fixed issue with Date fields being mandatory (DB column created with attribute ON UPDATE CURRENT_TIMESTAMP)
SVN:code[134]
2009-09-10 14:29:29 +00:00
Romain Quetiez
e5d9ede18a Integrated data model changes to the data load (incidents/contracts and persons were not correctly loaded
SVN:code[133]
2009-09-10 14:28:08 +00:00
Denis Flaven
2a6de0bd28 Added an automatic naming for the change tickets based on their Id (Same as for Incident tickets but starting with C-).
SVN:code[132]
2009-09-10 14:08:22 +00:00
Denis Flaven
858e32065c Fixed the icon of date input fields
SVN:code[131]
2009-09-10 14:04:14 +00:00
Denis Flaven
c4a6f869ea - Fix the style of the loaded table
SVN:code[130]
2009-09-10 13:20:53 +00:00
Romain Quetiez
3c8cbeb170 Fixed cosmetic issue on the user management pages (wrong styles in the templates)
SVN:code[129]
2009-09-10 11:14:10 +00:00
Romain Quetiez
bfc2df25d7 Fixed issue: user always considered as being an admin (regression due to changes in the setup), user profile setup is finally done at 100% in the setup code.
SVN:code[128]
2009-09-10 10:58:45 +00:00
Denis Flaven
e7c7bda520 Use the latest version (unmodified) of autocomplete instead of an old - and customized - version.
SVN:code[127]
2009-09-10 09:03:16 +00:00
Denis Flaven
3025a01e88 Use the latest version (unmodified) of autocomplete instead of an old - and customized - version.
SVN:code[126]
2009-09-10 08:58:07 +00:00
Denis Flaven
dff00d7a7a Use the latest version (unmodified) of autocomplete instead of an old - and customized - version.
SVN:code[125]
2009-09-10 08:56:20 +00:00
Romain Quetiez
242ccc37d3 Added a logoff button
SVN:code[124]
2009-09-09 15:06:14 +00:00
Romain Quetiez
801a108e6b Cosmetics on the run query page
SVN:code[123]
2009-09-09 12:44:06 +00:00
Romain Quetiez
e0c7620560 Improved the run query page: added meaningfull examples, including "ticket of the user currently logged in", and did some cosmetics on the page (examples shown in a drawer) ; needed to add some options to the OQL (date intervals)
SVN:code[122]
2009-09-08 15:10:31 +00:00
Romain Quetiez
b11bfff1f5 Reworked the "run query" page: renamed, improved the examples
SVN:code[121]
2009-09-08 09:25:57 +00:00
Romain Quetiez
93cad0ef6c Finalized attribute labels in the business data model (each word in uppercase, same conventions on external keys)
SVN:code[120]
2009-09-08 08:29:57 +00:00
Romain Quetiez
ab801850dd Latest data model (Erwan) and few cosmetic changes (safer display of object hyperlinks)
SVN:code[119]
2009-09-07 14:29:49 +00:00
Romain Quetiez
3d4b45de26 Audit rules loaded as part of the structure of the application
SVN:code[118]
2009-09-07 14:25:04 +00:00
Denis Flaven
37cad7579e - Proper display on the n-n links
SVN:code[117]
2009-09-07 14:00:25 +00:00
Denis Flaven
4d1a5209db - Adjusted size of the CSV export
- nicer display for the modification of objects

SVN:code[116]
2009-09-07 13:58:53 +00:00
Denis Flaven
565891ce1c - Workaround for noit taking search parameters into account when displaying linked items.
SVN:code[115]
2009-09-07 13:57:12 +00:00
Denis Flaven
0b91c4724b - Style for auto-complete fields
SVN:code[114]
2009-09-07 13:54:45 +00:00
Denis Flaven
3849da02ac Limit the size of the table to fit the screen.
SVN:code[113]
2009-09-07 13:35:09 +00:00
Denis Flaven
657987f365 - Style for auto-complete fields
SVN:code[112]
2009-09-07 12:19:33 +00:00
Denis Flaven
18c875a326 Background image for auto-complete fields
SVN:code[111]
2009-09-07 12:18:09 +00:00
Romain Quetiez
6c286bf952 Finalization of the user management by profile (UI to manage the accounts), and some unrelated changes:
- Using class labels in the UI
- Data model: you may specify a set of allowed values from a query (see caller_id in bizIncident class), still not 100% used in the UI but does not generate any error
- Data model: you may specify a password field (AttributePassword replacing AttributeString)
- Setup: calling UserRight::Setup() right after calling UserRight::CreateAdministrator()
- Setup: administrator account created with "my organization" and a dedicated contact
- Menus: optimized the load of std menus (queries written in OQL to get the benefit of the query cache)
- Menus: admin tools, seen only by people having the "admin" profile
- Object edition: fixed bug with the display of N-N links in the form

SVN:code[110]
2009-09-04 15:22:40 +00:00
Romain Quetiez
a096d46a59 Improved the behavior when a link class to not have any other attributes than the external keys. Still, it requires some work to have this configuration working.
SVN:code[109]
2009-09-02 13:39:20 +00:00
Romain Quetiez
5cfcc1f516 In the UI, the class names have been replaced by the class labels
SVN:code[108]
2009-09-02 13:18:59 +00:00
Romain Quetiez
5ee94f9d3d Changed images paths into relative path (../images where it was still /images)
SVN:code[107]
2009-08-27 13:56:57 +00:00
Romain Quetiez
6cc4ab7e9d Fixed bug provoking a warning unseen so far but it was causing a fatal error during the installation, with IIS as web server
SVN:code[106]
2009-08-27 13:52:31 +00:00
Denis Flaven
dffab33080 Workaround for the missing REQUEST_URI on IIS
SVN:code[105]
2009-08-27 12:37:21 +00:00
Denis Flaven
31415e2482 - New user interface to manage n-n links
SVN:code[104]
2009-08-26 21:52:34 +00:00
Denis Flaven
cba7b556bd Fixed a missing display template
SVN:code[103]
2009-08-26 21:32:32 +00:00
Denis Flaven
d2a6a116b1 Fixed the disappearance of tabs when doing a 'reload'
SVN:code[102]
2009-08-25 19:48:37 +00:00
Denis Flaven
9130e5bcd0 New helper function IsModified
SVN:code[101]
2009-08-25 13:52:13 +00:00
Romain Quetiez
bc5ab17525 Improved the data load during the setup:
- Sample data are clearly separated from the structure data (inc. menus and user profiles)
- Both categories of data are enumerated from specific folders

SVN:code[100]
2009-08-24 16:40:11 +00:00
Denis Flaven
1a47af8c7b - Do NOT rely on PHP short open tags, for a better compatibility
- In case of exception, display the whole error string even if it contains HTML tags, sometimes ugly but sometimes VERY useful

SVN:code[99]
2009-08-22 09:52:12 +00:00
Denis Flaven
b4dbcbe9d8 Do NOT use PHP short open tags for a better compatibility
SVN:code[98]
2009-08-22 09:49:44 +00:00
Denis Flaven
1a3d8558c1 Do NOT use PHP short open tags for a better compatibility
SVN:code[97]
2009-08-22 09:49:13 +00:00
Denis Flaven
3cd364ab4b Make sure that we catch exceptions that may occur during the setup.
SVN:code[96]
2009-08-22 09:48:03 +00:00
Romain Quetiez
6c70bc4f03 Fixed issue #28, objects not created by the CSV import because mandatory external keys are not in the column set.
SVN:code[95]
2009-08-21 15:20:35 +00:00
Denis Flaven
852c063868 session_is_register is deprecated since PHP 5.3.0
SVN:code[94]
2009-08-21 13:57:38 +00:00
Romain Quetiez
2221709cc3 Finalized the module "user rights by profile". It is fully integrated with the application setup (inc. sample data). and it it now ready for developing the user management GUI
SVN:code[93]
2009-08-20 13:09:41 +00:00
Denis Flaven
0dc67869b5 - New search form allowing to perform OQL queries for any class of object
SVN:code[92]
2009-08-18 18:51:17 +00:00
Denis Flaven
8cf0103a0a - Improvements to the history log for large text fields
SVN:code[91]
2009-08-17 18:24:26 +00:00
Romain Quetiez
80a0d27cb0 User management by profile ready for integration with the UI
and some caching has been implemented for the building of queries (both from an OQL or from a programmatic query)

SVN:code[90]
2009-07-31 13:18:44 +00:00
Denis Flaven
59db699684 - Better display of the archives/change log on each object (Trac ticket #9)
SVN:code[89]
2009-07-24 15:44:51 +00:00
Romain Quetiez
367e678ff9 User management by profile moving forward: pages to check the projection of objects/users in user defined dimensions
Introduced parameters in OQL (:myvar)
Added the verb MetaModel::IsValidObject($oMyObj)

SVN:code[88]
2009-07-24 13:14:51 +00:00
Romain Quetiez
6659728058 Initialized dev of the user rights managed by profiles, it is still not usable by the application, but its data model is likely to be stable.
SVN:code[87]
2009-07-21 08:48:30 +00:00
Denis Flaven
a8d04b8a2e - new test case for JOINs
SVN:code[86]
2009-07-20 13:41:21 +00:00
Denis Flaven
650e5fcbd8 - Fixed bug #31: HTML display in the "export" page uses the appropriate stylesheet.
SVN:code[85]
2009-07-19 09:34:32 +00:00
Denis Flaven
039edd245d - enhancement: trap exceptions to keep a nice display in case of error
SVN:code[84]
2009-07-19 09:32:44 +00:00
Denis Flaven
4eb723b073 - reintegrated the changes (mostly bug fixes) from the 0.7.2 branch
SVN:code[83]
2009-07-18 17:24:25 +00:00
Denis Flaven
62fa1bfbf6 - Bug fix: emailed URL was still wrong for lists of objects
SVN:code[82]
2009-07-18 13:27:05 +00:00
Denis Flaven
85222612a9 - Bug fix: added the missing display template
SVN:code[81]
2009-07-16 06:49:33 +00:00
Denis Flaven
c4687e5899 - Fixed audit menu
- Removed backup/restore menu that is not working...
- Moved 'export' to the 'webservices' directory

SVN:code[80]
2009-07-08 16:13:10 +00:00
Denis Flaven
560345247e - The page was broken because there was no user login !
SVN:code[79]
2009-07-08 16:10:17 +00:00
Denis Flaven
48b63973a3 - The page was broken because there was no user login !
SVN:code[78]
2009-07-08 16:09:01 +00:00
Denis Flaven
fc15934dd0 - Fixed location of the "audit" page in the menu. Was broken if iTop was not installed at the root of the web server.
SVN:code[77]
2009-07-08 16:07:51 +00:00
Denis Flaven
6ef3961567 Fixed bug #24: choice of organizations was limited to organization in "implementation".
SVN:code[76]
2009-07-08 15:05:54 +00:00
Denis Flaven
0841f8f2d9 Fixed bug #24: choice of organizations was limited to organization in "implementation".
SVN:code[75]
2009-07-08 14:53:53 +00:00
Denis Flaven
9577fb5dd9 Incremented version number to 0.7.2
SVN:code[74]
2009-06-27 08:33:47 +00:00
Denis Flaven
427ccbe14c - bug fix: Ticket #1 (Life Cycle Schema not displayed)
SVN:code[73]
2009-06-27 08:32:46 +00:00
Denis Flaven
6520653306 - Bug fix: Ticket #2 (User rights not applied properly)
SVN:code[72]
2009-06-27 08:31:31 +00:00
Denis Flaven
c8b9954eef - Bug fix: Ticket #2 (User rights not applied properly)
SVN:code[71]
2009-06-27 08:30:13 +00:00
Denis Flaven
35a4611959 - Enhancement: display the current user's name in the top part of the window
SVN:code[70]
2009-06-27 08:28:58 +00:00
Denis Flaven
94904537ad - Bug fix: Ticket #3 (email hyperlink was wrong)
SVN:code[69]
2009-06-27 08:27:44 +00:00
Denis Flaven
5c55ffabf9 Fix for Ticket #22 (impossible to create change or incident tickets)
SVN:code[68]
2009-06-26 14:33:48 +00:00
Denis Flaven
46b8606b63 Fix for Ticket #22 (impossible to create change or incident tickets)
SVN:code[67]
2009-06-26 14:32:13 +00:00
Denis Flaven
b41421737e - Fixed sample data
SVN:code[66]
2009-06-26 12:56:04 +00:00
Denis Flaven
08cf5a8600 Preparing release 0.7.2
SVN:code[65]
2009-06-26 12:42:51 +00:00
Romain Quetiez
e8ec2968b3 CSVImport: Removed calls to deprecated method GetHyperLink
SVN:code[64]
2009-04-30 16:05:20 +00:00
Denis Flaven
74626cfe73 Removed CSVParser since the "old" version is already present in the CSV import page...
SVN:code[63]
2009-04-30 06:04:38 +00:00
Denis Flaven
8521f36fa2 Preparing to release 0.7.1
SVN:code[62]
2009-04-29 20:49:08 +00:00
Denis Flaven
dd95a1fcac Use non realistic persons...
SVN:code[61]
2009-04-29 20:38:51 +00:00
Denis Flaven
f126590165 Fixed bugs:
2783651 - New object - finalclass field is editable
2783643 - Number of objects displayed on result lists takes too much space
2783638 - PHP internal class name displayed in templates instead of class label
2783631 - Page "Admin tools/Backup-Restore" not working, removed !
2783629 - Menu "Admin Tools/Export" not working
2783625 - Cosmetics on new object wizard title

SVN:code[60]
2009-04-29 20:34:00 +00:00
Denis Flaven
b08ac55d93 New intermediate version
SVN:code[59]
2009-04-29 19:39:17 +00:00
Denis Flaven
0126c1322e Fixed bugs linked to the bookmark creation:
- There must be a user specific menu entry in the list of menuNodes
- The asynchronous ajax page must use the authentication stored in the session
- The query must be stored in OQL instead of sibusQL

SVN:code[58]
2009-04-28 13:24:12 +00:00
Denis Flaven
5ca45d7a82 Fixed bugs linked to the bookmark creation:
- There must be a user specific menu entry in the list of menuNodes
- The asynchronous ajax page must use the authentication stored in the session
- The query must be stored in OQL instead of sibusQL

SVN:code[57]
2009-04-28 11:52:38 +00:00
Denis Flaven
4c1156df76 SVN:code[56] 2009-04-28 11:30:40 +00:00
Denis Flaven
6545595f19 Moved under "trunk" to be able to track releases under "tags"
SVN:code[55]
2009-04-28 09:03:12 +00:00
Denis Flaven
27c05b460b Well identified releases of itop
SVN:code[54]
2009-04-28 08:53:56 +00:00
Denis Flaven
6e519e592f Main trunk (i.e. latest development version) of itop
SVN:code[53]
2009-04-28 08:52:21 +00:00
Romain Quetiez
a4663ebed1 Optimized the setup (not only), shortened to 37s (used to be 120s)
- DBObject::DBInsert(Tracked)NoReload() must be used when it is not required to use the object
- MetaModel::GetObject() has a cache, the operation is 5 times faster
- Changes tracking do not store the initial value, but only value changes
Reworked the CSV import to have it rely on the bulk change API
Bulk change to check the external keys (DB integrity)
Replaced trigger_error (Core only!) by the use of Exceptions (still, some new Exception classes should be defined)
Unit tests do display the call stack in a user friendly format

SVN:code[52]
2009-04-27 07:27:54 +00:00
3440 changed files with 451660 additions and 0 deletions

View File

@@ -0,0 +1,410 @@
<?php
/**
* UserRightsMatrix
* User management Module
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class UserRightsMatrixUsers extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"name" => "user",
"description" => "users and credentials",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "login",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixusers",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeInteger("userid", array("label"=>"User id", "description"=>"User identifier (depends on the business model)", "allowed_values"=>null, "sql"=>"userid", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("login", array("label"=>"login", "description"=>"user identification string", "allowed_values"=>null, "sql"=>"login", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("password", array("label"=>"password", "description"=>"user authentication string", "allowed_values"=>null, "sql"=>"pwd", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("userid");
MetaModel::Init_AddFilterFromAttribute("login");
}
}
class UserRightsMatrixClassGrant extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"name" => "class_permission",
"description" => "permissions on classes",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixclasses",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"UserRightsMatrixUsers", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("label"=>"Login", "description"=>"Login", "allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeString("class", array("label"=>"class", "description"=>"class name", "allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("action", array("label"=>"action", "description"=>"operations to perform on the given class", "allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("label"=>"permission", "description"=>"allowed or not allowed?", "allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("userid");
MetaModel::Init_AddFilterFromAttribute("login");
MetaModel::Init_AddFilterFromAttribute("class");
MetaModel::Init_AddFilterFromAttribute("action");
}
}
class UserRightsMatrixClassStimulusGrant extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"name" => "stimulus_permission",
"description" => "permissions on stimilus in the life cycle of the object",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixclassesstimulus",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"UserRightsMatrixUsers", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("label"=>"Login", "description"=>"Login", "allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeString("class", array("label"=>"class", "description"=>"class name", "allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("label"=>"action", "description"=>"operations to perform on the given class", "allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("label"=>"permission", "description"=>"allowed or not allowed?", "allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("userid");
MetaModel::Init_AddFilterFromAttribute("login");
MetaModel::Init_AddFilterFromAttribute("class");
MetaModel::Init_AddFilterFromAttribute("stimulus");
}
}
class UserRightsMatrixAttributeGrant extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "addon/userrights",
"name" => "attribute_permission",
"description" => "permissions at the attributes level",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_ur_matrixattributes",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"UserRightsMatrixUsers", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("label"=>"Login", "description"=>"Login", "allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login")));
MetaModel::Init_AddAttribute(new AttributeString("class", array("label"=>"class", "description"=>"class name", "allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("label"=>"attribute", "description"=>"attribute code", "allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("action", array("label"=>"action", "description"=>"operations to perform on the given class", "allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("label"=>"permission", "description"=>"allowed or not allowed?", "allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("userid");
MetaModel::Init_AddFilterFromAttribute("login");
MetaModel::Init_AddFilterFromAttribute("class");
MetaModel::Init_AddFilterFromAttribute("attcode");
MetaModel::Init_AddFilterFromAttribute("action");
}
}
class UserRightsMatrix extends UserRightsAddOnAPI
{
static public $m_aActionCodes = array(
UR_ACTION_READ => 'read',
UR_ACTION_MODIFY => 'modify',
UR_ACTION_DELETE => 'delete',
UR_ACTION_BULK_READ => 'bulk read',
UR_ACTION_BULK_MODIFY => 'bulk modify',
UR_ACTION_BULK_DELETE => 'bulk delete',
);
// Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd)
{
// Maybe we should check that no other user with userid == 0 exists
$oUser = new UserRightsMatrixUsers();
$oUser->Set('login', $sAdminUser);
$oUser->Set('password', $sAdminPwd);
$oUser->Set('userid', 1); // one is for root !
$oUser->DBInsert();
$this->SetupUser($oUser, true);
return true;
}
public function Setup()
{
// Users must be added manually
// This procedure will then update the matrix when a new user is found or a new class/attribute appears
$oUserSet = new DBObjectSet(DBObjectSearch::FromSibuSQL("UserRightsMatrixUsers"));
while ($oUser = $oUserSet->Fetch())
{
$this->SetupUser($oUser);
}
return true;
}
protected function SetupUser($oUser, $bNewUser = false)
{
$iUserId = $oUser->GetKey();
foreach(array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory)
{
foreach (MetaModel::GetClasses($sCategory) as $sClass)
{
foreach (self::$m_aActionCodes as $iActionCode => $sAction)
{
if ($bNewUser)
{
$bAddCell = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1);
}
if ($bAddCell)
{
// Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
$oMyClassGrant->Set("userid", $oUser->GetKey());
$oMyClassGrant->Set("class", $sClass);
$oMyClassGrant->Set("action", $sAction);
$oMyClassGrant->Set("permission", "yes");
$iId = $oMyClassGrant->DBInsert();
}
}
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
{
if ($bNewUser)
{
$bAddCell = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1);
}
if ($bAddCell)
{
// Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
$oMyClassGrant->Set("userid", $oUser->GetKey());
$oMyClassGrant->Set("class", $sClass);
$oMyClassGrant->Set("stimulus", $sStimulusCode);
$oMyClassGrant->Set("permission", "yes");
$iId = $oMyClassGrant->DBInsert();
}
}
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode)
{
if ($bNewUser)
{
$bAddCell = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '$sClass' AND attcode = '$sAttCode' AND userid = $iUserId"));
$bAddCell = ($oSet->Count() < 1);
}
if ($bAddCell)
{
foreach (array('read', 'modify') as $sAction)
{
// Create a new entry
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
$oMyAttGrant->Set("userid", $oUser->GetKey());
$oMyAttGrant->Set("class", $sClass);
$oMyAttGrant->Set("attcode", $sAttCode);
$oMyAttGrant->Set("action", $sAction);
$oMyAttGrant->Set("permission", "yes");
$iId = $oMyAttGrant->DBInsert();
}
}
}
}
}
// Create the "My Bookmarks" menu item (parent_id = 0, rank = 6)
if ($bNewUser)
{
$bAddMenu = true;
}
else
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT menuNode WHERE type = 'user' AND parent_id = 0 AND user_id = $iUserId"));
$bAddMenu = ($oSet->Count() < 1);
}
if ($bAddMenu)
{
$oMenu = MetaModel::NewObject('menuNode');
$oMenu->Set('type', 'user');
$oMenu->Set('parent_id', 0); // It's a toplevel entry
$oMenu->Set('rank', 6); // Located just above the Admin Tools section (=7)
$oMenu->Set('name', 'My Bookmarks');
$oMenu->Set('label', 'My Favorite Items');
$oMenu->Set('hyperlink', 'UI.php');
$oMenu->Set('template', '<p></p><p></p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:32px;">My bookmarks</p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:14px;"><i>This section contains my most favorite search results</i></p>');
$oMenu->Set('user_id', $iUserId);
$oMenu->DBInsert();
}
}
public function Init()
{
// Could be loaded in a shared memory (?)
return true;
}
public function CheckCredentials($sUserName, $sPassword)
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixUsers WHERE login = '$sUserName'"));
if ($oSet->Count() < 1)
{
// todo: throw an exception?
return false;
}
$oLogin = $oSet->Fetch();
if ($oLogin->Get('password') == $sPassword)
{
return true;
}
// todo: throw an exception?
return false;
}
public function GetFilter($sUserName, $sClass)
{
$oNullFilter = new DBObjectSearch($sClass);
return $oNullFilter;
}
public function IsActionAllowed($sUserName, $sClass, $iActionCode, dbObjectSet $aInstances)
{
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
{
return UR_ALLOWED_NO;
}
$sAction = self::$m_aActionCodes[$iActionCode];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '$sClass' AND action = '$sAction' AND login = '$sUserName'"));
if ($oSet->Count() < 1)
{
return UR_ALLOWED_NO;
}
$oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission'))
{
case 'yes':
$iRetCode = UR_ALLOWED_YES;
break;
case 'no':
default:
$iRetCode = UR_ALLOWED_NO;
break;
}
return $iRetCode;
}
public function IsActionAllowedOnAttribute($sUserName, $sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances)
{
if (!array_key_exists($iActionCode, self::$m_aActionCodes))
{
return UR_ALLOWED_NO;
}
$sAction = self::$m_aActionCodes[$iActionCode];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE UserRightsMatrixAttributeGrant.class = '$sClass' AND UserRightsMatrixAttributeGrant.attcode = '$sAttCode' AND UserRightsMatrixAttributeGrant.action = '$sAction' AND UserRightsMatrixAttributeGrant.login = '$sUserName'"));
if ($oSet->Count() < 1)
{
return UR_ALLOWED_NO;
}
$oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission'))
{
case 'yes':
$iRetCode = UR_ALLOWED_YES;
break;
case 'no':
default:
$iRetCode = UR_ALLOWED_NO;
break;
}
return $iRetCode;
}
public function IsStimulusAllowed($sUserName, $sClass, $sStimulusCode, dbObjectSet $aInstances)
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '$sClass' AND stimulus = '$sStimulusCode' AND login = '$sUserName'"));
if ($oSet->Count() < 1)
{
return UR_ALLOWED_NO;
}
$oGrantRecord = $oSet->Fetch();
switch ($oGrantRecord->Get('permission'))
{
case 'yes':
$iRetCode = UR_ALLOWED_YES;
break;
case 'no':
default:
$iRetCode = UR_ALLOWED_NO;
break;
}
return $iRetCode;
}
}
UserRights::SelectModule('UserRightsMatrix');
?>

View File

@@ -0,0 +1,682 @@
<?php
require_once('../application/webpage.class.inc.php');
require_once('../application/utils.inc.php');
require_once('../core/userrights.class.inc.php');
/**
* Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects
*
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
* The list of cmdbObjects to be displayed into the block is defined by a filter
* Right now the type of display is either: list, count, bare_details, details, csv, modify or search
* - list produces a table listing the objects
* - count produces a paragraphs with a sentence saying 'cont' objects found
* - bare_details displays just the details of the attributes of the object (best if only one)
* - details display the full details of each object found using its template (best if only one)
* - csv displays a textarea with the CSV export of the list of objects
* - modify displays the form to modify an object (best if only one)
* - search displays a search form with the criteria of the filter set
*/
class DisplayBlock
{
const TAG_BLOCK = 'itopblock';
protected $m_oFilter;
protected $m_sStyle;
protected $m_bAsynchronous;
protected $m_aParams;
protected $m_oSet;
public function __construct(DBObjectSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null)
{
$this->m_oFilter = $oFilter;
$this->m_sStyle = $sStyle;
$this->m_bAsynchronous = $bAsynchronous;
$this->m_aParams = $aParams;
$this->m_oSet = $oSet;
}
/**
* Constructs a DisplayBlock object from a DBObjectSet already in memory
* @param $oSet DBObjectSet
* @return DisplayBlock The DisplayBlock object, or null if the creation failed
*/
public static function FromObjectSet(DBObjectSet $oSet, $sStyle, $aParams = array())
{
$oDummyFilter = new DBObjectSearch($oSet->GetClass());
$oBlock = new DisplayBlock($oDummyFilter, $sStyle, false, $aParams, $oSet); // DisplayBlocks built this way are synchronous
return $oBlock;
}
/**
* Constructs a DisplayBlock object from an XML template
* @param $sTemplate string The XML template
* @return DisplayBlock The DisplayBlock object, or null if the template is invalid
*/
public static function FromTemplate($sTemplate)
{
$iStartPos = stripos($sTemplate, '<'.self::TAG_BLOCK.' ',0);
$iEndPos = stripos($sTemplate, '</'.self::TAG_BLOCK.'>', $iStartPos);
if (($iStartPos === false) || ($iEndPos === false)) return null; // invalid template
$sITopBlock = substr($sTemplate,$iStartPos, $iEndPos-$iStartPos);
$sITopData = substr($sITopBlock, 1+stripos($sITopBlock, ">"));
$sITopTag = substr($sITopBlock, 0, stripos($sITopBlock, ">"));
$aMatches = array();
$sBlockClass = "DisplayBlock";
$bAsynchronous = false;
$sBlockType = 'list';
$sEncoding = 'text/serialize';
if (preg_match('/ type="(.*)"/U',$sITopTag, $aMatches))
{
$sBlockType = strtolower($aMatches[1]);
}
if (preg_match('/ asynchronous="(.*)"/U',$sITopTag, $aMatches))
{
$bAsynchronous = (strtolower($aMatches[1]) == 'true');
}
if (preg_match('/ blockclass="(.*)"/U',$sITopTag, $aMatches))
{
$sBlockClass = $aMatches[1];
}
if (preg_match('/ objectclass="(.*)"/U',$sITopTag, $aMatches))
{
$sObjectClass = $aMatches[1];
}
if (preg_match('/ encoding="(.*)"/U',$sITopTag, $aMatches))
{
$sEncoding = strtolower($aMatches[1]);
}
if (preg_match('/ linkage="(.*)"/U',$sITopTag, $aMatches))
{
// The list to display is a list of links to the specified object
$sExtKey = strtolower($aMatches[1]);
$aParams['linkage'] = $sExtKey; // Name of the Ext. Key that make this linkage
}
// Parameters contains a list of extra parameters for the block
// the syntax is param_name1:value1;param_name2:value2;...
$aParams = array();
if (preg_match('/ parameters="(.*)"/U',$sITopTag, $aMatches))
{
$sParameters = $aMatches[1];
$aPairs = explode(';', $sParameters);
foreach($aPairs as $sPair)
{
if (preg_match('/(.*)\:(.*)/',$sPair, $aMatches))
{
$aParams[trim($aMatches[1])] = trim($aMatches[2]);
}
}
}
switch($sEncoding)
{
case 'text/serialize':
$oFilter = CMDBSearchFilter::unserialize($sITopData);
break;
case 'text/sibusql':
$oFilter = CMDBSearchFilter::FromSibusQL($sITopData);
break;
case 'text/oql':
$oFilter = CMDBSearchFilter::FromOQL($sITopData);
break;
}
return new $sBlockClass($oFilter, $sBlockType, $bAsynchronous, $aParams);
}
public function Display(web_page $oPage, $sId, $aExtraParams = array())
{
$aExtraParams = array_merge($aExtraParams, $this->m_aParams);
if (!$this->m_bAsynchronous)
{
// render now
$oPage->add("<div id=\"$sId\" class=\"display_block\">\n");
$this->RenderContent($oPage, $aExtraParams);
$oPage->add("</div>\n");
}
else
{
// render it as an Ajax (asynchronous) call
$sFilter = $this->m_oFilter->serialize();
$oPage->add("<div id=\"$sId\" class=\"display_block loading\">\n");
$oPage->p("<img src=\"../images/indicator_arrows.gif\"> Loading...");
$oPage->add("</div>\n");
$oPage->add('
<script language="javascript">
$.get("ajax.render.php?filter='.$sFilter.'&style='.$this->m_sStyle.'",
{ operation: "ajax" },
function(data){
$("#'.$sId.'").empty();
$("#'.$sId.'").append(data);
$("#'.$sId.'").removeClass("loading");
}
);
</script>'); // TO DO: add support for $aExtraParams in asynchronous/Ajax mode
}
}
public function GetDisplay(web_page $oPage, $sId, $aExtraParams = array())
{
$sHtml = '';
$aExtraParams = array_merge($aExtraParams, $this->m_aParams);
if (!$this->m_bAsynchronous)
{
// render now
$sHtml .= "<div id=\"$sId\" class=\"display_block\">\n";
$sHtml .= $this->GetRenderContent($oPage, $aExtraParams);
$sHtml .= "</div>\n";
}
else
{
// render it as an Ajax (asynchronous) call
$sFilter = $this->m_oFilter->serialize();
$sHtml .= "<div id=\"$sId\" class=\"display_block loading\">\n";
$sHtml .= $oPage->GetP("<img src=\"../images/indicator_arrows.gif\"> Loading...");
$sHtml .= "</div>\n";
$sHtml .= '
<script language="javascript">
$.get("ajax.render.php?filter='.$sFilter.'&style='.$this->m_sStyle.'",
{ operation: "ajax" },
function(data){
$("#'.$sId.'").empty();
$("#'.$sId.'").append(data);
$("#'.$sId.'").removeClass("loading");
}
);
</script>'; // TO DO: add support for $aExtraParams in asynchronous/Ajax mode
}
return $sHtml;
}
public function RenderContent(web_page $oPage, $aExtraParams = array())
{
$oPage->add($this->GetRenderContent($oPage, $aExtraParams));
}
public function GetRenderContent(web_page $oPage, $aExtraParams = array())
{
$sHtml = '';
// Add the extra params into the filter if they make sense for such a filter
$bDoSearch = utils::ReadParam('dosearch', false);
if ($this->m_oSet == null)
{
$aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
foreach($aFilterCodes as $sFilterCode)
{
$sExternalFilterValue = utils::ReadParam($sFilterCode, '');
if (isset($aExtraParams[$sFilterCode]))
{
$this->m_oFilter->AddCondition($sFilterCode, $aExtraParams[$sFilterCode]); // Use the default 'loose' operator
}
else if ($bDoSearch && $sExternalFilterValue != "")
{
$this->m_oFilter->AddCondition($sFilterCode, $sExternalFilterValue); // Use the default 'loose' operator
}
}
$this->m_oSet = new CMDBObjectSet($this->m_oFilter);
}
switch($this->m_sStyle)
{
case 'count':
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
foreach($aGroupBy as $sValue => $iCount)
{
$aData[] = array ( 'group' => $sValue,
'value' => "<a href=\"./UI.php?operation=search&dosearch=1&filter=$sFilter&$sGroupByField=".urlencode($sValue)."\">$iCount</a>"); // TO DO: add the context information
}
$sHtml .= $oPage->GetTable(array('group' => array('label' => MetaModel::GetLabel($this->m_oFilter->GetClass(), $sGroupByField), 'description' => ''), 'value' => array('label'=>'Count', 'description' => 'Number of elements')), $aData);
}
else
{
// Simply count the number of elements in the set
$iCount = $oSet->Count();
$sHtml .= $oPage->GetP("$iCount objects matching the criteria.");
}
break;
case 'list':
$bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false;
if ( ($this->m_oSet->Count()> 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) )
{
$sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : '';
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $sLinkage, !$bDashboardMode /* bDisplayMenu */);
}
else
{
$sHtml .= $oPage->GetP("No object to display.");
$sClass = $this->m_oFilter->GetClass();
if (!$bDashboardMode)
{
if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES)
{
$sHtml .= $oPage->GetP("<a href=\"./UI.php?operation=new&class=$sClass\">Click here to create a new ".Metamodel::GetName($sClass)."</a>\n");
}
}
}
break;
case 'details':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)
{
while($oObj = $this->m_oSet->Fetch())
{
$sHtml .= $oObj->GetDetails($oPage);
}
}
break;
case 'bare_details':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)
{
while($oObj = $this->m_oSet->Fetch())
{
$sHtml .= $oObj->GetBareDetails($oPage);
}
}
break;
case 'csv':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)
{
$sHtml .= "<textarea style=\"width:100%;height:98%\">\n";
$sHtml .= cmdbAbstractObject::GetSetAsCSV($this->m_oSet);
$sHtml .= "</textarea>\n";
}
break;
case 'modify':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES)
{
while($oObj = $this->m_oSet->Fetch())
{
$sHtml .= $oObj->GetModifyForm($oPage);
}
}
break;
case 'search':
$iSearchSectionId = 1;
$sStyle = (isset($aExtraParams['open']) && ($aExtraParams['open'] == 'true')) ? 'SearchDrawer' : 'SearchDrawer DrawerClosed';
$sHtml .= "<div id=\"Search_$iSearchSectionId\" class=\"$sStyle\">\n";
$sHtml .= "<h1>Search form for ".Metamodel::GetName($this->m_oSet->GetClass())."</h1>\n";
$oPage->add_ready_script("\$(\"#LnkSearch_$iSearchSectionId\").click(function() {\$(\"#Search_$iSearchSectionId\").slideToggle('normal'); $(\"#LnkSearch_$iSearchSectionId\").toggleClass('open');});");
$sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams);
$sHtml .= "</div>\n";
$sHtml .= "<div class=\"HRDrawer\"/></div>\n";
$sHtml .= "<div id=\"LnkSearch_$iSearchSectionId\" class=\"DrawerHandle\">Search</div>\n";
break;
case 'pie_chart':
$sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
$sFilter = $this->m_oFilter->ToOQL();
$sHtml .= "
<OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"
codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\"
WIDTH=\"400\"
HEIGHT=\"250\"
id=\"charts\"
ALIGN=\"\">
<PARAM NAME=movie VALUE=\"../images/charts.swf?library_path=../images/charts_library&xml_source=".urlencode("../pages/ajax.render.php?operation=pie_chart&group_by=$sGroupBy&encoding=oql&filter=".urlencode($sFilter))."\">
<PARAM NAME=\"quality\" VALUE=\"high\">
<PARAM NAME=\"bgcolor\" VALUE=\"#ffffff\">
<EMBED src=\"../images/charts.swf?library_path=../images/charts_library&xml_source=".urlencode("../pages/ajax.render.php?operation=pie_chart&group_by=$sGroupBy&encoding=oql&filter=".urlencode($sFilter))."\"
quality=\"high\"
bgcolor=\"#ffffff\"
WIDTH=\"400\"
HEIGHT=\"250\"
NAME=\"charts\"
ALIGN=\"\"
swLiveConnect=\"true\"
TYPE=\"application/x-shockwave-flash\"
PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">
</EMBED>
</OBJECT>
";
break;
case 'pie_chart_ajax':
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
$sHtml .= "<chart>\n";
$sHtml .= "<chart_type>3d pie</chart_type>\n";
$sHtml .= "<chart_data>\n";
$sHtml .= "<row>\n";
$sHtml .= "<null/>\n";
foreach($aGroupBy as $sValue => $void)
{
$sHtml .= "<string>$sValue</string>\n";
}
$sHtml .= "</row>\n";
$sHtml .= "<row>\n";
$sHtml .= "<string></string>\n";
foreach($aGroupBy as $void => $iCount)
{
$sHtml .= "<number>$iCount</number>\n";
}
$sHtml .= "</row>\n";
$sHtml .= "</chart_data>\n";
$sHtml .= "
<chart_value color='ffffff' alpha='90' font='arial' bold='true' size='10' position='inside' prefix='' suffix='' decimals='0' separator='' as_percentage='true' />
<draw>
<text color='000000' alpha='10' font='arial' rotation='0' bold='true' size='30' x='0' y='140' width='400' height='150' h_align='center' v_align='bottom'>|||||||||||||||||||||||||||||||||||||||||||||||</text>
</draw>
<legend_label layout='horizontal' bullet='circle' font='arial' bold='true' size='13' color='000000' alpha='85' />
<legend_rect fill_color='ffffff' fill_alpha='10' line_color='ffffff' line_alpha='50' line_thickness='0' />
<series_color>
<color>ddaa41</color>
<color>88dd11</color>
<color>4e62dd</color>
<color>ff8811</color>
<color>4d4d4d</color>
<color>5a4b6e</color>
<color>1188ff</color>
</series_color>
";
$sHtml .= "</chart>\n";
}
else
{
// Simply count the number of elements in the set
$iCount = $oSet->Count();
$sHtml .= "<chart>\n</chart>\n";
}
break;
case 'open_flash_chart':
static $iChartCounter = 0;
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$sTitle = isset($aExtraParams['chart_title']) ? $aExtraParams['chart_title'] : '';
$sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
$sFilter = $this->m_oFilter->ToOQL();
$sHtml .= "<script>
swfobject.embedSWF(\"../images/open-flash-chart.swf\", \"my_chart_{$iChartCounter}\", \"400\", \"400\",\"9.0.0\", \"expressInstall.swf\",
{\"data-file\":\"".urlencode("../pages/ajax.render.php?operation=open_flash_chart&params[group_by]=$sGroupBy&params[chart_type]=$sChartType&params[chart_title]=$sTitle&encoding=oql&filter=".urlencode($sFilter))."\"});
</script>\n";
$sHtml .= "<div id=\"my_chart_{$iChartCounter}\">Here goes the chart</div>\n";
$iChartCounter++;
break;
case 'open_flash_chart_ajax':
include './php-ofc-library/open-flash-chart.php';
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$oChart = new open_flash_chart();
switch($sChartType)
{
case 'bars':
$oChartElement = new bar_glass();
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
$aLabels = array();
foreach($aGroupBy as $sValue => $iValue)
{
$aData[] = $iValue;
$aLabels[] = $sValue;
}
$maxValue = max($aData);
$oYAxis = new y_axis();
$aMagicValues = array(1,2,5,10);
$iMultiplier = 1;
$index = 0;
$iTop = $aMagicValues[$index % count($aMagicValues)]*$iMultiplier;
while($maxValue > $iTop)
{
$index++;
$iTop = $aMagicValues[$index % count($aMagicValues)]*$iMultiplier;
if (($index % count($aMagicValues)) == 0)
{
$iMultiplier = $iMultiplier * 10;
}
}
//echo "oYAxis->set_range(0, $iTop, $iMultiplier);\n";
$oYAxis->set_range(0, $iTop, $iMultiplier);
$oChart->set_y_axis( $oYAxis );
$oChartElement->set_values( $aData );
$oXAxis = new x_axis();
$oXLabels = new x_axis_labels();
// set them vertical
$oXLabels->set_vertical();
// set the label text
$oXLabels->set_labels($aLabels);
// Add the X Axis Labels to the X Axis
$oXAxis->set_labels( $oXLabels );
$oChart->set_x_axis( $oXAxis );
}
break;
case 'pie':
default:
$oChartElement = new pie();
$oChartElement->set_start_angle( 35 );
$oChartElement->set_animate( true );
$oChartElement->set_tooltip( '#label# - #val# (#percent#)' );
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
foreach($aGroupBy as $sValue => $iValue)
{
$aData[] = new pie_value($iValue, $sValue);
}
$oChartElement->set_values( $aData );
$oChart->x_axis = null;
}
}
if (isset($aExtraParams['chart_title'])) //@@ BUG: not passed via ajax !!!
{
$oTitle = new title( $aExtraParams['chart_title'] );
$oChart->set_title( $oTitle );
}
$oChart->set_bg_colour('#FFFFFF');
$oChart->add_element( $oChartElement );
$sHtml = $oChart->toPrettyString();
break;
default:
// Unsupported style, do nothing.
$sHtml .= "Error: unsupported style of block: ".$this->m_sStyle;
}
return $sHtml;
}
}
/**
* Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects
*
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
* The list of cmdbObjects to be displayed into the block is defined by a filter
* Right now the type of display is either: list, count or details
* - list produces a table listing the objects
* - count produces a paragraphs with a sentence saying 'cont' objects found
* - details display (as table) the details of each object found (best if only one)
*/
class HistoryBlock extends DisplayBlock
{
public function GetRenderContent(web_page $oPage, $aExtraParams = array())
{
$sHtml = '';
// Add the extra params into the filter if they make sense for such a filter
$aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
foreach($aFilterCodes as $sFilterCode)
{
if (isset($aExtraParams[$sFilterCode]))
{
$this->m_oFilter->AddCondition($sFilterCode, $aExtraParams[$sFilterCode]); // Use the default 'loose' operator
}
}
$oSet = new CMDBObjectSet($this->m_oFilter, array('date'=>false));
$sHtml .= "<!-- filter: ".($this->m_oFilter->ToOQL())."-->\n";
switch($this->m_sStyle)
{
case 'toggle':
$oLatestChangeOp = $oSet->Fetch();
if (is_object($oLatestChangeOp))
{
global $oContext; // User Context.. should be statis instead of global...
// There is one change in the list... only when the object has been created !
$sDate = $oLatestChangeOp->GetAsHTML('date');
$oChange = $oContext->GetObject('CMDBChange', $oLatestChangeOp->Get('change'));
$sUserInfo = $oChange->GetAsHTML('userinfo');
$oSet->Load(); // Reset the pointer to the beginning of the set: there should be a better way to do this...
$sHtml .= $oPage->GetStartCollapsibleSection("Last modified on $sDate by $sUserInfo.");
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $oSet);
$sHtml .= $oPage->GetEndCollapsibleSection();
}
break;
default:
$sHtml .= parent::GetRenderContent($oPage, $aExtraParams);
}
return $sHtml;
}
}
class MenuBlock extends DisplayBlock
{
public function GetRenderContent(web_page $oPage, $aExtraParams = array())
{
$sHtml = '';
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$sClass = $this->m_oFilter->GetClass();
$oSet = new CMDBObjectSet($this->m_oFilter);
$sFilter = $this->m_oFilter->serialize();
$aActions = array();
$sUIPage = cmdbAbstractObject::ComputeUIPage($sClass);
switch($oSet->Count())
{
case 0:
// No object in the set, the only possible action is "new"
$bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet);
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New', 'url' => "../page/$sUIPage?operation=new&class=$sClass&$sContext"); }
break;
case 1:
$oObj = $oSet->Fetch();
$id = $oObj->GetKey();
$bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet);
$bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet);
$bIsBulkModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet);
$bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet);
// Just one object in the set, possible actions are "new / clone / modify and delete"
if (isset($aExtraParams['linkage']))
{
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "#"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "#"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All', 'url' => "#"); }
if ($bIsModifyAllowed | $bIsDeleteAllowed) { $aActions[] = array ('label' => 'Manage Links...', 'url' => "#"); }
}
else
{
$aActions[] = array ('label' => 'eMail', 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("http://localhost:81/pages/UI.php?operation=search&filter=$sFilter&$sContext"));
$aActions[] = array ('label' => 'CSV Export', 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext");
$aActions[] = array ('label' => 'Bookmark...', 'url' => "../pages/ajax.render.php?operation=create&class=$sClass&filter=$sFilter", 'class' => 'jqmTrigger');
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext"); }
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'Clone...', 'url' => "../pages/$sUIPage?operation=clone&class=$sClass&id=$id&$sContext"); }
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'Modify...', 'url' => "../pages/$sUIPage?operation=modify&class=$sClass&id=$id&$sContext"); }
if ($bIsDeleteAllowed) { $aActions[] = array ('label' => 'Delete', 'url' => "../pages/$sUIPage?operation=delete&class=$sClass&id=$id&$sContext"); }
}
$aTransitions = $oObj->EnumTransitions();
$aStimuli = Metamodel::EnumStimuli($sClass);
foreach($aTransitions as $sStimulusCode => $aTransitionDef)
{
$iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet);
switch($iActionAllowed)
{
case UR_ALLOWED_YES:
$aActions[] = array('label' => $aStimuli[$sStimulusCode]->Get('label'), 'url' => "../pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id&$sContext");
break;
case UR_ALLOWED_DEPENDS:
$aActions[] = array('label' => $aStimuli[$sStimulusCode]->Get('label').' (*)', 'url' => "../pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id&$sContext");
break;
default:
// Do nothing
}
}
//print_r($aTransitions);
break;
default:
// Check rights
// New / Modify
$bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet);
$bIsBulkModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet);
$bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet);
if (isset($aExtraParams['linkage']))
{
$bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet);
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "#"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "#"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All', 'url' => "#"); }
if ($bIsModifyAllowed | $bIsDeleteAllowed) { $aActions[] = array ('label' => 'Manage Links...', 'url' => "#"); }
}
else
{
// many objects in the set, possible actions are: new / modify all / delete all
$aActions[] = array ('label' => 'eMail', 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("http://localhost:81/pages/UI.php?operation=search&filter=$sFilter&$sContext"));
$aActions[] = array ('label' => 'CSV Export', 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext");
$aActions[] = array ('label' => 'Bookmark...', 'url' => "../pages/ajax.render.php?operation=create&class=$sClass&filter=$sFilter", 'class' => 'jqmTrigger');
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "../pages/$sUIPage?operation=modify_all&filter=$sFilter&$sContext"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Delete All', 'url' => "../pages/$sUIPage?operation=delete_all&filter=$sFilter&$sContext"); }
}
}
$sHtml .= "<div class=\"jd_menu_itop\"><ul class=\"jd_menu jd_menu_itop\">\n<li>Actions\n<ul>\n";
foreach ($aActions as $aAction)
{
$sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : "";
$sHtml .= "<li><a href=\"{$aAction['url']}\"$sClass>{$aAction['label']}</a></li>\n<li>\n";
}
$sHtml .= "</ul>\n</li>\n</ul></div>\n";
$oPage->add_ready_script("$(\"ul.jd_menu\").jdMenu();\n");
return $sHtml;
}
}
?>

View File

@@ -0,0 +1,414 @@
<?php
require_once("../application/nicewebpage.class.inc.php");
require_once("../application/usercontext.class.inc.php");
require_once("../application/applicationcontext.class.inc.php");
/**
* Web page with some associated CSS and scripts (jquery) for a fancier display
*/
class iTopWebPage extends nice_web_page
{
private $m_sMenu;
private $m_currentOrganization;
private $m_aTabs;
private $m_sCurrentTabContainer;
private $m_sCurrentTab;
public function __construct($sTitle, $currentOrganization)
{
parent::__construct($sTitle);
$this->m_sCurrentTabContainer = '';
$this->m_sCurrentTab = '';
$this->m_aTabs = array();
$this->m_sMenu = "";
$oAppContext = new ApplicationContext();
$sExtraParams = $oAppContext->GetForLink();
$this->add_header("Content-type: text/html; charset=utf-8");
$this->add_header("Cache-control: no-cache");
$this->m_currentOrganization = $currentOrganization;
$this->add_linked_script("../js/jquery.dimensions.js");
$this->add_linked_script("../js/splitter.js");
$this->add_linked_script("../js/jquery.tablehover.js");
$this->add_linked_script("../js/jquery.treeview.js");
$this->add_linked_script("../js/jquery.autocomplete.js");
$this->add_linked_script("../js/jquery.bgiframe.js");
$this->add_linked_script("../js/jquery.jdMenu.js");
$this->add_linked_script("../js/date.js");
$this->add_linked_script("../js/jquery.date.picker.js");
$this->add_linked_script("../js/jquery.tablesorter.min.js");
//$this->add_linked_script("../js/jquery-ui-personalized-1.5.3.js");
$this->add_linked_script("../js/swfobject.js");
$this->add_linked_stylesheet("../css/jquery.treeview.css");
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
$this->add_linked_stylesheet("../css/date.picker.css");
$this->add_ready_script(
<<<EOF
// Vertical splitter. The min/max/starting sizes for the left (A) pane
// are set here. All values are in pixels.
$("#MySplitter").splitter({
type: "v",
minA: 100, initA: 250, maxA: 500,
accessKey: "|"
});
// Horizontal splitter, nested in the right pane of the vertical splitter.
if ( $("#TopPane").length > 0)
{
$("#RightPane").splitter({
type: "h" //,
//minA: 100, initA: 150, maxA: 500,
//accessKey: "_"
});
}
// Manually set the outer splitter's height to fill the browser window.
// This must be re-done any time the browser window is resized.
$(window).bind("resize", function(){
var ms = $("#MySplitter");
var top = ms.offset().top; // from dimensions.js
var wh = $(window).height();
// Account for margin or border on the splitter container
var mrg = parseInt(ms.css("marginBottom")) || 0;
var brd = parseInt(ms.css("borderBottomWidth")) || 0;
ms.css("height", (wh-top-mrg-brd)+"px");
// IE fires resize for splitter; others don't so do it here
if ( !jQuery.browser.msie )
ms.trigger("resize");
}).trigger("resize");
var ms = $("#MySplitter");
ms.trigger("resize");
if ( $("#TopPane").length > 0)
{
$("#RightPane").trigger("resize");
}
$("#tabbedContent > ul").tabs( 1, { fxFade: true, fxSpeed: 'fast' } ); // tabs
$("table.listResults").tableHover(); // hover tables
$(".listResults").tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables
$(".date-pick").datePicker( {clickInput: false, createButton: true, startDate: '2000-01-01'} ); // Date picker
$('#ModalDlg').jqm({ajax: '@href', trigger: 'a.jqmTrigger', overlay:70, modal:true, toTop:true}); // jqModal Window
//$('.display_block').draggable(); // make the blocks draggable
EOF
);
$this->add_script("
// For automplete
function findValue(li) {
if( li == null ) return alert(\"No match!\");
// if coming from an AJAX call, let's use the CityId as the value
if( !!li.extra ) var sValue = li.extra[0];
// otherwise, let's just display the value in the text box
else var sValue = li.selectValue;
//alert(\"The value you selected was: \" + sValue);
}
function selectItem(li) {
findValue(li);
}
function formatItem(row) {
return row[0];
}
function goBack()
{
window.history.back();
}
");
$this->DisplayMenu();
}
public function AddToMenu($sHtml)
{
$this->m_sMenu .= $sHtml;
}
public function DisplayMenu()
{
// Combo box to select the organization
$this->AddToMenu("<div id=\"OrganizationSelection\">
<form style=\"display:inline\"><select style=\"width:150px;font-size:x-small\" name=\"org_id\" \"title=\"Pick an organization\" onChange=\"this.form.submit();\">\n");
// List of visible Organizations
$oContext = new UserContext();
$oSearchFilter = $oContext->NewFilter("bizOrganization");
$oSet = new CMDBObjectSet($oSearchFilter);
$sSelected = ($this->m_currentOrganization == '') ? ' selected' : '';
$this->AddToMenu("<option value=\"\"$sSelected> All Organizations </option>");
if ($oSet->Count() > 0)
while($oOrg = $oSet->Fetch())
{
if ($this->m_currentOrganization == $oOrg->GetKey())
{
$oCurrentOrganization = $oOrg;
$sSelected = " selected";
}
else
{
$sSelected = "";
}
$this->AddToMenu("<option value=\"".$oOrg->GetKey()."\"$sSelected>".$oOrg->Get('name')."</option>\n");
}
$this->AddToMenu("</select></form>\n");
$this->AddToMenu("</div>\n");
$this->AddToMenu("<ul id=\"browser\" class=\"dir\">\n");
$oAppContext = new ApplicationContext();
// Display the menu
// 1) Application defined menus
$oSearchFilter = $oContext->NewFilter("menuNode");
$oSearchFilter->AddCondition('parent_id', 0, '=');
$oSearchFilter->AddCondition('type', 'application', '=');
// There may be more criteria added later to have a specific menu based on the user's profile
$oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true));
while ($oRootMenuNode = $oSet->Fetch())
{
$oRootMenuNode->DisplayMenu($this, 'application', $oAppContext->GetAsHash());
}
// 2) User defined menus (Bookmarks)
$oSearchFilter = $oContext->NewFilter("menuNode");
$oSearchFilter->AddCondition('parent_id', 0, '=');
$oSearchFilter->AddCondition('type', 'user', '=');
$oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '=');
// There may be more criteria added later to have a specific menu based on the user's profile
$oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true));
while ($oRootMenuNode = $oSet->Fetch())
{
$oRootMenuNode->DisplayMenu($this, 'user', $oAppContext->GetAsHash());
}
$this->AddToMenu("</ul>\n");
}
/**
* Outputs (via some echo) the complete HTML page by assembling all its elements
*/
public function output()
{
foreach($this->a_headers as $s_header)
{
header($s_header);
}
$s_captured_output = ob_get_contents();
ob_end_clean();
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
echo "<html>\n";
echo "<head>\n";
echo "<title>{$this->s_title}</title>\n";
foreach($this->a_linked_scripts as $s_script)
{
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
}
if (count($this->m_aReadyScripts)>0)
{
$this->add_script("\$(document).ready(function() {\n".implode("\n", $this->m_aReadyScripts)."\n});");
}
if (count($this->a_scripts)>0)
{
echo "<script type=\"text/javascript\">\n";
foreach($this->a_scripts as $s_script)
{
echo "$s_script\n";
}
echo "</script>\n";
}
foreach($this->a_linked_stylesheets as $a_stylesheet)
{
if ($a_stylesheet['condition'] != "")
{
echo "<!--[if {$a_stylesheet['condition']}]>\n";
}
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$a_stylesheet['link']}\" />\n";
if ($a_stylesheet['condition'] != "")
{
echo "<![endif]-->\n";
}
}
if (count($this->a_styles)>0)
{
echo "<style>\n";
foreach($this->a_styles as $s_style)
{
echo "$s_style\n";
}
echo "</style>\n";
}
echo "<link rel=\"search\" type=\"application/opensearchdescription+xml\" title=\"iTop\" href=\"./opensearch.xml.php\">\n";
echo "</head>\n";
echo "<body>\n";
// Display the header
echo "<div id=\"Header\">\n";
echo "<div class=\"iTopLogo\"><span>iTop</span></div>\n";
//echo "<div id=\"GlobalSearch\"><div style=\"border: 1px solid #999; padding:1px; background-color:#fff;\"><img src=\"/images/magnifier.gif\"/><input style=\"border:0\" type=\"text\" size=\"15\" title=\"Global Search\"></input></div></div>\n";
$sText = Utils::ReadParam('text', '');
$sOnClick = "";
if (empty($sText))
{
// if no search text is supplied then
// 1) the search text is filled with "your search"
// 2) clicking on it will erase it
$sText = "Your search";
$sOnClick = " onclick=\"this.value='';this.onclick=null;\"";
}
echo "<div id=\"OrganizationSelection\" style=\"position:absolute; top:18px; right:16px; width:400px;\">";
echo "<form action=\"../pages/UI.php\" style=\"display:inline\"><div style=\"padding:1px; background-color:#fff;display:inline;\"><img src=\"../images/magnifier.gif\"/><input style=\"border:0\" type=\"text\" size=\"15\" title=\"Global Search\" name=\"text\" value=\"$sText\"$sOnClick></input></div><input type=\"Submit\" value=\"Search\">
<input type=\"hidden\" name=\"operation\" value=\"full_text\"></form>\n";
echo "</div>\n";
echo "</div>\n";
// Display the menu
echo "<div id=\"MySplitter\">\n";
echo " <div id=\"LeftPane\">\n";
echo $this->m_sMenu;
echo " </div> <!-- LeftPane -->\n";
echo "<div id=\"RightPane\">\n";
// Render the tabs in the page (if any)
foreach($this->m_aTabs as $sTabContainerName => $m_aTabs)
{
$sTabs = '';
if (count($m_aTabs) > 0)
{
$sTabs = "<!-- tabs -->\n<div id=\"tabbedContent\" class=\"light\">\n";
$sTabs .= "<ul>\n";
// Display the unordered list that will be rendered as the tabs
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<li><a href=\"#fragment_$i\" class=\"tab\"><span>".htmlentities($sTabName)."</span></a></li>\n";
$i++;
}
$sTabs .= "</ul>\n";
// Now add the content of the tabs themselves
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<div id=\"fragment_$i\">".$sTabContent."</div>\n";
$i++;
}
$sTabs .= "</div>\n<!-- end of tabs-->\n";
}
$this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content);
}
// Display the page's content
echo $this->s_content;
// Add the captured output
if (trim($s_captured_output) != "")
{
echo "<div class=\"raw_output\">$s_captured_output</div>\n";
}
echo "<div class=\"jqmWindow\" id=\"ex2\">Please wait...</div>\n"; // jqModal Window
echo "</div> <!-- RightPane -->\n";
echo "</div> <!-- Splitter -->\n";
echo "<div class=\"jqmWindow\" id=\"ModalDlg\"></div>";
echo "</body>\n";
echo "</html>\n";
}
public function AddTabContainer($sTabContainer)
{
$this->m_aTabs[$sTabContainer] = array();
$this->add("\$Tabs:$sTabContainer\$");
}
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
{
if (!isset($this->m_aTabs[$sTabContainer][$sTabLabel]))
{
// Set the content of the tab
$this->m_aTabs[$sTabContainer][$sTabLabel] = $sHtml;
}
else
{
// Append to the content of the tab
$this->m_aTabs[$sTabContainer][$sTabLabel] .= $sHtml;
}
}
public function SetCurrentTabContainer($sTabContainer = '')
{
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
$this->m_sCurrentTabContainer = $sTabContainer;
return $sPreviousTabContainer;
}
public function SetCurrentTab($sTabLabel = '')
{
$sPreviousTab = $this->m_sCurrentTab;
$this->m_sCurrentTab = $sTabLabel;
return $sPreviousTab;
}
public function StartCollapsibleSection($sSectionLabel, $bOpen = false)
{
$this->add($this->GetStartCollapsibleSection($sSectionLabel, $bOpen));
}
public function GetStartCollapsibleSection($sSectionLabel, $bOpen = false)
{
$sHtml = '';
static $iSectionId = 0;
$sHtml .= "<a id=\"LnkCollapse_$iSectionId\" class=\"CollapsibleLabel\" href=\"#\">$sSectionLabel</a></br>\n";
$sStyle = $bOpen ? '' : 'style="display:none" ';
$sHtml .= "<div id=\"Collapse_$iSectionId\" $sStyle>";
$this->add_ready_script("\$(\"#LnkCollapse_$iSectionId\").click(function() {\$(\"#Collapse_$iSectionId\").slideToggle('normal'); $(\"#LnkCollapse_$iSectionId\").toggleClass('open');});");
//$this->add_ready_script("$('#LnkCollapse_$iSectionId').hide();");
$iSectionId++;
return $sHtml;
}
public function EndCollapsibleSection()
{
$this->add($this->GetEndCollapsibleSection());
}
public function GetEndCollapsibleSection()
{
return "</div>";
}
public function add($sHtml)
{
if (!empty($this->m_sCurrentTabContainer) && !empty($this->m_sCurrentTab))
{
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
}
else
{
parent::add($sHtml);
}
}
/*
public function AddSearchForm($sClassName, $bOpen = false)
{
$iSearchSectionId = 0;
$sStyle = $bOpen ? 'SearchDrawer' : 'SearchDrawer DrawerClosed';
$this->add("<div id=\"Search_$iSearchSectionId\" class=\"$sStyle\">\n");
$this->add("<h1>Search form for ".Metamodel::GetName($sClassName)."</h1>\n");
$this->add_ready_script("\$(\"#LnkSearch_$iSearchSectionId\").click(function() {\$(\"#Search_$iSearchSectionId\").slideToggle('normal'); $(\"#LnkSearch_$iSearchSectionId\").toggleClass('open');});");
$oFilter = new DBObjectSearch($sClassName);
$sFilter = $oFilter->serialize();
$oSet = new CMDBObjectSet($oFilter);
cmdbAbstractObject::DisplaySearchForm($this, $oSet, array('operation' => 'search', 'filter' => $sFilter, 'search_form' => true));
$this->add("</div>\n");
$this->add("<div class=\"HRDrawer\"/></div>\n");
$this->add("<div id=\"LnkSearch_$iSearchSectionId\" class=\"DrawerHandle\">Search</div>\n");
$iSearchSectionId++;
}
*/
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
<?php
/**
* UserRights
* User management API
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class UserRightException extends CoreException
{
}
define('UR_ALLOWED_NO', 0);
define('UR_ALLOWED_YES', 1);
define('UR_ALLOWED_DEPENDS', 2);
define('UR_ACTION_READ', 1); // View an object
define('UR_ACTION_MODIFY', 2); // Create/modify an object/attribute
define('UR_ACTION_DELETE', 3); // Delete an object
define('UR_ACTION_BULK_READ', 4); // Export multiple objects
define('UR_ACTION_BULK_MODIFY', 5); // Create/modify multiple objects
define('UR_ACTION_BULK_DELETE', 6); // Delete multiple objects
define('UR_ACTION_APPLICATION_DEFINED', 10000); // Application specific actions (CSV import, View schema...)
/**
* User management module API
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class UserRightsAddOnAPI
{
abstract public function Setup(); // initial installation
abstract public function Init(); // loads data (possible optimizations)
abstract public function CheckCredentials($iUserId, $sPassword); // returns the id of the user or false
abstract public function GetFilter($iUserId, $sClass); // returns a filter object
abstract public function IsActionAllowed($iUserId, $sClass, $iActionCode, dbObjectSet $aInstances);
abstract public function IsStimulusAllowed($iUserId, $sClass, $sStimulusCode, dbObjectSet $aInstances);
abstract public function IsActionAllowedOnAttribute($iUserId, $sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances);
}
/**
* User management core API
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class UserRights
{
protected static $m_oAddOn;
protected static $m_sUser;
protected static $m_sRealUser;
protected static $m_iUserId;
protected static $m_iRealUserId;
public static function SelectModule($sModuleName)
{
if (!class_exists($sModuleName))
{
trigger_error("Could not select this module, '$sModuleName' in not a valid class name", E_USER_ERROR);
return;
}
if (!is_subclass_of($sModuleName, 'UserRightsAddOnAPI'))
{
trigger_error("Could not select this module, the class '$sModuleName' is not derived from UserRightsAddOnAPI", E_USER_ERROR);
return;
}
self::$m_oAddOn = new $sModuleName;
self::$m_oAddOn->Init();
self::$m_sUser = '';
self::$m_sRealUser = '';
self::$m_iUserId = 0;
self::$m_iRealUserId = 0;
}
// Installation: create the very first user
public static function CreateAdministrator($sAdminUser, $sAdminPwd)
{
return self::$m_oAddOn->CreateAdministrator($sAdminUser, $sAdminPwd);
}
// Installation (e.g: give default values for users)
public static function Setup()
{
// to be discussed...
return self::$m_oAddOn->Setup();
}
protected static function IsLoggedIn()
{
return (!empty(self::$m_sUser));
}
public static function Login($sName, $sPassword)
{
self::$m_iUserId = self::$m_oAddOn->CheckCredentials($sName, $sPassword);
if ( self::$m_iUserId !== false )
{
self::$m_sUser = $sName;
self::$m_iRealUserId = self::$m_iUserId;
self::$m_sRealUser = $sName;
return true;
}
else
{
return false;
}
}
public static function Impersonate($sName, $sPassword)
{
if (!self::CheckLogin()) return false;
self::$m_iRealUserId = self::$m_oAddOn->CheckCredentials($sName, $sPassword);
if ( self::$m_iRealUserId !== false)
{
self::$m_sUser = $sName;
return true;
}
else
{
return false;
}
}
public static function GetUser()
{
return self::$m_sUser;
}
public static function GetUserId()
{
return self::$m_iUserId;
}
public static function GetRealUser()
{
return self::$m_sRealUser;
}
public static function GetRealUserId()
{
return self::$m_iRealUserId;
}
protected static function CheckLogin()
{
if (!self::IsLoggedIn())
{
//throw new UserRightException('No user logged in', array());
return false;
}
return true;
}
public static function GetFilter($sClass)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return new DBObjectSearch($sClass);
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->GetFilter(self::$m_iUserId, $sClass);
}
public static function IsActionAllowed($sClass, $iActionCode, dbObjectSet $aInstances)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return true;
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->IsActionAllowed(self::$m_iUserId, $sClass, $iActionCode, $aInstances);
}
public static function IsStimulusAllowed($sClass, $sStimulusCode, dbObjectSet $aInstances)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return true;
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->IsStimulusAllowed(self::$m_iUserId, $sClass, $sStimulusCode, $aInstances);
}
public static function IsActionAllowedOnAttribute($sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return true;
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->IsActionAllowedOnAttribute(self::$m_iUserId, $sClass, $sAttCode, $iActionCode, $aInstances);
}
}
?>

View File

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 559 B

View File

Before

Width:  |  Height:  |  Size: 764 B

After

Width:  |  Height:  |  Size: 764 B

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