From bcaa41e5e4eb2a40c59aa0f99f10add1ff2f1d11 Mon Sep 17 00:00:00 2001
From: ArmandBahi <armand.bahi@veremes.com>
Date: Wed, 26 Sep 2018 15:41:14 +0200
Subject: [PATCH] reset from svn

---
 client/modules/vitis/data/proj.json           |   22 +
 .../configuration_vitis_configuration.json    | 1029 ++++++++++
 .../vitis/forms/logs/logs_vitis_log.json      |   72 +
 .../vitis/forms/user/user_vitis_user.js       |   66 +
 .../vitis/forms/user/user_vitis_user.json     |  348 ++++
 .../users/active_directory_connection.json    |   79 +
 .../users/search_active_directory_group.json  |   52 +
 .../users/search_active_directory_person.json |   82 +
 .../forms/users/users_vitis_billinggroup.json |  223 +++
 .../vitis/forms/users/users_vitis_domain.json |  497 +++++
 .../vitis/forms/users/users_vitis_group.json  |  253 +++
 .../forms/users/users_vitis_privilege.json    |  190 ++
 .../vitis/forms/users/users_vitis_users.json  |  991 ++++++++++
 client/modules/vitis/images/administrator.png |  Bin 0 -> 746 bytes
 client/modules/vitis/images/button_green.gif  |  Bin 0 -> 600 bytes
 client/modules/vitis/images/button_red.gif    |  Bin 0 -> 609 bytes
 client/modules/vitis/images/user.png          |  Bin 0 -> 741 bytes
 .../controllers/activeDirectoryTreeCtrl.js    |  251 +++
 .../vitis/javascript/controllers/logsCtrl.js  |  144 ++
 .../controllers/versionConfigurationCtrl.js   |   64 +
 .../controllers/webServiceHelpCtrl.js         |   19 +
 .../controllers/websocketConfigurationCtrl.js |  102 +
 client/modules/vitis/javascript/deps.js       |   19 +
 .../directives/activeDirectoryTreeDrtv.js     |   98 +
 .../vitis/javascript/directives/logsDrtv.js   |  171 ++
 .../directives/phpInfoConfigurationDrtv.js    |   38 +
 .../directives/versionConfigurationDrtv.js    |   17 +
 .../directives/webServiceHelpDrtv.js          |   28 +
 .../directives/websocketConfigurationDrtv.js  |   17 +
 .../modules/vitis/javascript/script_module.js | 1696 +++++++++++++++++
 client/modules/vitis/lang/lang-en.json        |  330 ++++
 client/modules/vitis/lang/lang-fr.json        |  332 ++++
 .../vitis/less/activeDirectoryTree.less       |   78 +
 client/modules/vitis/less/logs.less           |   78 +
 client/modules/vitis/less/main.less           |   10 +
 .../vitis/less/phpInfoConfiguration.less      |   88 +
 .../vitis/less/updateConfiguration.less       |   11 +
 client/modules/vitis/less/users.less          |   15 +
 .../vitis/less/versionConfiguration.less      |   50 +
 client/modules/vitis/less/webServiceHelp.less |    8 +
 .../templates/activeDirectoryTreeLeftTpl.html |   11 +
 .../activeDirectoryTreeRightTpl.html          |    1 +
 .../modules/vitis/templates/logsLeftTpl.html  |    4 +
 .../modules/vitis/templates/logsRightTpl.html |   16 +
 .../templates/phpInfoConfigurationTpl.html    |    3 +
 .../templates/updateConfigurationTpl.html     |    1 +
 .../templates/versionConfigurationTpl.html    |   70 +
 .../vitis/templates/webServiceHelpTpl.html    |    1 +
 .../templates/websocketConfigurationTpl.html  |   46 +
 vas/rest/conf/constants.inc                   |   10 +
 vas/rest/conf/php_conf.inc                    |   14 +
 vas/rest/conf/properties.inc                  |   78 +
 vas/rest/conf/properties_domain.inc           |    3 +
 vas/rest/conf/properties_post.inc             |   18 +
 vas/rest/conf/properties_server.inc           |   50 +
 vas/rest/conf/selected_properties.inc         |  143 ++
 vas/rest/conf/version.inc                     |    7 +
 vas/rest/ws/vitis/Accounts.class.inc          |  662 +++++++
 vas/rest/ws/vitis/Accounts.class.mail.inc     |  617 ++++++
 vas/rest/ws/vitis/Accounts.class.sql.inc      |    9 +
 vas/rest/ws/vitis/Action.class.inc            |   35 +
 vas/rest/ws/vitis/Actions.class.inc           |   62 +
 vas/rest/ws/vitis/ActiveDirectory.class.inc   |  744 ++++++++
 vas/rest/ws/vitis/BillingGroup.class.inc      |  120 ++
 vas/rest/ws/vitis/BillingGroups.class.inc     |  293 +++
 vas/rest/ws/vitis/Column.class.inc            |   35 +
 vas/rest/ws/vitis/Columns.class.inc           |   59 +
 vas/rest/ws/vitis/Database.class.inc          |   34 +
 vas/rest/ws/vitis/Domain.class.inc            |   93 +
 vas/rest/ws/vitis/Domains.class.inc           |  530 ++++++
 vas/rest/ws/vitis/FormatDate.class.inc        |   78 +
 vas/rest/ws/vitis/FormatDates.class.inc       |  128 ++
 vas/rest/ws/vitis/GenericQuery.class.inc      |   42 +
 vas/rest/ws/vitis/GenericQuerys.class.inc     |  888 +++++++++
 vas/rest/ws/vitis/GenericQuerys.class.sql.inc |   14 +
 vas/rest/ws/vitis/Group.class.inc             |  119 ++
 vas/rest/ws/vitis/Groups.class.inc            |  393 ++++
 vas/rest/ws/vitis/Logs.class.inc              |  540 ++++++
 vas/rest/ws/vitis/Mode.class.inc              |   86 +
 vas/rest/ws/vitis/Modes.class.inc             |  233 +++
 vas/rest/ws/vitis/PhpInfo.class.inc           |  100 +
 vas/rest/ws/vitis/PrivateToken.class.inc      |  289 +++
 vas/rest/ws/vitis/Privilege.class.inc         |  115 ++
 vas/rest/ws/vitis/Privileges.class.inc        |  280 +++
 vas/rest/ws/vitis/Properties.class.inc        |  427 +++++
 vas/rest/ws/vitis/PublicToken.class.inc       |  105 +
 vas/rest/ws/vitis/Ressources.class.inc        |  140 ++
 vas/rest/ws/vitis/Schema.class.inc            |   34 +
 vas/rest/ws/vitis/SmtpServer.class.inc        |  123 ++
 vas/rest/ws/vitis/Tab.class.inc               |   80 +
 vas/rest/ws/vitis/Table.class.inc             |   34 +
 vas/rest/ws/vitis/Tabs.class.inc              |  130 ++
 vas/rest/ws/vitis/TimeZone.class.inc          |   78 +
 vas/rest/ws/vitis/TimeZones.class.inc         |  128 ++
 vas/rest/ws/vitis/User.class.inc              |  189 ++
 vas/rest/ws/vitis/Users.class.inc             |  746 ++++++++
 vas/rest/ws/vitis/Versions.class.inc          |  204 ++
 vas/rest/ws/vitis/Vitis.class.inc             | 1507 +++++++++++++++
 vas/rest/ws/vitis/Vitis.class.sql.inc         |   60 +
 vas/rest/ws/vitis/VitisSection.class.inc      |  112 ++
 vas/rest/ws/vitis/VitisSections.class.inc     |  135 ++
 vas/rest/ws/vitis/WebServices.class.inc       |  452 +++++
 vas/rest/ws/vitis/overview.phtml              |   26 +
 vas/sql/sqlQueries.xml                        |  948 +++++++++
 104 files changed, 20300 insertions(+)
 create mode 100755 client/modules/vitis/data/proj.json
 create mode 100755 client/modules/vitis/forms/configuration/configuration_vitis_configuration.json
 create mode 100755 client/modules/vitis/forms/logs/logs_vitis_log.json
 create mode 100755 client/modules/vitis/forms/user/user_vitis_user.js
 create mode 100755 client/modules/vitis/forms/user/user_vitis_user.json
 create mode 100755 client/modules/vitis/forms/users/active_directory_connection.json
 create mode 100755 client/modules/vitis/forms/users/search_active_directory_group.json
 create mode 100755 client/modules/vitis/forms/users/search_active_directory_person.json
 create mode 100755 client/modules/vitis/forms/users/users_vitis_billinggroup.json
 create mode 100755 client/modules/vitis/forms/users/users_vitis_domain.json
 create mode 100755 client/modules/vitis/forms/users/users_vitis_group.json
 create mode 100755 client/modules/vitis/forms/users/users_vitis_privilege.json
 create mode 100755 client/modules/vitis/forms/users/users_vitis_users.json
 create mode 100755 client/modules/vitis/images/administrator.png
 create mode 100755 client/modules/vitis/images/button_green.gif
 create mode 100755 client/modules/vitis/images/button_red.gif
 create mode 100755 client/modules/vitis/images/user.png
 create mode 100755 client/modules/vitis/javascript/controllers/activeDirectoryTreeCtrl.js
 create mode 100755 client/modules/vitis/javascript/controllers/logsCtrl.js
 create mode 100755 client/modules/vitis/javascript/controllers/versionConfigurationCtrl.js
 create mode 100755 client/modules/vitis/javascript/controllers/webServiceHelpCtrl.js
 create mode 100755 client/modules/vitis/javascript/controllers/websocketConfigurationCtrl.js
 create mode 100755 client/modules/vitis/javascript/deps.js
 create mode 100755 client/modules/vitis/javascript/directives/activeDirectoryTreeDrtv.js
 create mode 100755 client/modules/vitis/javascript/directives/logsDrtv.js
 create mode 100755 client/modules/vitis/javascript/directives/phpInfoConfigurationDrtv.js
 create mode 100755 client/modules/vitis/javascript/directives/versionConfigurationDrtv.js
 create mode 100755 client/modules/vitis/javascript/directives/webServiceHelpDrtv.js
 create mode 100755 client/modules/vitis/javascript/directives/websocketConfigurationDrtv.js
 create mode 100755 client/modules/vitis/javascript/script_module.js
 create mode 100755 client/modules/vitis/lang/lang-en.json
 create mode 100755 client/modules/vitis/lang/lang-fr.json
 create mode 100755 client/modules/vitis/less/activeDirectoryTree.less
 create mode 100755 client/modules/vitis/less/logs.less
 create mode 100755 client/modules/vitis/less/main.less
 create mode 100755 client/modules/vitis/less/phpInfoConfiguration.less
 create mode 100755 client/modules/vitis/less/updateConfiguration.less
 create mode 100755 client/modules/vitis/less/users.less
 create mode 100755 client/modules/vitis/less/versionConfiguration.less
 create mode 100755 client/modules/vitis/less/webServiceHelp.less
 create mode 100755 client/modules/vitis/templates/activeDirectoryTreeLeftTpl.html
 create mode 100755 client/modules/vitis/templates/activeDirectoryTreeRightTpl.html
 create mode 100755 client/modules/vitis/templates/logsLeftTpl.html
 create mode 100755 client/modules/vitis/templates/logsRightTpl.html
 create mode 100755 client/modules/vitis/templates/phpInfoConfigurationTpl.html
 create mode 100755 client/modules/vitis/templates/updateConfigurationTpl.html
 create mode 100755 client/modules/vitis/templates/versionConfigurationTpl.html
 create mode 100755 client/modules/vitis/templates/webServiceHelpTpl.html
 create mode 100755 client/modules/vitis/templates/websocketConfigurationTpl.html
 create mode 100755 vas/rest/conf/constants.inc
 create mode 100755 vas/rest/conf/php_conf.inc
 create mode 100755 vas/rest/conf/properties.inc
 create mode 100755 vas/rest/conf/properties_domain.inc
 create mode 100755 vas/rest/conf/properties_post.inc
 create mode 100644 vas/rest/conf/properties_server.inc
 create mode 100755 vas/rest/conf/selected_properties.inc
 create mode 100755 vas/rest/conf/version.inc
 create mode 100755 vas/rest/ws/vitis/Accounts.class.inc
 create mode 100755 vas/rest/ws/vitis/Accounts.class.mail.inc
 create mode 100755 vas/rest/ws/vitis/Accounts.class.sql.inc
 create mode 100755 vas/rest/ws/vitis/Action.class.inc
 create mode 100755 vas/rest/ws/vitis/Actions.class.inc
 create mode 100755 vas/rest/ws/vitis/ActiveDirectory.class.inc
 create mode 100755 vas/rest/ws/vitis/BillingGroup.class.inc
 create mode 100755 vas/rest/ws/vitis/BillingGroups.class.inc
 create mode 100755 vas/rest/ws/vitis/Column.class.inc
 create mode 100755 vas/rest/ws/vitis/Columns.class.inc
 create mode 100755 vas/rest/ws/vitis/Database.class.inc
 create mode 100755 vas/rest/ws/vitis/Domain.class.inc
 create mode 100755 vas/rest/ws/vitis/Domains.class.inc
 create mode 100755 vas/rest/ws/vitis/FormatDate.class.inc
 create mode 100755 vas/rest/ws/vitis/FormatDates.class.inc
 create mode 100755 vas/rest/ws/vitis/GenericQuery.class.inc
 create mode 100755 vas/rest/ws/vitis/GenericQuerys.class.inc
 create mode 100755 vas/rest/ws/vitis/GenericQuerys.class.sql.inc
 create mode 100755 vas/rest/ws/vitis/Group.class.inc
 create mode 100755 vas/rest/ws/vitis/Groups.class.inc
 create mode 100755 vas/rest/ws/vitis/Logs.class.inc
 create mode 100755 vas/rest/ws/vitis/Mode.class.inc
 create mode 100755 vas/rest/ws/vitis/Modes.class.inc
 create mode 100755 vas/rest/ws/vitis/PhpInfo.class.inc
 create mode 100644 vas/rest/ws/vitis/PrivateToken.class.inc
 create mode 100755 vas/rest/ws/vitis/Privilege.class.inc
 create mode 100755 vas/rest/ws/vitis/Privileges.class.inc
 create mode 100755 vas/rest/ws/vitis/Properties.class.inc
 create mode 100755 vas/rest/ws/vitis/PublicToken.class.inc
 create mode 100755 vas/rest/ws/vitis/Ressources.class.inc
 create mode 100755 vas/rest/ws/vitis/Schema.class.inc
 create mode 100755 vas/rest/ws/vitis/SmtpServer.class.inc
 create mode 100755 vas/rest/ws/vitis/Tab.class.inc
 create mode 100755 vas/rest/ws/vitis/Table.class.inc
 create mode 100755 vas/rest/ws/vitis/Tabs.class.inc
 create mode 100755 vas/rest/ws/vitis/TimeZone.class.inc
 create mode 100755 vas/rest/ws/vitis/TimeZones.class.inc
 create mode 100755 vas/rest/ws/vitis/User.class.inc
 create mode 100755 vas/rest/ws/vitis/Users.class.inc
 create mode 100755 vas/rest/ws/vitis/Versions.class.inc
 create mode 100755 vas/rest/ws/vitis/Vitis.class.inc
 create mode 100755 vas/rest/ws/vitis/Vitis.class.sql.inc
 create mode 100755 vas/rest/ws/vitis/VitisSection.class.inc
 create mode 100755 vas/rest/ws/vitis/VitisSections.class.inc
 create mode 100755 vas/rest/ws/vitis/WebServices.class.inc
 create mode 100755 vas/rest/ws/vitis/overview.phtml
 create mode 100755 vas/sql/sqlQueries.xml

diff --git a/client/modules/vitis/data/proj.json b/client/modules/vitis/data/proj.json
new file mode 100755
index 00000000..74be9ff4
--- /dev/null
+++ b/client/modules/vitis/data/proj.json
@@ -0,0 +1,22 @@
+{
+    "projections": [
+        {
+            "code": "EPSG:2154",
+            "name": "Lambert 93",
+            "osm": true,
+            "bing": true
+        },
+        {
+            "code": "EPSG:3857",
+            "name": "WGS84 Spherical Mercator",
+            "osm": true,
+            "bing": true
+        },
+        {
+            "code": "EPSG:4326",
+            "name": "WGS84 Spherical Mercator (longlat)",
+            "osm": false,
+            "bing": false
+        }
+    ]
+}
diff --git a/client/modules/vitis/forms/configuration/configuration_vitis_configuration.json b/client/modules/vitis/forms/configuration/configuration_vitis_configuration.json
new file mode 100755
index 00000000..71c20aa3
--- /dev/null
+++ b/client/modules/vitis/forms/configuration/configuration_vitis_configuration.json
@@ -0,0 +1,1029 @@
+{
+    "datasources": {
+        "datasource_timezone_id": {
+            "type": "web_service",
+            "dataType": "webService",
+            "name": "datasource_timezone",
+            "description": "",
+            "ressource_id": "vitis/timezones",
+            "webservice": {
+                "name": "vitis"
+            },
+            "ressource": {
+                "name": "Timezones"
+            }
+        }
+    },
+    "search": {},
+    "update": {
+        "name": "configuration_general_update_form",
+        "title": "",
+        "input_size": "xs",
+        "event": "updateProperties('vitis')",
+        "nb_cols": 7,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "label": "FORM_GENERAL_SECTION_CONFIGURATION",
+                        "name": "title_properties",
+                        "nb_cols": 12,
+                        "id": "title_properties_1_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "language",
+                        "label": "FORM_LANGUAGE_CONFIGURATION",
+                        "options": [
+                            "Français|fr",
+                            "English|en"
+                        ],
+                        "nb_cols": 12,
+                        "id": "language_2_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "cookie_lifetime",
+                        "label": "FORM_COOKIE_LIFETIME_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "cookie_lifetime_3_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "max_upload_file_size",
+                        "label": "FORM_MAX_UPLOAD_FILE_SIZE_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "max_upload_file_size_4_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "max_execution_time",
+                        "label": "FORM_MAX_EXECUTION_TIME_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "max_execution_time_5_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "max_request_time",
+                        "label": "FORM_MAX_REQUEST_TIME_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "max_request_time_6_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "minimum_refresh_period",
+                        "label": "FORM_MINIMUM_REFRESH_PERIOD_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "minimum_refresh_period_7_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "forbidden_extension",
+                        "label": "FORM_FORBIDDEN_EXTENSION_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "forbidden_extension_8_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "rows_per_page",
+                        "label": "FORM_ROWS_PER_PAGE_CONFIGURATION",
+                        "options": [
+                            "10|10",
+                            "20|20",
+                            "50|50",
+                            "100|100",
+                            "200|200",
+                            "500|500"
+                        ],
+                        "nb_cols": 12,
+                        "id": "rows_per_page_9_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "extract_dir",
+                        "label": "FORM_EXTRACT_DIR_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "extract_dir_10_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "server_timezone",
+                        "label": "FORM_TIMEZONE_ID_CONFIGURATION",
+                        "required": true,
+                        "web_service": {
+                            "ressource_id": "vitis/timezones",
+                            "id_key": "name",
+                            "label_key": "label",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        },
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "date_format",
+                        "options": [
+                            "jj/mm/aaaa|d/m/Y",
+                            "mm/dd/yyyy|m/d/Y"
+                        ],
+                        "label": "FORM_DATE_FORMAT_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "date_format_11_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "login_remember_me",
+                        "label": "FORM_REMEMBER_ME_CONFIGURATION",
+                        "nb_cols": 6,
+                        "id": "login_remember_me_33_1",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": "enabled"
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": "disabled"
+                                }
+                            ]
+                        },
+                        "default_value": "disabled"
+                    },
+                    {
+                        "type": "radio",
+                        "name": "login_remember_me_default",
+                        "label": "FORM_REMEMBER_ME_DEFAULT_CONFIGURATION",
+                        "nb_cols": 6,
+                        "id": "login_remember_me_default_33_2",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "default_value": "enabled"
+                    }
+                ]
+            },{
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "instanceIdentifier",
+                        "label": "FORM_INSTANCE_IDENTIFIER_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "web_server_name_12_15"
+                    }
+                ]
+            },{
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "web_server_name",
+                        "label": "FORM_WEB_SERVER_NAME_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "web_server_name_12_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "vas_home",
+                        "label": "FORM_VAS_HOME_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "vas_home_13_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "enable_error_notification",
+                        "label": "FORM_ENABLE_ERROR_NOTIFICATION_CONFIGURATION",
+                        "nb_cols": 6,
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "id": "vas_home_13_15",
+                        "default_value": false
+                    },{
+                        "type":"email",
+                        "name":"admin_sign_up",
+                        "label":"FORM_ADMIN_SIGN_UP_CONFIGURATION",
+                        "nb_cols":6
+                    }
+                ]
+            },{
+                "fields":[
+                    {
+                        "type":"title",
+                        "label":"FORM_THEME_ACCOUNT_CONFIGURATION_CONFIGURATION",
+                        "name":"title_properties_account",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "account_deps",
+                        "label": "FORM_ACCOUNT_DEPS",
+                        "nb_cols": 12,
+                        "id": "vas_home_13_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "advanced_login_page",
+                        "label": "FORM_ADVANCE_LOGIN_PAGE",
+                        "nb_cols": 6,
+                        "id": "login_remember_me_33_1",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "default_value": false
+                    },
+                    {
+                        "type": "radio",
+                        "name": "automated_sign_up",
+                        "label": "FORM_AUTOMATED_SIGN_UP_CONFIGURATION",
+                        "nb_cols": 6,
+                        "id": "login_remember_me_default_33_2",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": false
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": true
+                                }
+                            ]
+                        },
+                        "default_value": false
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "sign_up",
+                        "label": "FORM_SIGN_UP_CONFIGURATION",
+                        "nb_cols": 6,
+                        "id": "sign_up_33_1",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "FORM_SIGN_UP_CONFIGURATION_YES",
+                                    "value": "enabled"
+                                },
+                                {
+                                    "label": "FORM_SIGN_UP_CONFIGURATION_NO",
+                                    "value": "disabled"
+                                }
+                            ]
+                        },
+                        "default_value": "disabled"
+                    },
+                    {
+                        "type": "radio",
+                        "name": "password_forgotten",
+                        "label": "FORM_FPWD_CONFIGURATION",
+                        "nb_cols": 6,
+                        "id": "password_forgotten_33_2",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": "enabled"
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": "disabled"
+                                }
+                            ]
+                        },
+                        "default_value": "enabled"
+                    }
+                ]
+            },{
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"google_private_captcha",
+                        "label":"FORM_GOOGLE_PRIVATE_CAPTCHA_CONFIGURATION",
+                        "nb_cols":12
+                    }
+                ]
+            },{
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"mail_tag_subject",
+                        "label":"FORM_MAIL_TAG_SUBJECT_CONFIGURATION",
+                        "nb_cols":12
+                    }
+                ]
+            }, {
+                "fields":[
+                    {
+                        "type":"title",
+                        "label":"FORM_THEME_NOTIFICATIONS_CONFIGURATION",
+                        "name":"title_properties_notifications",
+                        "nb_cols":12
+                    }
+                ]
+            }, {
+                "fields":[
+                    {
+                        "type":"radio",
+                        "name":"sms_notifications",
+                        "id":"sms_notifications",
+                        "label":"FORM_SMS_NOTIFICATIONS_CONFIGURATION_CONFIG",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_SMS_NOTIFICATIONS_TRUE_CONFIGURATION",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_SMS_NOTIFICATIONS_FALSE_CONFIGURATION",
+                                    "value": false
+                                }]
+                        },
+                        "default_value": false,
+                        "nb_cols": 12
+                    }
+                ]
+            }, {
+                "fields":[
+                    {
+                        "type":"title",
+                        "label":"FORM_THEME_SMTP_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "name":"title_properties_smtp",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"email",
+                        "name":"mail_sender",
+                        "label":"FORM_MAIL_SENDER_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "nb_cols":6
+                    },{
+                        "type":"text",
+                        "name":"nickname_sender",
+                        "label":"FORM_NICKNAME_SENDER_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"smtp_host",
+                        "label":"FORM_SMTP_HOST_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "nb_cols":6
+                    },
+                    {
+                        "type":"number",
+                        "name":"smtp_port",
+                        "label":"FORM_SMTP_PORT_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "min": 0,
+                        "max": 9999,
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"radio",
+                        "name":"smtp_authentification",
+                        "id":"smtp_authentification",
+                        "label":"FORM_SMTP_AUTHENTIFICATION_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_SMTP_AUTHENTIFICATION_TRUE_CONFIGURATION",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_SMTP_AUTHENTIFICATION_FALSE_CONFIGURATION",
+                                    "value": false
+                                }]
+                        },
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"smtp_login",
+                        "label":"FORM_SMTP_LOGIN_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "nb_cols":6
+                    },{
+                        "type":"password",
+                        "name":"smtp_password",
+                        "label":"FORM_SMTP_PASSWORD_CONFIGURATION_CONFIGURATION_GTF_CONFIG",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "check_smtp_connection",
+                                "label": "FORM_CHECK_SMTP_CONNECTION_CONFIGURATION",
+                                "class": "btn-primary",
+                                "event": "checkSmtpServerConnection()"
+                            }
+                        ],
+                        "id": "check_smtp_connection"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "label": "FORM_LOG_SECTION_CONFIGURATION",
+                        "name": "title_properties_log",
+                        "nb_cols": 12,
+                        "id": "title_properties_log_14_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "log_mode",
+                        "id": "log_mode",
+                        "label": "FORM_LOG_MODE_CONFIGURATION",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "FORM_LOG_MODE_TRUE_CONFIGURATION",
+                                    "value": true,
+                                    "$$hashKey": "object:1958"
+                                },
+                                {
+                                    "label": "FORM_LOG_MODE_FALSE_CONFIGURATION",
+                                    "value": false,
+                                    "$$hashKey": "object:1959"
+                                }
+                            ]
+                        },
+                        "nb_cols": 6
+                    },
+                    {
+                        "type": "radio",
+                        "name": "debug_mode",
+                        "id": "debug_mode",
+                        "label": "FORM_DEBUG_MODE_CONFIGURATION",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "FORM_DEBUG_MODE_TRUE_CONFIGURATION",
+                                    "value": true,
+                                    "$$hashKey": "object:1970"
+                                },
+                                {
+                                    "label": "FORM_DEBUG_MODE_FALSE_CONFIGURATION",
+                                    "value": false,
+                                    "$$hashKey": "object:1971"
+                                }
+                            ]
+                        },
+                        "nb_cols": 6
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "log_period",
+                        "label": "FORM_LOG_PERIOD_CONFIGURATION",
+                        "options": [
+                            "Jour|Y-m-d",
+                            "Mois|Y-m"
+                        ],
+                        "nb_cols": 12,
+                        "id": "log_period_16_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "log_size",
+                        "label": "FORM_LOG_SIZE_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "log_size_17_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "log_directories.Apache",
+                        "label": "FORM_APACHE_LOG_DIRECTORIE_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "log_directories.Apache_18_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "label": "FORM_HTTP_SERVER_SECTION_CONFIGURATION",
+                        "name": "title_properties_server",
+                        "nb_cols": 12,
+                        "id": "title_properties_server_19_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "shared_dir",
+                        "label": "FORM_SHARED_DIR_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "shared_dir_20_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "public_alias",
+                        "label": "FORM_PUBLIC_ALIAS_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "public_alias_21_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "services_alias",
+                        "label": "FORM_SERVICES_ALIAS_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "services_alias_22_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "doc_alias",
+                        "label": "FORM_DOC_ALIAS_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "doc_alias_23_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "ws_data_alias",
+                        "label": "FORM_WS_DATA_ALIAS_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "ws_data_alias_24_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "label": "FORM_SECURITY_SECTION_CONFIGURATION",
+                        "name": "title_properties_security",
+                        "nb_cols": 12,
+                        "id": "title_properties_security_25_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "proxy_check_ssl",
+                        "id": "proxy_check_ssl",
+                        "label": "FORM_PROXY_CHECK_SSL_CONFIGURATION",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "FORM_PROXY_CHECK_SSL_TRUE_CONFIGURATION",
+                                    "value": true,
+                                    "$$hashKey": "object:2036"
+                                },
+                                {
+                                    "label": "FORM_PROXY_CHECK_SSL_FALSE_CONFIGURATION",
+                                    "value": false,
+                                    "$$hashKey": "object:2037"
+                                }
+                            ]
+                        },
+                        "tooltip": {
+                            "title": "PROXY_CHECK_SSL_TOOLTIP_TITLE_CONFIGURATION",
+                            "content": "PROXY_CHECK_SSL_TOOLTIP_CONTENT_CONFIGURATION",
+                            "container": "body",
+                            "trigger": "hover"
+                        },
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "mixed_rights_management",
+                        "id": "mixed_rights_management",
+                        "label": "FORM_MIXED_RIGHTS_MANAGEMENT_CONFIGURATION",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "FORM_MIXED_RIGHTS_MANAGEMENT_TRUE_CONFIGURATION",
+                                    "value": true,
+                                    "$$hashKey": "object:2049"
+                                },
+                                {
+                                    "label": "FORM_MIXED_RIGHTS_MANAGEMENT_FALSE_CONFIGURATION",
+                                    "value": false,
+                                    "$$hashKey": "object:2050"
+                                }
+                            ]
+                        },
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "allow_public_connection",
+                        "id": "allow_public_connection",
+                        "label": "FORM_ALLOW_PUBLIC_CONNECTION_CONFIGURATION",
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "FORM_MIXED_RIGHTS_MANAGEMENT_TRUE_CONFIGURATION",
+                                    "value": true,
+                                    "$$hashKey": "object:2062"
+                                },
+                                {
+                                    "label": "FORM_MIXED_RIGHTS_MANAGEMENT_FALSE_CONFIGURATION",
+                                    "value": false,
+                                    "$$hashKey": "object:2063"
+                                }
+                            ]
+                        },
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "public_login",
+                        "label": "FORM_PUBLIC_LOGIN_CONFIGURATION",
+                        "web_service": {
+                            "ressource_id": "vitis/users",
+                            "id_key": "login",
+                            "label_key": "login",
+                            "parameters": {
+                                "order_by": "login"
+                            }
+                        },
+                        "nb_cols": 5,
+                        "id": "public_login_29_1"
+                    }
+                ]
+            },
+            {
+                "class": "form-field-inline",
+                "fields": [
+                    {
+                        "type": "password",
+                        "name": "public_password",
+                        "label": "FORM_PUBLIC_PASSWORD_CONFIGURATION",
+                        "nb_cols": 5,
+                        "id": "public_password_30_1"
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 4,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "test_connection",
+                                "label": "FORM_TEST_CONNECTION_CONFIGURATION",
+                                "class": "btn-primary",
+                                "event": "testPublicConnection()"
+                            }
+                        ],
+                        "id": "undefined_30_2"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "public_token",
+                        "label": "FORM_PUBLIC_TOKEN_CONFIGURATION",
+                        "pattern": "^[a-zA-Z0-9-,]+$",
+                        "tooltip": {
+                            "title": "Jeton de connexion du compte PUBLIC",
+                            "content": "Les caractères acceptés sont les chiffres et les lettres<br>ainsi que les caractères '-' et ','.",
+                            "container": "body",
+                            "html": true,
+                            "trigger": "hover"
+                        },
+                        "nb_cols": 12,
+                        "id": "public_token_31_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "private_captcha_key",
+                        "label": "FORM_PRIVATE_CAPTCHA_KEY_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "private_captcha_key_32_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "label": "FORM_DATABASE_TITLE_CONFIGURATION",
+                        "name": "title_properties_database",
+                        "nb_cols": 12,
+                        "id": "title_properties_database_34_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "sgbd",
+                        "label": "FORM_SGBD_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "sgbd_35_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "server",
+                        "label": "FORM_SERVER_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "server_36_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "port",
+                        "label": "FORM_PORT_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "port_37_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "database",
+                        "label": "FORM_DATABASE_TITLE_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "database_38_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "schema_framework",
+                        "label": "FORM_SCHEMA_CONFIGURATION",
+                        "nb_cols": 12,
+                        "id": "schema_framework_39_1"
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_UPDATE",
+                                "class": "btn-primary"
+                            }
+                        ],
+                        "id": "undefined_40_1"
+                    }
+                ]
+            }
+        ],
+        "tabs": {
+            "position": "top",
+            "list": [
+                {
+                    "label": "Tab 0",
+                    "elements": [
+                        "title_properties",
+                        "language",
+                        "cookie_lifetime",
+                        "max_upload_file_size",
+                        "max_execution_time",
+                        "max_request_time",
+                        "minimum_refresh_period",
+                        "forbidden_extension",
+                        "rows_per_page",
+                        "extract_dir",
+                        "date_format",
+                        "web_server_name",
+                        "vas_home",
+                        "title_properties_log",
+                        "log_mode",
+                        "debug_mode",
+                        "log_period",
+                        "log_size",
+                        "log_directories.Apache",
+                        "title_properties_server",
+                        "shared_dir",
+                        "public_alias",
+                        "services_alias",
+                        "doc_alias",
+                        "ws_data_alias",
+                        "title_properties_security",
+                        "proxy_check_ssl",
+                        "mixed_rights_management",
+                        "allow_public_connection",
+                        "public_login",
+                        "public_password",
+                        "test_connection",
+                        "public_token",
+                        "private_captcha_key",
+                        "login_remember_me",
+                        "login_remember_me_default",
+                        "sign_up",
+                        "password_forgotten",
+                        "title_properties_database",
+                        "sgbd",
+                        "server",
+                        "port",
+                        "database",
+                        "schema_framework",
+                        "form_submit",
+                        "smtp_authentification",
+                        "smtp_password",
+                        "smtp_login",
+                        "smtp_port",
+                        "smtp_host",
+                        "nickname_sender",
+                        "mail_sender",
+                        "title_properties_notifications",
+                        "sms_notifications",
+                        "title_properties_smtp",
+                        "check_smtp_connection",
+                        "advanced_login_page",
+                        "automated_sign_up",
+                        "enable_error_notification",
+                        "mail_tag_subject",
+                        "admin_sign_up",
+                        "google_private_captcha",
+                        "title_properties_account",
+                        "server_timezone"
+                    ]
+                }
+            ]
+        }
+    },
+    "insert": {},
+    "display": {},
+    "datasources": {}
+}
diff --git a/client/modules/vitis/forms/logs/logs_vitis_log.json b/client/modules/vitis/forms/logs/logs_vitis_log.json
new file mode 100755
index 00000000..9ee280eb
--- /dev/null
+++ b/client/modules/vitis/forms/logs/logs_vitis_log.json
@@ -0,0 +1,72 @@
+{
+    "search": {},
+    "update": {
+        "name": "logs_form",
+        "title": "FORM_TITLE_LOGS",
+        "input_size": "xxs",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "class": "form-field-inline logs-min-days-row",
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "min_days_files",
+                        "id": "min_days_files",
+                        "label": "FORM_DELETE_LOGS_LOG",
+                        "min": 5,
+                        "max": 200,
+                        "read_only": "true",
+                        "required": true,
+                        "nb_cols": 10
+                    },
+                    {
+                        "type": "label",
+                        "name": "min_days_files_unity",
+                        "default_value": "FORM_DAYS_LOGS_LOG",
+                        "nb_cols": 2
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-xs",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "btn_delete_file",
+                                "glyphicon": "trash",
+                                "class": "btn-primary btn-xs",
+                                "event": "deleteLogsHistory()",
+                                "tooltip": {
+                                    "title": "FORM_BTN_DELETE_HISTORY_LOGS",
+                                    "placement": "bottom",
+                                    "trigger": "hover",
+                                    "container": "body"
+                                }
+                            },
+                            {
+                                "type": "button",
+                                "name": "btn_refresh_treeview",
+                                "glyphicon": "refresh",
+                                "class": "btn-primary btn-xs",
+                                "event": "loadTreeview()",
+                                "tooltip": {
+                                    "title": "FORM_BTN_REFRESH_LOGS",
+                                    "placement": "bottom",
+                                    "trigger": "hover",
+                                    "container": "body"
+                                }
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {},
+    "display": {}
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/user/user_vitis_user.js b/client/modules/vitis/forms/user/user_vitis_user.js
new file mode 100755
index 00000000..d07edb10
--- /dev/null
+++ b/client/modules/vitis/forms/user/user_vitis_user.js
@@ -0,0 +1,66 @@
+/* global angular, goog, vitisApp */
+
+//bloque les delete du destructeur à éviter
+//'use strict';
+
+console.info("user_vitis_user.js loaded --> your functions are ready");
+/***********************************************************************************
+ LOGIN Javascript
+ ***********************************************************************************/
+
+var oFormRequired = {
+    "sUrl": "",
+    "scope_": {},
+    "toDestructor": []
+};
+
+/**
+ * constructor_form
+ * Function called by form init only if javascript boolean is Equal true 
+ * @param {type} scope Scope who contain the formreader
+ * @param {type} s_url URL of file for destructor
+ * @returns {undefined} 
+ */
+var constructor_form = function (scope, s_url) {
+    //////////////////////////////////////////////////////////
+    //Don't Edit this Part
+    console.log("Constructor");
+
+    oFormRequired.sUrl = s_url;
+    oFormRequired.scope_ = scope;
+    //////////////////////////////////////////////////////////
+    // Push element to Destruct (variable, function, watcher) in oFormRequired.toDestructor
+
+    // hide signup and forgotten password button if properties not set
+    var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+    setTimeout(function () {
+
+        if (propertiesSrvc["unsubscribe"] === true) {
+            angular.element("#unsubscribe_button").removeClass("hidden");
+        }
+    }, 1);
+};
+/**
+ * destructor_form
+ * Function called before constructor_form of a new form to remove all the watchers, variables, and others objects useless for others forms 
+ * @returns {undefined}
+ */
+var destructor_form = function () {
+    console.log("Destructor");
+
+    for (var i = 0; i < oFormRequired.toDestructor.length; i++) {
+        oFormRequired.toDestructor[i] = undefined;
+        delete oFormRequired.toDestructor[i];
+    }
+
+    //remove script Tag for reload javascript if user return on this form
+    angular.element('[src="' + oFormRequired.sUrl + '?version=' + oFormRequired.scope_["oProperties"]["build"] + '"]').remove();
+
+    oFormRequired = undefined;
+    delete oFormRequired;
+
+    constructor_form = undefined;
+    delete constructor_form;
+    destructor_form = undefined;
+    delete destructor_form;
+};
\ No newline at end of file
diff --git a/client/modules/vitis/forms/user/user_vitis_user.json b/client/modules/vitis/forms/user/user_vitis_user.json
new file mode 100755
index 00000000..a5dacd7e
--- /dev/null
+++ b/client/modules/vitis/forms/user/user_vitis_user.json
@@ -0,0 +1,348 @@
+{
+    "datasources": {
+        "datasource_timezone_id": {
+            "type": "web_service",
+            "dataType": "webService",
+            "name": "datasource_timezone",
+            "description": "",
+            "ressource_id": "vitis/timezones",
+            "webservice": {
+                "name": "vitis"
+            },
+            "ressource": {
+                "name": "Timezones"
+            }
+        },
+        "datasource_formatdate_id": {
+            "type": "web_service",
+            "dataType": "webService",
+            "name": "datasource_formatdate",
+            "description": "",
+            "ressource_id": "vitis/formatdates",
+            "webservice": {
+                "name": "vitis"
+            },
+            "ressource": {
+                "name": "FormatDates"
+            }
+        }
+    },
+    "search": {
+    },
+    "update": {
+        "name": "vitis_user_update_form",
+        "title": "",
+        "input_size": "xs",
+        "beforeEvent": "preventUserPasswordChanged(true)",
+        "event": "sendSimpleForm()",
+        "afterEvent": "disconnectUserPasswordChanged()",
+        "nb_cols": 8,
+        "javascript": true,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "name": "informations_title",
+                        "label": "FORM_INFORMATIONS_USER_USER",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "login",
+                        "label": "FORM_LOGIN_USER_USER",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_USER_USER",
+                        "required": true,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "email",
+                        "name": "email",
+                        "label": "FORM_EMAIL_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },{
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "acceptnotification",
+                        "label": "FORM_ACCEPTNOTIFICATION_USER_USER",
+                        "nb_cols": 6,
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "visible": "oProperties.sms_notifications == true ? true : false",
+                        "default_value": false
+                    },{
+                        "type": "text",
+                        "name": "phone",
+                        "label": "FORM_PHONE_USER_USER",
+                        "required": false,
+                        "visible": "oProperties.sms_notifications == true ? true : false",
+                        "nb_cols": 6
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "company",
+                        "label": "FORM_AGENCY_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "department",
+                        "label": "FORM_DEPARTMENT_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "dataencrypt",
+                        "label": "FORM_DATAENCRYPT_USER_USER",
+                        "nb_cols": 5,
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "default_value": false
+                    },
+                    {
+                        "type": "hidden",
+                        "name": "encrypted_secretkey",
+                        "label": "",
+                        "required": false,
+                        "nb_cols": 1
+                    },
+                    {
+                        "type": "text",
+                        "name": "secretkey",
+                        "label": "FORM_SECRETKEY_USER_USER",
+                        "required": false,
+                        "pattern": "^[^\t\r\n]+$",
+                        "nb_cols": 6
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "timezone_id",
+                        "label": "FORM_TIMEZONE_ID_USER_USER",
+                        "required": true,
+                        "nb_cols": 4,
+                        "datasource": {
+                            "datasource_id": "datasource_timezone_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "label",
+                            "order_by": "name",
+                            "id_key": "name",
+                            "attributs": "name|label",
+                            "parameters":{
+                                "order_by":"name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "formatdate_id",
+                        "label": "FORM_FORMATDATE_ID_USER_USER",
+                        "required": true,
+                        "nb_cols": 4,
+                        "datasource": {
+                            "datasource_id": "datasource_formatdate_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "label",
+                            "order_by": "label",
+                            "id_key": "formatdate_id",
+                            "attributs": "formatdate_id|label",
+                            "parameters":{
+                                "order_by":"label"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "name": "new_password_title",
+                        "label": "FORM_NEW_PASSWORD_USER_USER",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "password",
+                        "name": "password",
+                        "label": "FORM_USER_PASSWORD_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "password",
+                        "name": "password_confirm",
+                        "label": "FORM_USER_CONFIRM_PASSWORD_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "hidden",
+                        "name": "login",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_UPDATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "unsubscribe",
+                                "label": "ACCOUNT_UNSUBSCRIBE",
+                                "id": "unsubscribe_button",
+                                "class": "btn-primary hidden",
+                                "event": "unsubscribeAccount()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {
+    },
+    "display": {
+        "name": "vitis_user_update_form",
+        "title": "",
+        "input_size": "xs",
+        "nb_cols": 8,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "login",
+                        "label": "FORM_LOGIN_USER_USER",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "name",
+                        "label": "FORM_NAME_USER_USER",
+                        "required": true,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "email",
+                        "label": "FORM_EMAIL_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "company",
+                        "label": "FORM_AGENCY_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "department",
+                        "label": "FORM_DEPARTMENT_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/client/modules/vitis/forms/users/active_directory_connection.json b/client/modules/vitis/forms/users/active_directory_connection.json
new file mode 100755
index 00000000..023d6458
--- /dev/null
+++ b/client/modules/vitis/forms/users/active_directory_connection.json
@@ -0,0 +1,79 @@
+{
+    "search":{
+        "name":"active_directory_connection_form",
+        "title":"",
+        "input_size":"xs",
+        "event":"loadImportForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"select",
+                        "name":"domain",
+                        "label":"FORM_DOMAIN_ACTIVE_DIRECTORY_CONNECTION",
+                        "web_service":{
+                            "ressource_id":"vitis/domains",
+                            "id_key":"domain",
+                            "label_key":"alias",
+                            "callback": "selectFirstOption('domain')",
+                            "parameters":{
+                                    "order_by":"domain"
+                            }
+                        },
+                        "nb_cols":8,
+                        "required": true
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"login",
+                        "label":"FORM_LOGIN_ACTIVE_DIRECTORY_CONNECTION",
+                        "required": true,
+                        "nb_cols":5
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password",
+                        "label":"FORM_PASSWORD_ACTIVE_DIRECTORY_CONNECTION",
+                        "required": true,
+                        "nb_cols":5
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm import-user-ad-connect-btn",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CONNECTION_ACTIVE_DIRECTORY_CONNECTION",
+                                "class":"btn-primary"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+            
+    },
+    "insert":{
+
+    },
+    "display":{
+            
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/search_active_directory_group.json b/client/modules/vitis/forms/users/search_active_directory_group.json
new file mode 100755
index 00000000..d8ef1bcc
--- /dev/null
+++ b/client/modules/vitis/forms/users/search_active_directory_group.json
@@ -0,0 +1,52 @@
+{
+    "search":{
+        "name":"active_directory_groups_search_form",
+        "title":"",
+        "input_size":"xs",
+        "event":"searchAdTree('group')",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"search_group",
+                        "label":"FORM_GROUP_ACTIVE_DIRECTORY_USERS_GROUP",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_GROUP_INFO_ACTIVE_DIRECTORY_USERS_GROUP",
+                                "container": "body"
+                        },
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_SEARCH_BTN_ACTIVE_DIRECTORY_USERS_GROUP",
+                                "class":"btn-primary"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+            
+    },
+    "insert":{
+
+    },
+    "display":{
+            
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/search_active_directory_person.json b/client/modules/vitis/forms/users/search_active_directory_person.json
new file mode 100755
index 00000000..73be9914
--- /dev/null
+++ b/client/modules/vitis/forms/users/search_active_directory_person.json
@@ -0,0 +1,82 @@
+{
+    "search":{
+        "name":"active_directory_users_search_form",
+        "title":"",
+        "input_size":"xs",
+        "event":"searchAdTree('person')",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"search_account",
+                        "label":"FORM_ACCOUNT_ACTIVE_DIRECTORY_USERS_USER",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_ACCOUNT_INFO_ACTIVE_DIRECTORY_USERS_USER",
+                                "container": "body"
+                        },
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"search_groups",
+                        "label":"FORM_GROUP_ACTIVE_DIRECTORY_USERS_USER",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_GROUP_INFO_ACTIVE_DIRECTORY_USERS_USER",
+                                "container": "body"
+                        },
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"search_department",
+                        "label":"FORM_DEPARTMENT_ACTIVE_DIRECTORY_USERS_USER",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_DEPARTMENT_INFO_ACTIVE_DIRECTORY_USERS_USER",
+                                "container": "body"
+                        },
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_SEARCH_BTN_ACTIVE_DIRECTORY_USERS_USER",
+                                "class":"btn-primary"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+            
+    },
+    "insert":{
+
+    },
+    "display":{
+            
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/users_vitis_billinggroup.json b/client/modules/vitis/forms/users/users_vitis_billinggroup.json
new file mode 100755
index 00000000..6b1c3b25
--- /dev/null
+++ b/client/modules/vitis/forms/users/users_vitis_billinggroup.json
@@ -0,0 +1,223 @@
+{
+    "search": {
+        "name": "framework_billinggroup_search_form",
+        "title": "",
+        "input_size": "xxs",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "billinggroup",
+                        "label": "FORM_BILLINGGROUP_USERS_BILLINGGROUP",
+                        "required": false,
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-xs",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "search",
+                                "label": "FORM_SEARCH_BUTTON",
+                                "class": "btn-primary",
+                                "event": "setGridFilter()"
+                            },
+                            {
+                                "type": "reset",
+                                "name": "reset",
+                                "label": "FORM_RESET_BUTTON",
+                                "class": "btn-primary",
+                                "event": "resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update": {
+        "name": "framework_billinggroup_update_form",
+        "title": "FORM_TITLE_USERS_BILLINGGROUP",
+        "input_size": "xs",
+        "event": "sendSimpleForm()",
+        "nb_cols": 8,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "billinggroup_id",
+                        "label": "FORM_ID_USERS_BILLINGGROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "billinggroup",
+                        "label": "FORM_BILLINGGROUP_USERS_BILLINGGROUP",
+                        "required": true,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_USERS_BILLINGGROUP",
+                        "size":13,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_UPDATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {
+        "name": "framework_billinggroup_insert_form",
+        "title": "FORM_TITLE_USERS_BILLINGGROUP",
+        "input_size": "xs",
+        "event": "sendSimpleForm()",
+        "afterEvent": "editSectionForm()",
+        "nb_cols": 8,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "billinggroup",
+                        "label": "FORM_BILLINGGROUP_USERS_BILLINGGROUP",
+                        "required": true,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_USERS_BILLINGGROUP",
+                        "size":13,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_CREATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display": {
+        "name": "framework_billinggroup_display_form",
+        "title": "FORM_TITLE_USERS_BILLINGGROUP",
+        "input_size": "xs",
+        "nb_cols": 6,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "billinggroup_id",
+                        "label": "FORM_ID_USERS_BILLINGGROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "billinggroup",
+                        "label": "FORM_BILLINGGROUP_USERS_BILLINGGROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "description",
+                        "label": "FORM_DESCRIPTION_USERS_BILLINGGROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/users_vitis_domain.json b/client/modules/vitis/forms/users/users_vitis_domain.json
new file mode 100755
index 00000000..d62cd258
--- /dev/null
+++ b/client/modules/vitis/forms/users/users_vitis_domain.json
@@ -0,0 +1,497 @@
+{
+    "search":{
+        "name":"framework_domain_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"alias",
+                        "label":"FORM_ALIAS_USERS_DOMAIN",
+                        "required":false,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"domain",
+                        "label":"FORM_NAME_USERS_DOMAIN",
+                        "required":false,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"server",
+                        "label":"FORM_IP_SERVER_USERS_DOMAIN",
+                        "required":false,
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"framework_domain_update_form",
+        "title":"FORM_TITLE_USERS_DOMAIN",
+        "input_size":"xs",
+        "beforeEvent":"beforeSendingDomainForm()",
+        "event":"sendSimpleForm()",
+        "nb_cols":6,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"domain_id",
+                        "label":"FORM_ID_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"select",
+                        "name":"type",
+                        "label":"FORM_TYPE_USERS_DOMAIN",
+                        "options": ["Active Directory|AD", "LDAP|LDAP"],
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"alias",
+                        "label":"FORM_ALIAS_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"domain",
+                        "label":"FORM_NAME_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"server",
+                        "label":"FORM_IP_SERVER_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"number",
+                        "name":"port",
+                        "label":"FORM_PORT_USERS_DOMAIN",
+                        "min":0,
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"dn_search_user",
+                        "label":"FORM_DN_USER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"filter_user",
+                        "label":"FORM_FILTER_USER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"dn_search_group",
+                        "label":"FORM_DN_GROUP_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"filter_group",
+                        "label":"FORM_FILTER_GROUP_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"login",
+                        "label":"FORM_LOGIN_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password",
+                        "label":"FORM_PASSWORD_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"framework_domain_insert_form",
+        "title":"FORM_TITLE_USERS_DOMAIN",
+        "input_size":"xs",
+        "beforeEvent":"beforeSendingDomainForm()",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":6,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"select",
+                        "name":"type",
+                        "label":"FORM_TYPE_USERS_DOMAIN",
+                        "options": ["Active Directory|AD", "LDAP|LDAP"],
+                        "default_value":"AD",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"alias",
+                        "label":"FORM_ALIAS_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"domain",
+                        "label":"FORM_NAME_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"server",
+                        "label":"FORM_IP_SERVER_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"number",
+                        "name":"port",
+                        "label":"FORM_PORT_USERS_DOMAIN",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"dn_search_user",
+                        "label":"FORM_DN_USER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"filter_user",
+                        "label":"FORM_FILTER_USER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"dn_search_group",
+                        "label":"FORM_DN_GROUP_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"filter_group",
+                        "label":"FORM_FILTER_GROUP_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"login",
+                        "label":"FORM_LOGIN_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password",
+                        "label":"FORM_PASSWORD_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"framework_domain_display_form",
+        "title":"FORM_TITLE_USERS_DOMAIN",
+        "input_size":"xs",
+        "nb_cols":6,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"domain_id",
+                        "label":"FORM_ID_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"type",
+                        "label":"FORM_TYPE_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"alias",
+                        "label":"FORM_ALIAS_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"domain",
+                        "label":"FORM_NAME_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"server",
+                        "label":"FORM_IP_SERVER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"port",
+                        "label":"FORM_PORT_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"dn_search_user",
+                        "label":"FORM_DN_USER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"filter_user",
+                        "label":"FORM_FILTER_USER_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"dn_search_group",
+                        "label":"FORM_DN_GROUP_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"filter_group",
+                        "label":"FORM_FILTER_GROUP_USERS_DOMAIN",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/users_vitis_group.json b/client/modules/vitis/forms/users/users_vitis_group.json
new file mode 100755
index 00000000..1d882d84
--- /dev/null
+++ b/client/modules/vitis/forms/users/users_vitis_group.json
@@ -0,0 +1,253 @@
+{
+    "search": {
+        "name": "framework_group_search_form",
+        "title": "",
+        "input_size": "xxs",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_USERS_GROUP",
+                        "required": false,
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-xs",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "search",
+                                "label": "FORM_SEARCH_BUTTON",
+                                "class": "btn-primary",
+                                "event": "setGridFilter()"
+                            },
+                            {
+                                "type": "reset",
+                                "name": "reset",
+                                "label": "FORM_RESET_BUTTON",
+                                "class": "btn-primary",
+                                "event": "resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update": {
+        "name": "framework_group_update_form",
+        "title": "FORM_TITLE_USERS_GROUP",
+        "input_size": "xs",
+        "event": "sendSimpleForm()",
+        "nb_cols": 8,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "group_id",
+                        "label": "FORM_ID_USERS_GROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_USERS_GROUP",
+                        "required": true,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "double_select",
+                        "name": "users",
+                        "name_from": "user",
+                        "name_to": "users",
+                        "label": "FORM_USER_USERS_GROUP",
+                        "label_from": "FORM_AVAILABLE_USER_USERS_GROUP",
+                        "label_to": "FORM_LINKED_USER_USERS_GROUP",
+                        "web_service": {
+                            "ressource_id": "vitis/users",
+                            "id_key": "user_id",
+                            "label_key": "user_string",
+                            "parameters": {
+                                "filter": {
+                                    "domain": "getUsers2DomainFilter()"
+                                },
+                                "order_by": "user_string"
+                            }
+                        },
+                        "size": 18,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_UPDATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {
+        "name": "framework_group_insert_form",
+        "title": "FORM_TITLE_USERS_GROUP",
+        "input_size": "xs",
+        "event": "sendSimpleForm()",
+        "afterEvent": "editSectionForm()",
+        "nb_cols": 8,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_USERS_GROUP",
+                        "required": true,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "double_select",
+                        "name": "users",
+                        "name_from": "user",
+                        "name_to": "users",
+                        "label": "FORM_USER_USERS_GROUP",
+                        "label_from": "FORM_AVAILABLE_USER_USERS_GROUP",
+                        "label_to": "FORM_LINKED_USER_USERS_GROUP",
+                        "web_service": {
+                            "ressource_id": "vitis/users",
+                            "id_key": "user_id",
+                            "label_key": "user_string",
+                            "parameters": {
+                                "filter": {
+                                    "domain": "getUsers2DomainFilter()"
+                                },
+                                "order_by": "user_string"
+                            }
+                        },
+                        "size": 18,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_CREATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display": {
+        "name": "framework_group_display_form",
+        "title": "FORM_TITLE_USERS_GROUP",
+        "input_size": "xs",
+        "nb_cols": 6,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "group_id",
+                        "label": "FORM_ID_USERS_GROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "name",
+                        "label": "FORM_NAME_USERS_GROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "users_label",
+                        "label": "FORM_USER_USERS_GROUP",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/users_vitis_privilege.json b/client/modules/vitis/forms/users/users_vitis_privilege.json
new file mode 100755
index 00000000..91eef95e
--- /dev/null
+++ b/client/modules/vitis/forms/users/users_vitis_privilege.json
@@ -0,0 +1,190 @@
+{
+    "search":{
+        "name":"framework_privilege_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"rolname",
+                        "label":"FORM_USER_GROUP_USERS_PRIVILEGE",
+                        "required":false,
+                        "nb_cols":6
+                    },
+                    {
+                        "type":"text",
+                        "name":"description",
+                        "label":"FORM_GROUP_DESCRIPTION_USERS_PRIVILEGE",
+                        "required":false,
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"framework_privilege_update_form",
+        "title":"FORM_TITLE_USERS_PRIVILEGE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "nb_cols":8,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"rolname",
+                        "label":"FORM_USER_GROUP_USERS_PRIVILEGE",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"description",
+                        "label":"FORM_GROUP_DESCRIPTION_USERS_PRIVILEGE",
+                        "size":13,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"double_select",
+                        "name":"users",
+                        "name_from":"user",
+                        "name_to":"users",
+                        "label":"FORM_USERS_USERS_PRIVILEGE",
+                        "label_from":"FORM_GROUP_AVAILABLE_USER_USERS_PRIVILEGE",
+                        "label_to":"FORM_GROUP_LINKED_USERS_USERS_PRIVILEGE",
+                        "web_service":{
+                            "ressource_id":"vitis/users",
+                            "id_key":"user_id",
+                            "label_key":"login",
+                            "parameters":{
+                                    "order_by":"login"
+                            },
+                            "callback": "hideCurrentUserFromExcludedPrivileges('users')"
+                        },
+                        "size":15,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+
+    },
+    "display":{
+        "name":"framework_privilege_display_form",
+        "title":"FORM_TITLE_USERS_PRIVILEGE",
+        "input_size":"xs",
+        "nb_cols":6,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"rolname",
+                        "label":"FORM_USER_GROUP_USERS_PRIVILEGE",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"description",
+                        "label":"FORM_GROUP_DESCRIPTION_USERS_PRIVILEGE",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"users_label",
+                        "label":"FORM_GROUP_LINKED_USERS_USERS_PRIVILEGE",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/users/users_vitis_users.json b/client/modules/vitis/forms/users/users_vitis_users.json
new file mode 100755
index 00000000..75f99967
--- /dev/null
+++ b/client/modules/vitis/forms/users/users_vitis_users.json
@@ -0,0 +1,991 @@
+{
+    "datasources": {
+        "datasource_billinggroup_id": {
+            "type": "web_service",
+            "dataType": "webService",
+            "name": "datasource_billinggroup",
+            "description": "",
+            "ressource_id": "vitis/billinggroups",
+            "webservice": {
+                "name": "vitis"
+            },
+            "ressource": {
+                "name": "Billinggroups"
+            }
+        },
+        "datasource_timezone_id": {
+            "type": "web_service",
+            "dataType": "webService",
+            "name": "datasource_timezone",
+            "description": "",
+            "ressource_id": "vitis/timezones",
+            "webservice": {
+                "name": "vitis"
+            },
+            "ressource": {
+                "name": "Timezones"
+            }
+        },
+        "datasource_formatdate_id": {
+            "type": "web_service",
+            "dataType": "webService",
+            "name": "datasource_formatdate",
+            "description": "",
+            "ressource_id": "vitis/formatdates",
+            "webservice": {
+                "name": "vitis"
+            },
+            "ressource": {
+                "name": "FormatDates"
+            }
+        }
+    },
+    "search":{
+        "name":"framework_v_user_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"login",
+                        "label":"FORM_LOGIN_USERS_USER",
+                        "required":false,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"select",
+                        "name":"domain_id",
+                        "label":"FORM_DOMAIN_USERS_USER",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vitis/domains",
+                            "id_key":"domain_id",
+                            "label_key":"domain",
+                            "parameters":{
+                                    "order_by":"domain"
+                            }
+                        }
+                    },
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_USERS_USER",
+                        "required":false,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"email",
+                        "label":"FORM_EMAIL_USERS_USER",
+                        "required":false,
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"ip_constraint",
+                        "label":"FORM_IP_USERS_USER",
+                        "required":false,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"company",
+                        "label":"FORM_AGENCY_USERS_USER",
+                        "required":false,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"department",
+                        "label":"FORM_DEPARTMENT_USERS_USER",
+                        "required":false,
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"framework_v_user_update_form",
+        "title":"FORM_TITLE_USERS_USER",
+        "input_size":"xs",
+        "beforeEvent":"preventUserPasswordChanged(false)",
+        "event":"sendSimpleForm()",
+        "afterEvent":"disconnectUserPasswordChanged()",
+        "nb_cols":8,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"user_id",
+                        "label":"FORM_ID_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"login",
+                        "label":"FORM_LOGIN_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"last_connection",
+                        "label":"FORM_LAST_CONNECTION_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_USERS_USER",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"email",
+                        "name":"email",
+                        "label":"FORM_EMAIL_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },{
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "acceptnotification",
+                        "label": "FORM_ACCEPTNOTIFICATION_USERS_USER",
+                        "nb_cols": 6,
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "visible": "oProperties.sms_notifications == true ? true : false",
+                        "default_value": false
+                    },{
+                        "type": "text",
+                        "name": "phone",
+                        "label": "FORM_PHONE_USERS_USER",
+                        "required": false,
+                        "visible": "oProperties.sms_notifications == true ? true : false",
+                        "nb_cols": 6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"company",
+                        "label":"FORM_AGENCY_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"department",
+                        "label":"FORM_DEPARTMENT_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"active_directory_groups",
+                        "label":"FORM_ACTIVE_DIRECTORY_USER_GROUPS_USERS_USER",
+                        "visible": false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"double_select",
+                        "name":"groups",
+                        "name_from":"group",
+                        "name_to":"groups",
+                        "label":"FORM_LOCAL_GROUPS_USERS_USER",
+                        "label_from":"FORM_GROUPS_AVAILABLE_USERS_USER",
+                        "label_to":"FORM_GROUPS_USER_USERS_USER",
+                        "web_service":{
+                            "ressource_id":"vitis/groups",
+                            "id_key":"group_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        },
+                        "size":9,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"all_groups",
+                        "label":"FORM_ALL_USER_GROUPS_USERS_USER",
+                        "visible": false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"double_select",
+                        "name":"privileges",
+                        "name_from":"privilege",
+                        "name_to":"privileges",
+                        "label":"FORM_PRIVILEGES_USERS_USER",
+                        "label_from":"FORM_PRIVILEGES_AVAILABLE_USERS_USER",
+                        "label_to":"FORM_PRIVILEGES_USER_USERS_USER",
+                        "web_service":{
+                            "ressource_id":"vitis/privileges",
+                            "id_key":"rolname",
+                            "label_key":"rolname",
+                            "callback": "hideExcludedUserPrivileges('privileges')",
+                            "parameters":{
+                                    "order_by":"rolname"
+                            }
+                        },
+                        "switch_event":"hideExcludedUserPrivileges('privileges')",
+                        "size":9,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "billinggroup_id",
+                        "label": "FORM_BILLINGGROUP_ID_USERS_USER",
+                        "required": false,
+                        "nb_cols": 4,
+                        "datasource": {
+                            "datasource_id": "datasource_billinggroup_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "billinggroup",
+                            "order_by": "billinggroup",
+                            "id_key": "billinggroup_id",
+                            "attributs": "billinggroup_id|billinggroup",
+                            "parameters":{
+                                "order_by":"billinggroup"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"ip_constraint",
+                        "label":"FORM_IP_USERS_USER",
+                        "required":false,
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_IP_TOOLTIP_USERS_USER",
+                                "container": "body",
+                                "html": true
+                        },
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"restriction",
+                        "label":"FORM_RESTRICTION_USERS_USER",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_RESTRICTION_TOOLTIP_USERS_USER",
+                                "container": "body",
+                                "html": true
+                        },
+                        "size":8,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "timezone_id",
+                        "label": "FORM_TIMEZONE_ID_USERS_USER",
+                        "required": true,
+                        "nb_cols": 4,
+                        "datasource": {
+                            "datasource_id": "datasource_timezone_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "label",
+                            "order_by": "name",
+                            "id_key": "name",
+                            "attributs": "name|label",
+                            "parameters":{
+                                "order_by":"name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "formatdate_id",
+                        "label": "FORM_FORMATDATE_ID_USERS_USER",
+                        "required": true,
+                        "nb_cols": 4,
+                        "datasource": {
+                            "datasource_id": "datasource_formatdate_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "label",
+                            "order_by": "label",
+                            "id_key": "formatdate_id",
+                            "attributs": "formatdate_id|label",
+                            "parameters":{
+                                "order_by":"label"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"title",
+                        "name":"new_password_title",
+                        "label":"FORM_NEW_PASSWORD_USERS_USER",
+                        "name":"title_user_password",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password",
+                        "label":"FORM_USER_PASSWORD_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password_confirm",
+                        "label":"FORM_USER_CONFIRM_PASSWORD_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"hidden",
+                        "name":"login",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"framework_v_user_insert_form",
+        "title":"FORM_TITLE_USERS_USER",
+        "input_size":"xs",
+        "beforeEvent":"preventUserPasswordChanged(false)",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":8,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"login",
+                        "label":"FORM_LOGIN_USERS_USER",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_USERS_USER",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"email",
+                        "name":"email",
+                        "label":"FORM_EMAIL_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"company",
+                        "label":"FORM_AGENCY_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"department",
+                        "label":"FORM_DEPARTMENT_USERS_USER",
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },{
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "acceptnotification",
+                        "label": "FORM_ACCEPTNOTIFICATION_USERS_USER",
+                        "nb_cols": 6,
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "visible": "oProperties.sms_notifications == true ? true : false"
+                    },{
+                        "type": "text",
+                        "name": "phone",
+                        "label": "FORM_PHONE_USERS_USER",
+                        "required": false,
+                        "nb_cols": 6,
+                        "visible": "oProperties.sms_notifications == true ? true : false"
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"double_select",
+                        "name":"groups",
+                        "name_from":"group",
+                        "name_to":"groups",
+                        "label":"FORM_LOCAL_GROUPS_USERS_USER",
+                        "label_from":"FORM_GROUPS_AVAILABLE_USERS_USER",
+                        "label_to":"FORM_GROUPS_USER_USERS_USER",
+                        "web_service":{
+                            "ressource_id":"vitis/groups",
+                            "id_key":"group_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        },
+                        "size":9,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"double_select",
+                        "name":"privileges",
+                        "name_from":"privilege",
+                        "name_to":"privileges",
+                        "label":"FORM_PRIVILEGES_USERS_USER",
+                        "label_from":"FORM_PRIVILEGES_AVAILABLE_USERS_USER",
+                        "label_to":"FORM_PRIVILEGES_USER_USERS_USER",
+                        "web_service":{
+                            "ressource_id":"vitis/privileges",
+                            "id_key":"rolname",
+                            "label_key":"rolname",
+                            "parameters":{
+                                    "order_by":"rolname"
+                            }
+                        },
+                        "size":9,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "billinggroup_id",
+                        "label": "FORM_BILLINGGROUP_ID_USERS_USER",
+                        "required": false,
+                        "nb_cols": 4,
+                        "datasource": {
+                            "datasource_id": "datasource_billinggroup_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "billinggroup",
+                            "order_by": "billinggroup",
+                            "id_key": "billinggroup_id",
+                            "attributs": "billinggroup_id|billinggroup",
+                            "parameters":{
+                                "order_by":"billinggroup"
+                            }
+                        },
+                        "default_value": -1
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"ip_constraint",
+                        "label":"FORM_IP_USERS_USER",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_IP_TOOLTIP_USERS_USER",
+                                "container": "body",
+                                "html": true
+                        },
+                        "required":false,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"restriction",
+                        "label":"FORM_RESTRICTION_USERS_USER",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_RESTRICTION_TOOLTIP_USERS_USER",
+                                "container": "body",
+                                "html": true
+                        },
+                        "size":8,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "timezone_id",
+                        "label": "FORM_TIMEZONE_ID_USERS_USER",
+                        "required": true,
+                        "nb_cols": 4,
+                        "default_value": "Europe/Paris",
+                        "datasource": {
+                            "datasource_id": "datasource_timezone_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "label",
+                            "order_by": "name",
+                            "id_key": "name",
+                            "attributs": "name|label",
+                            "parameters":{
+                                "order_by":"name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "formatdate_id",
+                        "label": "FORM_FORMATDATE_ID_USERS_USER",
+                        "required": true,
+                        "nb_cols": 4,
+                        "default_value": "YYYY-MM-DDT",
+                        "datasource": {
+                            "datasource_id": "datasource_formatdate_id",
+                            "sort_order": "ASC",
+                            "distinct": "true",
+                            "label_key": "label",
+                            "order_by": "label",
+                            "id_key": "formatdate_id",
+                            "attributs": "formatdate_id|label",
+                            "parameters":{
+                                "order_by":"label"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password",
+                        "label":"FORM_USER_PASSWORD_USERS_USER",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"password",
+                        "name":"password_confirm",
+                        "label":"FORM_USER_CONFIRM_PASSWORD_USERS_USER",
+                        "required":true,
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"framework_v_user_display_form",
+        "title":"FORM_TITLE_USERS_USER",
+        "input_size":"xs",
+        "nb_cols":8,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"user_id",
+                        "label":"FORM_ID_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"login",
+                        "label":"FORM_LOGIN_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"last_connection",
+                        "label":"FORM_LAST_CONNECTION_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"domain",
+                        "label":"FORM_DOMAIN_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"name",
+                        "label":"FORM_NAME_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"email",
+                        "label":"FORM_EMAIL_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },{
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "acceptnotification",
+                        "label": "FORM_ACCEPTNOTIFICATION_USERS_USER",
+                        "nb_cols": 6,
+                        "options": {
+                            "choices": [
+                                {
+                                    "label": "Oui",
+                                    "value": true
+                                },
+                                {
+                                    "label": "Non",
+                                    "value": false
+                                }
+                            ]
+                        },
+                        "visible": "oProperties.sms_notifications == true ? true : false",
+                        "disabled":true
+                    },{
+                        "type": "label",
+                        "name": "phone",
+                        "label": "FORM_PHONE_USERS_USER",
+                        "visible": "oProperties.sms_notifications == true ? true : false",
+                        "nb_cols": 6
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "company",
+                        "label": "FORM_AGENCY_USER_USER",
+                        "required": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"company",
+                        "label":"FORM_AGENCY_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"department",
+                        "label":"FORM_DEPARTMENT_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"groups_label",
+                        "label":"FORM_GROUPS_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"privileges_label",
+                        "label":"FORM_PRIVILEGES_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"billinggroup",
+                        "label":"FORM_BILLINGGROUP_ID_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"ip_constraint",
+                        "label":"FORM_IP_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"restriction",
+                        "label":"FORM_RESTRICTION_USERS_USER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "timezone_id",
+                        "label": "FORM_TIMEZONE_ID_USER_USER",
+                        "nb_cols": 4
+                    },
+                    {
+                        "type": "label",
+                        "name": "label",
+                        "label": "FORM_FORMATDATE_ID_USER_USER",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/client/modules/vitis/images/administrator.png b/client/modules/vitis/images/administrator.png
new file mode 100755
index 0000000000000000000000000000000000000000..deae99bcff9815d8530a920e754d743700ddd5fb
GIT binary patch
literal 746
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7SkfJR9T^zbpD<_bdda}R
zAX(xXQ4*Y=R#Ki=l*-_klAn~S;F+74o*I;zm{M7IGS!BGfvLvR#WBR<^wJ6S9>IYk
z$KUo(Qi{GUrO0v2X+u)r3Kr3%!zXWDX<^-La(kNZ+zgFY<NB7=v(v0L=B(D8`miS2
z*g1Swams{=t<x?mewiL1rf9O^O6#fL-|lI<I4--;%K!Y%Y1{e5?|2ynKH0CST+w+u
zG*JE788eS^C;haAPABG_?syoQ?=eC6u;$MBr_|2Al(AW`Lp#}7J#nE%9lNIOiM3JT
z2~##*a1wpBQfcm#w%*w%ZDK4BI;Qbtr^Pnv)mg_$oHo3=`uK#U9Ic!-BI<3*@kiQ!
zNmL(P<;%&dWsvUrkE7;)%S>~(nz!rQuNU%8KA(Ts-jYeF{Qa4T)oI=Vj>*UVIsX4$
z=EHAoXzvwpW9A)urw0qY3}n7=?q0g>Y~XRzutf@D``dLne#|pEQ@>^5=OP`Jk30P<
zls;cGWwqfHJSDpQscVPrhuV3qi*-c5Z4zO#s<-{fE$FF#P|$AI5z$%O)(RE)TbZ@0
zT8d0O**s&$Ece?Y0dJT;-D4DwV|-rCuy(WXQ8(5rUzaQFSLEsN<_p#1<~uR#vXKAl
zhcZ!3C%HxTs7|zYP}<$^5+=^Mbf&}9;Lh}YYCUzuhcB#eyrXbn;-3#uZXXufRAt^;
zdUS7^xX9j+@KuX9%|5b|PbfVnWX;3{*?Smcg?kr-uYIn>GfyT;Ac5sxSM8GfwX!c?
ziG_SWueg}mB3oT?`=kkx9xBsi-TKcrO<i5Rrc><C-;Tm;$Cn<NR~7|TW*hn$GN_vF
z%3^ir{<-6EnB(&>gQL6bj=ti|P<vaMI5m9r&gx4s%TBah)33Ss*s?C@IFtRwoeC4u
z^-g6i4t#zt&Fb>Rd;0$mx-HPV9`I+$@qgmkFFxD52`*;7>((8>z`(%Z>FVdQ&MBb@
E00?SEs{jB1

literal 0
HcmV?d00001

diff --git a/client/modules/vitis/images/button_green.gif b/client/modules/vitis/images/button_green.gif
new file mode 100755
index 0000000000000000000000000000000000000000..82b66c3d7c37c8caf7da09054daae0ae39bb3643
GIT binary patch
literal 600
zcmZ?wbhEHb<Y(Y#c$UJTsjX+(swS(dU^h+Ocdda=r1I=56+s(J<kS>hR%oW}a$R}5
zBYwO6@fYiky;z&D-9b%DYwwdqS$o{4TrBWkXQW}JHfw7~<B6D(#Zm32leRvX?wx6O
z>FwT%!yy;m?3#DAdgkS_nxhemZ#2w3)||M~rT1)xx~1yGjkTR;Qd4)ioVj)A*!ctN
z?)K;H_nvyO;P%H;B?kklkA^F#E9LI<%Gu}DemYq<N@eBk&dAM{*1c+*?oV-BrM==-
z`=MtmGRhNck41W|*3H`EQL{WbdaHHe0skon%l+q@xVX71sw=B&Y1bc*(vMclT<g8(
z$%5?<XDOL0UU_%m@t3R1Z?%OjwyHlK?Ycs<`%GHgHoFPuvm-WJ=2d36rCSEBH=cU2
z(0PT%r%#^>i%O0kKM@iZAuX%$|NnmmY6HceEQ|~cDGWLwgF$h^z`nI1r70ybAt^a2
zA+fnRzCC%u#H9FMhGfquF=Z!dk7R}^Dedms`n*>18a|>OEy)5}fdRHUY?3a)9LcT8
zb~18&enEQT#unbmZOQ6_zEb9FVX~U+j2#nPxowmbRP9Zi9hfJyOT-FCm@4Y>h{Rp%
zOpXrmGBj`uj|q)qJ(-wn<lzzUL4muGC9a6$hH6$1r!qUon-7mt4@?eA*%u*{pnRZ#
YfmN(2>x+ia&VU{+S+6Y_0SXM(0ILYrYybcN

literal 0
HcmV?d00001

diff --git a/client/modules/vitis/images/button_red.gif b/client/modules/vitis/images/button_red.gif
new file mode 100755
index 0000000000000000000000000000000000000000..7e712d781f640cdd6bd04b3ae75f4eebe186b283
GIT binary patch
literal 609
zcmZ?wbhEHb<Y(Y#cvi^J+c%-GsKm{~>xU4}oVoLUw5G3Gz2^Aw6IZWZ`#Gc9!qVpP
zlP5p?&GIB9e$A=>5%2t?CGAJ1&x*M-cI@1BAldgvP27)2yB}IoKRk_o=*Ya%m;X@^
z^!wcIzmKl|oKW<0dR1~tTCS{gXMocWO{pIe{6EwseiVoOuu^;FZutAuwjW{EcZK;}
zq-44><9_4@{O~gkGSvA|m+))vvLA->=Zus!<Q0C{YWy%(G?SJ4A<qB9+jyy@=npTW
zAJ*z-(y~814S!B9(@;?SwY=xo%Dx{7F2A<UJyetaYtxL)qC$VJ9Qsiab+9bqhm4@B
zoz3qvJANd)|A=?_A<BEu)o4py?ou(~ZOi8WsEhy6oO)1P=(P~<ubm4uwRC@Noc=>i
z+(k*@M~X*{wc!s_r5~<(KUBqkq`3bO=KYcF7wqQrLtgmT{N^8y+96>P^$ks*K7G>E
z*83^MBQ2}&|NnmmqJiR17Dfh!LIxd>4p5vhu<vUqY%0uU%gN4R;co6>$SasIF(<c&
zae}X|o07o<rYVIv1<^vDQJJi1L8b)?h1?TDWo2CX!UcIuCa^OUr2A<aIXj5@+ZZbr
zFlHA7yT>?jvPz3(DMu7Ao%ZIGmlIHPu}aKfo^V>kFw9FYK;Kq1P`e;+T0(pZzm|l$
zxJrIV!8M5nVV0x(hGuysCqJrn^INby;%Ip6>fC1Nb81iJ<peoZmi~e_5*q|Lxnr9h
W+@fBlF)2GSh`0n9WCkcOSOWlnyXq_e

literal 0
HcmV?d00001

diff --git a/client/modules/vitis/images/user.png b/client/modules/vitis/images/user.png
new file mode 100755
index 0000000000000000000000000000000000000000..79f35ccbdad44489dbf07d1bf688c411aa3b612c
GIT binary patch
literal 741
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7SkfJR9T^zbpD<_bdda}R
zAX(xXQ4*Y=R#Ki=l*-_klAn~S;F+74o*I;zm{M7IGS!BGfvMcn#WBR<^wP<>9+v|}
z+Ih8J9=*0LjO9?4=8{G6SNyMDSh~qFmbrJ$)LgA+J&|1xUr$?^s=H=I#<Xp{JGbhd
zy%0FdODuDi&uJ;Q`AdvA4z@m7=CgPIKd&B^nXdA37BT1ETYfLvQOEG-U%M!O@#5{8
z**|+;N*`Jq@HsQ!(+fRMmDRu2vn*GVbS-x&37UWGKx|jEX2}(mOB2rDb!rhj!@Ziz
z#7U|oB*3>dtEKxwp<!oh@kSn*{w2O^wN^aLb8BBF^Z0ERkI55d{kGPo9dj*Y&pUpz
z+jTr(&YSna0rStzoAdJ@XK<}l&Ffulg0CxkY<Ds}zaenOvU=IQ*TvU=i`<#g^394}
zKH<<kmhaZat*I-^_+}RBE8ltdnbW#uS?R&w#k^^*B57}VXB67R9r}B%W!fQ)mf~W$
zjgMZNuhB?Qo%MHS&0?Dg_j!*`&x|<jvSEs<{>F&?Qhz%Sv^-Dv@NRzMr&nfr!Un9@
zOc^=DG_6;PFMgaSalDa<U7?;iWgml|9jjIx(|Y?|2gSZ53WsYiKbm!|iZxL)sxW4i
zlrQt=71E3%e_1STSt8GKT#DxGi{c3S%B_*R+$D@@-VdWglh%3dZF=}=?`Pp{Nq4T@
zQdm06Xl3UnvnJuQAvatmEQ)RLa4y&&wqnn{-jjTyzqp-k;tqBgwOCkdPn@>axpX@B
zq_hVTre8Z6xy%J*@>q^oE!dGN*7?%y&x>`35&|_oa@k3Us5+}2EH=8ibZ15;f6A4s
z#{V3?%~o*K7KvQCE;00o&eWAr+gc5~Z5%?Q&fZboc6DR&mw3yM{IPRd()iWao!o4F
z?M<5e1z#4~tk*WP!#Doj94hzVv-v;n{S0pRSAN}e>y8cs0|SGntDnm{r-UW|&%8>|

literal 0
HcmV?d00001

diff --git a/client/modules/vitis/javascript/controllers/activeDirectoryTreeCtrl.js b/client/modules/vitis/javascript/controllers/activeDirectoryTreeCtrl.js
new file mode 100755
index 00000000..359e6270
--- /dev/null
+++ b/client/modules/vitis/javascript/controllers/activeDirectoryTreeCtrl.js
@@ -0,0 +1,251 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.controllers.activeDirectoryTree");
+goog.require("vitis.modules.main");
+
+/**
+ * activeDirectoryTree Controller.
+ * .
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {service} $q Angular q service.
+ * @param {service} $translate Translate service.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @ngInject
+ **/
+vitisApp.activeDirectoryTreeCtrl = function ($log, $scope, $q, $translate, envSrvc, propertiesSrvc) {
+        // Initialisation
+        $log.info("initActiveDirectoryTree");
+        // Provisoire
+        $scope["aTreeviewActiveDirectoryTree"] = {};
+        // Paramétrage du module ui-grid
+        $scope["gridOptions"] = {
+                "enableRowSelection" : true,
+                "enableSelectAll" : true,
+                "enablePagination" : true,
+                "enablePaginationControls" : false,
+                "useExternalPagination" : true,
+                "paginationPageSize" : 10,
+                "enableColumnMenus" : false,
+                "enableColumnResizing": true,    // Redimensionnement des colonnes.
+                //"enableColumnMoving": true,      // Déplacement des colonnes.
+                "paginationPageSizes": [10, 20, 50, 100],
+                "appHeader": true, // Barre d'entête de la liste.
+                "appHeaderTitleBar": true, // Barre (boutons...) sous le form. de recherche.
+                "appHeaderSearchForm": false, // Formulaire de recherche.
+                "appLoadGridData": false,
+                "data": [],
+                "columnDefs": []
+        };
+        
+        // Définition des colonnes de la liste.
+        var aTranslationsId = ["NAME_SEARCH_ACTIVE_DIRECTORY_USERS_USER",
+                                "ACCOUNT_SEARCH_ACTIVE_DIRECTORY_USERS_USER",
+                                "EMAIL_SEARCH_ACTIVE_DIRECTORY_USERS_USER",
+                                "AGENCY_SEARCH_ACTIVE_DIRECTORY_USERS_USER",
+                                "DEPARTMENT_SEARCH_ACTIVE_DIRECTORY_USERS_USER",
+                                "GROUP_SEARCH_ACTIVE_DIRECTORY_USERS_USER"];
+        $translate(aTranslationsId).then(function (aTranslations) {
+                if ($scope["oActiveDirectoryParameters"]["sObject"] == "person") {
+                        $scope["gridOptions"]["columnDefs"] = [
+                                {"name": aTranslations["NAME_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "displayName": aTranslations["NAME_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "field": "displayname", "width": 200, "enableSorting": true,"type":"string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "active_directory_" + envSrvc["oSelectedObject"]["name"] + "_name"},
+                                {"name": aTranslations["ACCOUNT_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "displayName": aTranslations["ACCOUNT_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "field": "userprincipalname", "width": 200, "enableSorting": true,"type":"string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "active_directory_" + envSrvc["oSelectedObject"]["name"] + "_login"},
+                                {"name": aTranslations["EMAIL_SEARCH_ACTIVE_DIRECTORY_USERS_USER"],"displayName": aTranslations["EMAIL_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "field": "email", "width": 300, "enableSorting": true,"type":"string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "active_directory_" + envSrvc["oSelectedObject"]["name"] + "_email"},
+                                {"name": aTranslations["AGENCY_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "displayName": aTranslations["AGENCY_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "field": "company", "width": 200, "enableSorting": true,"type":"string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "active_directory_" + envSrvc["oSelectedObject"]["name"] + "_company"},
+                                {"name": aTranslations["DEPARTMENT_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "displayName": aTranslations["DEPARTMENT_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "field": "department", "width": 200, "enableSorting": true,"type":"string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "active_directory_" + envSrvc["oSelectedObject"]["name"] + "_company"}
+                        ];
+                }
+                else {
+                        $scope["gridOptions"]["columnDefs"] = [
+                                {"name": aTranslations["GROUP_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "displayName": aTranslations["GROUP_SEARCH_ACTIVE_DIRECTORY_USERS_USER"], "field": "name", "width": 400, "enableSorting": true,"type":"string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "active_directory_" + envSrvc["oSelectedObject"]["name"] + "_name"}
+                        ];
+                }
+        });
+        
+        // Bouton d'importation de la sélection.
+        $translate("BTN_IMPORT_SELECTION_" + envSrvc["oSelectedObject"]["name"].toUpperCase()).then(function (sLabel) {
+                envSrvc["oSelectedObject"]["actions"] = [
+                        {
+                                "label": sLabel,
+                                "name": $scope["sSelectedObjectName"] + "_import_btn",
+                                "event": "importAdSelection()"
+                        }
+                ];
+                $scope["gridOptions"]["appActions"] = envSrvc["oSelectedObject"]["actions"];
+        });
+        
+        // Nom + url du formulaire.
+        $scope["sFormDefinitionName"] = envSrvc["oSelectedObject"]["name"] + "_search_form";
+        // Paramètres pour la requête ajax du subform.
+        $scope["oFormRequestParams"] = {
+                "sUrl": "modules/vitis/forms/users/search_active_directory_" + $scope["oActiveDirectoryParameters"]["sObject"] + ".json"
+        };
+        // Suppression de la définition et des données du formulaire (sinon problème de cache...).
+        //formSrvc["clearFormData"]($scope["sFormDefinitionName"]);
+        $scope.$root["clearFormData"]($scope["sFormDefinitionName"], $scope);
+        envSrvc["oFormValues"][$scope["sFormDefinitionName"]] = {};
+        // Pas de données de form. à charger.
+        $scope["bLoadFormValues"] = false;
+        
+        /**
+         * convertAdTreeToBootstrapTreeview function.
+         * Convertion d'une arborescence Active Directory pour le composant "Bootstrap Treeview".
+         * @param {object} oAdtree Arborescence Active Directory
+         * $return {object}
+         **/
+        $scope["convertAdTreeToBootstrapTreeview"] = function(oAdtree) {
+                var oTrees = [], oTree, oNode;
+                var i = 0;
+                while (i < oAdtree.length) {
+                        oTree = {
+                                //"text": oAdtree[i]["id"].substr(0, 20),
+                                "text": oAdtree[i]["id"].split(",")[0],
+                                "branch": oAdtree[i]["id"]
+                                //"selectable": false
+                        };
+                        //
+                        //if (oAdtree[i]["items"].length > 0)
+                        //oTree["icon"] = "glyphicon glyphicon-file";
+                        //
+                        if (oAdtree[i]["items"].length > 0)
+                                oTree["nodes"] = $scope["convertAdTreeToBootstrapTreeview"](oAdtree[i]["items"]);
+                        oTrees.push(oTree);
+                        i++;
+                }
+               return oTrees;
+        }
+        
+        /**
+         * loadAdTreeBranch function.
+         * Charge le contenu d'une branche d'un arbre active directory.
+         * @param {string} sBranch Id de la branche d'un arbre active directory.
+         **/
+        $scope["loadAdTreeBranch"] = function(sBranch) {
+                // Test du domaine
+                var oParams = {
+                        "domain_id": $scope["oLdap"]["sIdLdap"],
+                        "login": $scope["oLdap"]["sLoginLdap"].split("@")[0],
+                        "password": $scope["oLdap"]["sPwdLdap"],
+                        //"branch": sBranch,
+                        //"language": propertiesSrvc["language"],
+                        "object": $scope["oActiveDirectoryParameters"]["sObject"]
+                };
+                // Charge les enregistrements de la branche.
+                ajaxRequest({
+                    "method": "GET",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/ActiveDirectory/" + $scope["oActiveDirectoryParameters"]["sWebServicePath"] + "/" + sBranch,
+                    "params": oParams,
+                    "scope": $scope,
+                    "success": function(response) {
+                        if (response["data"]["status"] == 1) {
+                            // MAJ de la liste des enregistrements.
+                            $scope["gridOptions"]["data"] = envSrvc["extractWebServiceData"]("activedirectory", response["data"])[0][$scope["oActiveDirectoryParameters"]["sWebServicePath"].toLowerCase()];
+                        }
+                    }
+                });
+        };
+        
+        /**
+         * importAdSelection function.
+         * Importation des utilisateurs sélectionnés.
+         **/
+        $scope["importAdSelection"] = function() {
+                var aSelection = $scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["getSelectedRows"]();
+                $scope["aSelection"] = angular.copy(aSelection);
+                var i = 0;
+                // Paramètres du service web.
+                var oParams = {
+                        "domain_id": $scope["oLdap"]["sIdLdap"],
+                        "ldap_name": $scope["oLdap"]["sLdapName"]
+                };
+                //var sHeaders = {"Content-Type": undefined};
+                while (i < aSelection.length) {
+                        oParams["action"] = 'importFromAd';
+                        if ($scope["oActiveDirectoryParameters"]["sObject"] == "person") {
+                                oParams["company"] = aSelection[i]["company"];
+                                oParams["department"] = aSelection[i]["department"];
+                                oParams["email"] = aSelection[i]["email"];
+                                oParams["name"] = aSelection[i]["displayname"];
+                                oParams["login"] = aSelection[i]["userprincipalname"];
+                        }
+                        else
+                                oParams["name"] = aSelection[i]["name"];
+                        // Importation d'un enregistrement sélectionné.
+                        ajaxRequest({
+                            "method": "POST",
+                            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/" + $scope["oActiveDirectoryParameters"]["sWebServicePath"].toLowerCase(),
+                            "params": oParams,
+                            "scope": $scope,
+                            "success": function(response) {
+                                if (response["data"]["status"] == 1) {
+                                    $scope["aSelection"].shift();
+                                    // Si l'importation est terminée avec succés: message ?
+                                    if ($scope["aSelection"].length == 0) {
+                                            $translate("SUCCESFULL_IMPORTATION_" + envSrvc["oSelectedObject"]["name"].toUpperCase()).then(function (sTranslation) {
+                                                    $.notify(sTranslation, "success");
+                                            });
+                                            // Supprime la sélection.
+                                            $scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["clearSelectedRows"]();
+                                    }
+                                }
+                                else {
+                                    // Message d'erreur.
+                                    $scope["aSelection"] = [];
+                                    var oOptions = {"className": "modal-danger"};
+                                    // Message d'erreur ?
+                                    if (response["data"]["errorMessage"] != null)
+                                            oOptions["message"] = response["data"]["errorMessage"];
+                                    $scope["modalWindow"]("alert", "FORM_VALIDATION_ERROR", oOptions);
+                                }
+                            }
+                        });
+                        i++;
+                }
+        }
+        
+        /**
+         * searchAdTree function.
+         * Cherche un utilisateur ou un groupe dans un arbre active directory.
+         * @param {string} sObject Type de recherche (user/group).
+         **/
+        $scope["searchAdTree"] = function(sObject) {
+                var deferred = $q.defer();
+                var promise = deferred.promise;
+                var oParams = {
+                        "domain_id": $scope["oLdap"]["sIdLdap"],
+                        "login": $scope["oLdap"]["sLoginLdap"].split("@")[0],
+                        "password": $scope["oLdap"]["sPwdLdap"],
+                        //"branch": sBranch,
+                        //"language": propertiesSrvc["language"],
+                        //"object": "sObject"
+                };
+                // Valeurs du formulaire.
+                var oFormValues = envSrvc["oFormValues"][$scope["sFormDefinitionName"]];
+                var aKeys = Object.keys(oFormValues);
+                var i = 0;
+                while (i < aKeys.length) {
+                        if (oFormValues[aKeys[i]] != "")
+                                oParams[aKeys[i]] = oFormValues[aKeys[i]];
+                        i++;
+                }
+                // Charge les enregistrements de la branche.
+                ajaxRequest({
+                    "method": "GET",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/ActiveDirectory/" + $scope["oActiveDirectoryParameters"]["sWebServicePath"],
+                    "params": oParams,
+                    "scope": $scope,
+                    "success": function(response) {
+                        if (response["data"]["status"] == 1) {
+                                // MAJ de la liste des enregistrements.
+                                $scope["gridOptions"]["data"] = envSrvc["extractWebServiceData"]("activedirectory", response["data"])[0][$scope["oActiveDirectoryParameters"]["sWebServicePath"].toLowerCase()];
+                        }
+                        deferred.resolve();
+                    }
+                });
+                // Retourne la promesse.
+                return promise;
+        };
+};
+vitisApp.module.controller("activeDirectoryTreeCtrl", vitisApp.activeDirectoryTreeCtrl);
diff --git a/client/modules/vitis/javascript/controllers/logsCtrl.js b/client/modules/vitis/javascript/controllers/logsCtrl.js
new file mode 100755
index 00000000..1e54e647
--- /dev/null
+++ b/client/modules/vitis/javascript/controllers/logsCtrl.js
@@ -0,0 +1,144 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.controllers.logs");
+goog.require("vitis.modules.main");
+
+/**
+ * logs Controller.
+ * .
+ * @param {angular.$rootScope} $rootScope Angular rootScope.
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {service} $translate Translate service.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @ngInject
+ **/
+vitisApp.logsCtrl = function ($rootScope, $log, $scope, $translate, envSrvc, propertiesSrvc) {
+    // Initialisation
+    $log.info("initLogs");
+    // Valeurs du formulaire de log.
+    envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]] = {
+        'min_days_files': 5
+    };
+
+    // Sauve les valeurs du form.
+    envSrvc["oFormDefaultValues"][envSrvc["sFormDefinitionName"]] = angular.copy(envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]);
+
+    /**
+     * getFileContent function.
+     * Charge le contenu d'un fichier.
+     * @param {object} oLogFile
+     * @param {string} size
+     **/
+    $rootScope["getFileContent"] = function (oLogFile, size) {
+        if (typeof (oLogFile) != "undefined") {
+            var iLogSize = propertiesSrvc["log_size"];
+            // 1Mo max par défaut.
+            if (isNaN(iLogSize)) {
+                iLogSize = 1024;
+            }
+            iLogSize *= 1024;
+            if (size < iLogSize) {
+                var oParams = {
+                    "folder": oLogFile['folder']
+                };
+                ajaxRequest({
+                    "method": "GET",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/logs/" + oLogFile['log_directory'] + "/file/" + oLogFile['name'],
+                    "params": oParams,
+                    "scope": $scope,
+                    "success": function(response) {
+                            if (response["data"]["status"] == 1) {
+                                $scope["sLogContent"] = response["data"]["file"];
+                                $rootScope["sLogPath"] = oLogFile['path'];
+                                if (typeof ($scope["sLogContent"]) != "undefined") {
+                                    // Redimensionne et affiche le <textarea> du log.
+                                    $("#logs-content-container").show();
+                                    $scope["resizeLogsContainer"]();
+                                    window.addEventListener("resize", $scope["resizeLogsContainer"]);
+                                }
+                            } else {
+                                // Affichage de la fenêtre modale d'erreur.
+                                var oOptions = {
+                                    "className": "modal-danger",
+                                    "message": response["data"]["errorMessage"],
+                                    "appDuration": 2000
+                                };
+                                $scope["modalWindow"]("dialog", "LOADING_FILE_ERROR_LOGS", oOptions);
+
+                            }
+                        }
+                    });
+
+            } else {
+                $rootScope["sLogPath"] = oLogFile['path'];
+                $("#logs-content-container").show();
+                $scope["sLogContent"] = ""
+                var itextAreaContainerheight = $("#logs-content-container").height() - document.getElementById("logs-content-container").children[0].offsetHeight;
+                document.getElementById("logs-content-container").children[1].style.height = itextAreaContainerheight + "px";
+                // Affichage de la fenêtre modale d'erreur.
+                var oOptions = {
+                    "className": "dialog-modal-window",
+                    "appDuration": 2000
+                };
+                $scope["modalWindow"]("dialog", "FILE_TOO_BIG_LOGS", oOptions);
+            }
+        }
+    };
+
+    /**
+     * deleteFile function.
+     * Supprime un fichier.
+     * @param {string} aPath Chemin du fichier
+     **/
+    $rootScope["deleteFile"] = function (oLogFile) {
+        if (goog.isDefAndNotNull(oLogFile)) {
+            var oParams = {
+                "folder": oLogFile['folder']
+            };
+            ajaxRequest({
+                "method": "DELETE",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/logs/" + oLogFile['log_directory'] + "/file/" + oLogFile['name'],
+                "params": oParams,
+                "scope": $scope,
+                "success": function(response) {
+                    var sTitle, sMessage;
+                    var oOptions = {};
+                    if (response["data"]["status"] == 1) {
+                        // Affichage du message de succés.
+                        sTitle = "DELETE_FILE_SUCCESS_LOGS";
+                        $translate(sTitle).then(function (sTranslation) {
+                            $.notify(sTranslation, "success");
+                        });
+                        // Raffraîchissement de l'arborescence.
+                        setTimeout(function () {
+                            $scope["loadTreeview"]();
+                        });
+                    } else {
+                        // Paramètres de la fenêtre modale.
+                        sTitle = "DELETE_FILE_ERROR_LOGS";
+                        // Affichage de la fenêtre modale.
+                        oOptions["className"] = "modal-danger";
+                        oOptions["message"] = response["data"]["errorMessage"];
+                        $scope["modalWindow"]("dialog", sTitle, oOptions);
+                    }
+                }
+            });
+        }
+    };
+
+    /**
+     * resizeLogsContainer  function.
+     * Redimensionne le conteneur des logs.
+     **/
+    $scope["resizeLogsContainer"] = function () {
+        $log.info("resizeLogsContainer");
+        if (envSrvc["oSelectedMode"]["mode_id"] == "logs") {
+            var itextAreaContainerheight = $("#logs-content-container").height() - document.getElementById("logs-content-container").children[0].offsetHeight;
+            document.getElementById("logs-content-container").children[1].style.height = itextAreaContainerheight + "px";
+        }
+    };
+};
+vitisApp.module.controller("logsCtrl", vitisApp.logsCtrl);
diff --git a/client/modules/vitis/javascript/controllers/versionConfigurationCtrl.js b/client/modules/vitis/javascript/controllers/versionConfigurationCtrl.js
new file mode 100755
index 00000000..1c1d4356
--- /dev/null
+++ b/client/modules/vitis/javascript/controllers/versionConfigurationCtrl.js
@@ -0,0 +1,64 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.controllers.versionConfiguration");
+goog.require("vitis.modules.main");
+
+/**
+ * versionConfiguration Controller.
+ * Chargement des données de la version.
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @ngInject
+ **/
+vitisApp.versionConfigurationCtrl = function ($log, $scope, propertiesSrvc) {
+    // Initialisation
+    $log.info("initVersionConfiguration");
+    /**
+     * getStateCssClass function.
+     * .
+     * @param {boolean} oState Etat de l'installation du composant.
+     **/
+    $scope["getStateCssClass"] = function (oState) {
+        if (oState)
+            return 'install-state-ok';
+        else
+            return 'install-state-error';
+    };
+    // Chargement des données de version.
+    ajaxRequest({
+        "method": "GET",
+        "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/Versions",
+        "params": {"app": sessionStorage["application"]},
+        "scope": $scope,
+        "success": function(response) {
+            if (response["data"]["status"] == 1) {
+                response["data"]["VM_VERSION"] = propertiesSrvc["version"],
+                response["data"]["VM_BUILD"] = propertiesSrvc["build"],
+                $scope["oVersion"] = response["data"];
+                $scope["oVersion"]["neededUpdate"] = true;
+                if (propertiesSrvc["version"] === "trunk") {
+                    delete $scope["oVersion"]["appVersion"];
+                } else {
+                    if($scope["oVersion"]["appVersion"] === null){
+                        // Impossible de vérifier les mises à jour, vous pouvez 
+                        $scope["oVersion"]["update"] = "ERROR_RETRIEVE_UPDATE_CONFIGURATION";
+                    }else{
+                        var version = angular.copy(propertiesSrvc["version"]).replace(".", "");
+                        var versionUpdate = angular.copy($scope["oVersion"]["appVersion"]).replace(".", "");
+                        if (versionUpdate > version) {
+                            // Votre version n'est pas à jour, vous pouvez télécharger les mises à jour ici
+                            $scope["oVersion"]["update"] = "NEEDED_UPDATE_CONFIGURATION";
+                        } else {
+                            // Votre version est à jour
+                            $scope["oVersion"]["neededUpdate"] = false;
+                            $scope["oVersion"]["update"] = "NO_NEEDED_UPDATE_CONFIGURATION";
+                        }
+                    }
+                }
+            }
+        }
+    });
+};
+vitisApp.module.controller("versionConfigurationCtrl", vitisApp.versionConfigurationCtrl);
diff --git a/client/modules/vitis/javascript/controllers/webServiceHelpCtrl.js b/client/modules/vitis/javascript/controllers/webServiceHelpCtrl.js
new file mode 100755
index 00000000..eb9c1564
--- /dev/null
+++ b/client/modules/vitis/javascript/controllers/webServiceHelpCtrl.js
@@ -0,0 +1,19 @@
+// Google closure
+goog.provide("vitis.controllers.webServiceHelp");
+goog.require("vitis.modules.main");
+
+/**
+ * webServiceHelp Controller.
+ * .
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {service} propertiesSrvc Paramètres des properties.
+  * @ngInject
+**/
+vitisApp.webServiceHelpCtrl = function ($log, $scope, propertiesSrvc) {
+        // Initialisation
+        $log.info("initWebServiceHelp");
+        // Url de la doc.
+        $scope["sUrlWebServiceDoc"] = propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["doc_alias"] + "/index.phtml";
+};
+vitisApp.module.controller("webServiceHelpCtrl", vitisApp.webServiceHelpCtrl);
diff --git a/client/modules/vitis/javascript/controllers/websocketConfigurationCtrl.js b/client/modules/vitis/javascript/controllers/websocketConfigurationCtrl.js
new file mode 100755
index 00000000..614f8ebd
--- /dev/null
+++ b/client/modules/vitis/javascript/controllers/websocketConfigurationCtrl.js
@@ -0,0 +1,102 @@
+// Google closure
+goog.provide("vitis.controllers.websocketConfiguration");
+goog.require("vitis.modules.main");
+
+/**
+ * websocketConfiguration Controller.
+ * Chargement des données de la version.
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {angular.$translate} $translate Angular $translate.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @ngInject
+ **/
+vitisApp.websocketConfigurationCtrl = function ($log, $scope, $translate, propertiesSrvc) {
+    // Initialisation
+    $log.info("initWebsocketConfiguration");
+
+    var this_ = this;
+
+    this.$log = $log;
+    this.$scope = $scope;
+    this.$translate = $translate;
+    this['propertiesSrvc'] = propertiesSrvc;
+
+    this.boolean1 = false;
+    this.boolean2 = false;
+
+    $scope['sWebSocketUrl'] = 'wss://' + location.host + '/' + propertiesSrvc['websocket_alias'] + '/';
+    $scope['oServerInfos'] = null;
+
+    // S'inscrit au service WebSocket Status
+//    if (goog.isDefAndNotNull(vitisApp['oWebsocket'])) {
+//        vitisApp['oWebsocket'].subscribeService('Status');
+//    }
+
+    vitisApp['oWebsocket'].on('serverInfo', function (oResult) {
+        this_.$scope.$applyAsync(function () {
+            this_.boolean2 = false;
+            this_.$scope['oServerInfos'] = oResult;
+            if (this_.boolean1) {
+                $translate(["WEBSOCKET_INFOS_REFRESHED_CONFIGURATION"]).then(function (oTranslations) {
+                    $.notify(oTranslations["WEBSOCKET_INFOS_REFRESHED_CONFIGURATION"], 'success');
+                });
+            }
+        });
+    });
+};
+
+/**
+ * Refresh the websocket server infos
+ * @export
+ */
+vitisApp.websocketConfigurationCtrl.prototype.reloadWebsocketStatus = function () {
+    this.$log.info("websocketConfigurationCtrl.reloadWebsocketStatus");
+
+    var this_ = this;
+
+    this.boolean1 = true;
+    this.boolean2 = true;
+
+    vitisApp['oWebsocket'].send_('serverInfo', '', 'Status');
+
+    setTimeout(function () {
+        if (this_.boolean2) {
+            this_.$translate(["WEBSOCKET_NO_SERVER_RESPONSE_CONFIGURATION"]).then(function (oTranslations) {
+                $.notify(oTranslations["WEBSOCKET_NO_SERVER_RESPONSE_CONFIGURATION"], 'error');
+            });
+            this_.$scope.$applyAsync(function () {
+                this_.$scope['oServerInfos'] = null;
+            });
+        }
+    }, 2000);
+};
+
+/**
+ * Refresh the websocket server clients
+ * @export
+ */
+vitisApp.websocketConfigurationCtrl.prototype.refreshClients = function () {
+    this.$log.info("websocketConfigurationCtrl.refreshClients");
+    vitisApp['oWebsocket'].send_('refreshClients', 'refreshClients');
+
+    var this_ = this;
+    var connectedOnce = false;
+    vitisApp['oWebsocket'].on('connect', function (oResult) {
+        if (!connectedOnce) {
+            setTimeout(function () {
+                this_.$translate(["WEBSOCKET_USERS_RECONNECTED_CONFIGURATION"]).then(function (oTranslations) {
+                    $.notify(oTranslations["WEBSOCKET_USERS_RECONNECTED_CONFIGURATION"], 'success');
+                });
+                setTimeout(function () {
+                    this_.reloadWebsocketStatus();
+                }, 1000);
+            }, 500);
+        }
+        connectedOnce = true;
+    });
+};
+
+vitisApp.module.controller("websocketConfigurationCtrl", vitisApp.websocketConfigurationCtrl);
+
+
diff --git a/client/modules/vitis/javascript/deps.js b/client/modules/vitis/javascript/deps.js
new file mode 100755
index 00000000..1c5731d0
--- /dev/null
+++ b/client/modules/vitis/javascript/deps.js
@@ -0,0 +1,19 @@
+'use strict';
+/* 
+ * Dépendances de closure pour le module "vitis".
+ */
+goog.provide("vitis.vitis");
+goog.require("vitis.controllers.logs");
+goog.require("vitis.controllers.websocketConfiguration");
+goog.require("vitis.controllers.versionConfiguration");
+goog.require("vitis.controllers.activeDirectoryTree");
+goog.require("vitis.controllers.webServiceHelp");
+goog.require("vitis.directives.logs");
+goog.require("vitis.directives.websocketConfiguration");
+goog.require("vitis.directives.versionConfiguration");
+goog.require("vitis.directives.phpInfo");
+goog.require("vitis.directives.activeDirectoryTree");
+goog.require("vitis.directives.webServiceHelp");
+
+goog.require("vitis.directives.htmlForm");
+goog.require("vitis.directives.main");
\ No newline at end of file
diff --git a/client/modules/vitis/javascript/directives/activeDirectoryTreeDrtv.js b/client/modules/vitis/javascript/directives/activeDirectoryTreeDrtv.js
new file mode 100755
index 00000000..b794accb
--- /dev/null
+++ b/client/modules/vitis/javascript/directives/activeDirectoryTreeDrtv.js
@@ -0,0 +1,98 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.directives.activeDirectoryTree");
+goog.require("vitis.modules.main");
+
+/**
+ * appActiveDirectoryFiles directive.
+ * Liste des utilisateurs.
+ **/
+vitisApp.appActiveDirectoryFilesDrtv = function() {
+        return {
+                restrict: 'A',
+                controller : 'activeDirectoryTreeCtrl',
+                controllerAs : 'ctrl',
+                templateUrl: "templates/workspaceListTpl.html"
+        }
+};
+vitisApp.module.directive("appActiveDirectoryFiles", vitisApp.appActiveDirectoryFilesDrtv);
+
+/**
+ * appActiveDirectoryTreeForm directive.
+ * Charge le template des éléments de formulaire.
+ * @ngInject
+ **/
+vitisApp.appActiveDirectoryTreeFormDrtv = function() {
+        return {
+                replace: true,
+                templateUrl: "templates/formTpl.html"
+        }
+};
+vitisApp.module.directive("appActiveDirectoryTreeForm", vitisApp.appActiveDirectoryTreeFormDrtv);
+
+/**
+ * appActiveDirectoryTreeTreeviewContainer directive.
+ * Charge et compile le template des arborescences des activeDirectoryTree.
+ * @param {service} $translate Translate service.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @ngInject
+ **/
+vitisApp.appActiveDirectoryTreeTreeviewContainerDrtv = function($translate, propertiesSrvc, envSrvc) {
+        return {
+                link: function (scope, element, attrs) {
+                        // Id de l'élément (pour le comoosant Treeview)
+                        element[0].id = scope["sSelectedObjectName"] + "_treeview";
+                        // Traduction du titre.
+                        $translate("TITLE_SECTION_" + envSrvc["oSelectedObject"]["name"].toUpperCase()).then(function (sTitle) {
+                                document.querySelector("#container_mode_" + envSrvc["oSelectedMode"]["mode_id"] + " .double-form-title").textContent = sTitle;
+                        });
+                        var oParams = {
+                                "domain_id": scope["oLdap"]["sIdLdap"],
+                                "login": scope["oLdap"]["sLoginLdap"].split("@")[0],
+                                "password": scope["oLdap"]["sPwdLdap"],
+                                "object": scope["oActiveDirectoryParameters"]["sObject"]
+                        };
+                        ajaxRequest({
+                            "method": "GET",
+                            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/ActiveDirectory/Tree",
+                            "params": oParams,
+                            "scope": scope,
+                            "success": function(response) {
+                                if (response["data"]["status"] == 1) {
+                                    response["data"] = envSrvc["extractWebServiceData"]("activedirectory", response["data"])[0]["tree"];
+                                    // Formate l'arbre pour Bootstrap Treeview.
+                                    scope["aTreeviewActiveDirectoryTree"]["data"] = scope["convertAdTreeToBootstrapTreeview"](response["data"]);
+                                    // Sauve le "sDn".
+                                    scope["oLdap"]["sDn"] = response["data"][0]["id"].split(",").slice(1).join(",");
+                                    // Crée l'arborescence dans l'élément.
+                                    $(element)["treeview"]({
+                                            "showBorder": false,
+                                            //"expandIcon": "glyphicon glyphicon-folder-close",
+                                            //"collapseIcon": "glyphicon glyphicon-folder-open",
+                                            "expandIcon": "glyphicon glyphicon-plus",
+                                            "collapseIcon": "glyphicon glyphicon-minus",
+                                            "highlightSelected": true,
+                                            "multiSelect": false,
+                                            //"showCheckbox": true,
+                                            "levels": 0,
+                                            //"emptyIcon": "glyphicon glyphicon-minus",
+                                            "data": scope["aTreeviewActiveDirectoryTree"]["data"],
+                                            "onNodeSelected": function(event, data) {
+                                                    // Charge le contenu de la branche.
+                                                    scope["loadAdTreeBranch"](data["branch"]);
+                                            }
+                                    });
+                                }
+                            }
+                        });
+                        // Attends la suppression du scope.
+                        scope.$on("$destroy", function () {
+                            // Supprime le treeview.
+                            $("#" + element[0].id)["treeview"]("remove");
+                        });
+                }
+        }
+};
+vitisApp.module.directive("appActiveDirectoryTreeTreeviewContainer", vitisApp.appActiveDirectoryTreeTreeviewContainerDrtv);
diff --git a/client/modules/vitis/javascript/directives/logsDrtv.js b/client/modules/vitis/javascript/directives/logsDrtv.js
new file mode 100755
index 00000000..791f3520
--- /dev/null
+++ b/client/modules/vitis/javascript/directives/logsDrtv.js
@@ -0,0 +1,171 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.directives.logs");
+goog.require("vitis.modules.main");
+
+/**
+ * appLogs directive.
+ * Association du contrôleur à la directive.
+ * @param {service} $translate Translate service.
+ * @ngInject
+ **/
+vitisApp.appLogsDrtv = function ($translate) {
+    return {
+        restrict: 'A',
+        controller: 'logsCtrl',
+        controllerAs: 'ctrl',
+        link: function (scope, element, attrs) {
+            // Traduction et affichage du tooltip.
+            $translate(["FORM_BTN_DELETE_FILE_LOGS"]).then(function (aTranslations) {
+                var oOptions = {
+                    "title": aTranslations["FORM_BTN_DELETE_FILE_LOGS"],
+                    "placement": "bottom",
+                    "trigger": "hover",
+                    "container": "body"
+                }
+                angular.element("#btn_delete_log_file")["tooltip"](oOptions);
+            });
+            // Attends la suppression du scope.
+            scope.$on("$destroy", function () {
+                // Supprime le tooltip.
+                angular.element("#btn_delete_log_file")["tooltip"]("destroy");
+                // Supprime l'évènement.
+                window.removeEventListener("resize", scope["resizeLogsContainer"]);
+            });
+        }
+    }
+};
+vitisApp.module.directive("appLogs", vitisApp.appLogsDrtv);
+
+/**
+ * appLogsForm directive.
+ * Charge le template des éléments de formulaire.
+ * @ngInject
+ **/
+vitisApp.appLogsFormDrtv = function () {
+    return {
+        replace: true,
+        templateUrl: "templates/formTpl.html"
+    }
+};
+vitisApp.module.directive("appLogsForm", vitisApp.appLogsFormDrtv);
+
+/**
+ * appLogsTreeviewContainer directive.
+ * Charge et compile le template des arborescences des logs.
+ * @param {angular.$timeout} $timeout Angular timeout service.
+ * @param {service} $translate Translate service.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @ngInject
+ **/
+vitisApp.appLogsTreeviewContainerDrtv = function ($timeout, $translate, propertiesSrvc, envSrvc) {
+    return {
+        link: function (scope, element, attrs) {
+            /**
+             * loadTreeview function.
+             * Crée le treeview des fichiers de log.
+             **/
+            scope["loadTreeview"] = function () {
+                // Cache le contenu du fichier de log.
+                $("#logs-content-container").hide();
+                // Charge l'arborescence des logs.
+                ajaxRequest({
+                    "method": "GET",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/Logs",
+                    "params": {"application_name": sessionStorage["application"]},
+                    "scope": scope,
+                    "success": function(response) {
+                        if (response["data"]["status"] == 1) {
+                            $timeout(function () {
+                                response["data"] = response["data"]["tree"];
+                                scope["oSelectedLogFile"] = {};
+                                scope["aTreeviewLogs"] = response["data"];
+
+                                // Crée l'arborescence dans l'élément.
+                                $(element)["treeview"]({
+                                    "showBorder": false,
+                                    "expandIcon": "glyphicon glyphicon-folder-close",
+                                    "collapseIcon": "glyphicon glyphicon-folder-open",
+                                    "onNodeSelected": function (event, data) {
+
+                                        scope["oSelectedLogFile"] = data;
+
+                                        // Fichier trop volumineux ?
+                                        scope["getFileContent"](data, data["size"]);
+
+                                    },
+                                    "onNodeUnselected": function (event, data) {
+                                        scope["oSelectedLogFile"] = [];
+                                    },
+                                    //"showTags": true,
+                                    "highlightSelected": true,
+                                    "multiSelect": false,
+                                    //"showCheckbox": true,
+                                    "data": scope["aTreeviewLogs"]["data"]
+                                });
+                            });
+                        }
+                    }
+                });
+            };
+
+            /**
+             * deleteLogsHistory function.
+             * Supprime les fichiers de log de plus de x jours.
+             **/
+            scope["deleteLogsHistory"] = function () {
+                var iMinDays = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["min_days_files"];
+                $translate('DELETE_HISTORY_CONFIRM_LOGS', {"min_days_files": iMinDays}).then(function (sText) {
+                    var oOptions = {
+                        "className": "modal-warning",
+                        "message": sText,
+                        "callback": function (bResponse) {
+                            if (bResponse) {
+                                ajaxRequest({
+                                    "method": "DELETE",
+                                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/Logs",
+                                    "params": {"min_days": iMinDays},
+                                    "scope": scope,
+                                    "success": function(response) {
+                                            // Raffraîchissement de l'arborescence.
+                                            scope["loadTreeview"]();
+                                    }
+                                });
+                            }
+                        }
+                    };
+                    scope["modalWindow"]("confirm", "", oOptions);
+                });
+            };
+
+            /**
+             * deleteLogFile function.
+             * Supprime un fichier de log.
+             * @param {string} sLogFile Chemin du fichier.
+             **/
+            scope["deleteLogFile"] = function (oLogFile) {                
+                var oOptions = {
+                    "className": "modal-warning",
+                    "message": "DELETE_FILE_CONFIRM_LOGS",
+                    "callback": function (bResponse) {
+                        if (bResponse)
+                            scope["deleteFile"](oLogFile);
+                    }
+                };
+                scope["modalWindow"]("confirm", "", oOptions);
+            };
+
+            // Charge les logs.
+            scope["loadTreeview"]();
+
+            // Attends la suppression du scope.
+            scope.$on("$destroy", function () {
+                // Supprime le treeview.
+                $("#" + element[0].id)["treeview"]("remove");
+            });
+        }
+    }
+};
+vitisApp.module.directive("appLogsTreeviewContainer", vitisApp.appLogsTreeviewContainerDrtv);
diff --git a/client/modules/vitis/javascript/directives/phpInfoConfigurationDrtv.js b/client/modules/vitis/javascript/directives/phpInfoConfigurationDrtv.js
new file mode 100755
index 00000000..332e3437
--- /dev/null
+++ b/client/modules/vitis/javascript/directives/phpInfoConfigurationDrtv.js
@@ -0,0 +1,38 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.directives.phpInfo");
+goog.require("vitis.modules.main");
+
+/**
+ * appPhpInfo directive.
+ * .
+ * @param {angular.$log} $log Angular log service.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @ngInject
+ **/
+vitisApp.appPhpInfoDrtv = function($log, propertiesSrvc) {
+        return {
+                link: function (scope, element, attrs) {
+                        // Initialisation
+                        $log.info("initPhpInfoConfiguration");
+                        // Charge les données du phpinfo().
+                        ajaxRequest({
+                            "method": "GET",
+                            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/Phpinfo",
+                            "scope": scope,
+                            "success": function(response) {
+                                if (response["data"]["status"] == 1) {
+                                    // Largeur du tableau à 100%.
+                                    //response["data"]["phpinfo"] = response["data"]["phpinfo"].replace(/600/g, "100%");
+                                    // Extraction du contenu de l'élément <body>.
+                                    var doc = document.implementation.createHTMLDocument("phpinfo");
+                                    doc.documentElement.innerHTML = response["data"]["phpinfo"];
+                                    element[0].innerHTML = doc.body.innerHTML;
+                                }
+                            }
+                        });
+                }
+        }
+};
+vitisApp.module.directive("appPhpInfo", vitisApp.appPhpInfoDrtv);
diff --git a/client/modules/vitis/javascript/directives/versionConfigurationDrtv.js b/client/modules/vitis/javascript/directives/versionConfigurationDrtv.js
new file mode 100755
index 00000000..1f1e69a6
--- /dev/null
+++ b/client/modules/vitis/javascript/directives/versionConfigurationDrtv.js
@@ -0,0 +1,17 @@
+// Google closure
+goog.provide("vitis.directives.versionConfiguration");
+goog.require("vitis.modules.main");
+
+/**
+ * appVersionConfiguration directive.
+ * Association du contrôleur à la directive.
+ * @export
+ **/
+vitisApp.appVersionConfigurationDrtv = function() {
+        return {
+                restrict: 'A',
+                controller : 'versionConfigurationCtrl',
+                controllerAs : 'ctrl'
+        }
+};
+vitisApp.module.directive("appVersionConfiguration", vitisApp.appVersionConfigurationDrtv);
diff --git a/client/modules/vitis/javascript/directives/webServiceHelpDrtv.js b/client/modules/vitis/javascript/directives/webServiceHelpDrtv.js
new file mode 100755
index 00000000..9affbf9b
--- /dev/null
+++ b/client/modules/vitis/javascript/directives/webServiceHelpDrtv.js
@@ -0,0 +1,28 @@
+// Google closure
+goog.provide("vitis.directives.webServiceHelp");
+goog.require("vitis.modules.main");
+
+/**
+ * appWebServiceHelp directive.
+ * Association du contrôleur à la directive.
+ * @export
+ **/
+vitisApp.appWebServiceHelpDrtv = function() {
+        return {
+                restrict: 'A',
+                controller : 'webServiceHelpCtrl',
+                controllerAs : 'ctrl',
+                link: function (scope, element, attrs) {
+                        // Affiche le loader ajax.
+                        showAjaxLoader();
+                        element[0].onload = function(){
+                                // Supprime l'entête.
+                                var oHeaderElement = element[0].contentDocument.querySelector("header");
+                                oHeaderElement.parentNode.removeChild(oHeaderElement);
+                                // Cache le loader ajax à la fin du chargement.
+                                hideAjaxLoader();
+                        };
+                }
+        }
+};
+vitisApp.module.directive("appWebServiceHelp", vitisApp.appWebServiceHelpDrtv);
diff --git a/client/modules/vitis/javascript/directives/websocketConfigurationDrtv.js b/client/modules/vitis/javascript/directives/websocketConfigurationDrtv.js
new file mode 100755
index 00000000..e851f57a
--- /dev/null
+++ b/client/modules/vitis/javascript/directives/websocketConfigurationDrtv.js
@@ -0,0 +1,17 @@
+// Google closure
+goog.provide("vitis.directives.websocketConfiguration");
+goog.require("vitis.modules.main");
+
+/**
+ * appWebsocketConfiguration directive.
+ * Association du contrôleur à la directive.
+ * @export
+ **/
+vitisApp.appWebsocketConfigurationDrtv = function () {
+    return {
+        restrict: 'A',
+        controller: 'websocketConfigurationCtrl',
+        controllerAs: 'ctrl'
+    };
+};
+vitisApp.module.directive("appWebsocketConfiguration", vitisApp.appWebsocketConfigurationDrtv);
diff --git a/client/modules/vitis/javascript/script_module.js b/client/modules/vitis/javascript/script_module.js
new file mode 100755
index 00000000..1f0e99b4
--- /dev/null
+++ b/client/modules/vitis/javascript/script_module.js
@@ -0,0 +1,1696 @@
+/* global vitisApp, goog, angular, bootbox */
+
+'use strict';
+goog.provide('vitis.vitis.script_module');
+goog.require('vitis');
+goog.require('vitis.directives.htmlForm');
+goog.require('vitis.directives.main');
+
+vitisApp.on('appMainDrtvLoaded', function () {
+
+    // Injection des services.
+    var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+    var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+    var sessionSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["sessionSrvc"]);
+    var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+
+    /**
+     * preventUserPasswordChanged function.
+     * Fenêtre de confirmation pour valider ou non le changement du mot de passe de l'utilisateur.
+     * @param {boolean} bShowConfirm Affiche ou non une fenêtre de confirmation.
+     * @return {promise}
+     **/
+    angular.element(vitisApp.appHtmlFormDrtv).scope()["preventUserPasswordChanged"] = function (bShowConfirm) {
+        // Injection des services.
+        var $q = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["$q"]);
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var userSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["userSrvc"]);
+        // Création de la promesse.
+        $log.info("preventUserPasswordChanged");
+        var scope = this;
+        var deferred = $q.defer();
+        var promise = deferred.promise;
+        // Cryptage de la clé secrète.
+        var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+        oFormValues['encrypted_secretkey'] = "";
+        if (oFormValues['dataencrypt'] === true && (goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) !== "0x")) {
+            var key = oFormValues['login'];
+            var ciphertext = des(key, oFormValues['secretkey'], 1, 0);
+            oFormValues['encrypted_secretkey'] = stringToHex(ciphertext);
+        }
+        else if (oFormValues['dataencrypt'] === false)
+            oFormValues['secretkey'] = "";
+        // Changement de mot de passe ?
+        var oPasswordInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password']");
+        var oPasswordConfirmInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password_confirm']");
+        if (envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["domain"] == null && oPasswordInput.value !== "") {
+            // Injection du service $translate.
+            //var $translate = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["$translate"]);
+            // Le mot de passe de confirmation est différent du mot de passe ?
+            if (oPasswordInput.value !== oPasswordConfirmInput.value) {
+                // Affichage de la fenêtre d'erreur.
+                var oOptions = {
+                    "className": "modal-danger",
+                    "appCallback": function () {
+                        deferred.reject();
+                    }
+                };
+                scope["modalWindow"]("dialog", "ERROR_PASSWORD_CONFIRM_USER_USER", oOptions);
+            } else if (bShowConfirm || envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["user_id"] === userSrvc["id"]) {
+                // Affichage de la fenêtre de confirmation.
+                var oOptions = {
+                    "className": "modal-warning",
+                    "message": "UPDATE_PASSWORD_USER_USER",
+                    "callback": function (bResponse) {
+                        if (bResponse)
+                            deferred.resolve();
+                        else
+                            deferred.reject();
+                    }
+                };
+                scope["modalWindow"]("confirm", "WARNING_PASSWORD_CHANGE_USER_USER", oOptions);
+            } else
+                deferred.resolve();
+        } else
+            deferred.resolve();
+        return promise;
+    };
+
+    /**
+     * disconnectUserPasswordChanged function.
+     * Si changement de mot de passe : déconnexion de l'application.
+     **/
+    angular.element(vitisApp.appHtmlFormDrtv).scope()["disconnectUserPasswordChanged"] = function () {
+        // Injection des services.
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var userSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["userSrvc"]);
+        // Changement de mot de passe ?
+        $log.info("disconnectUserPasswordChanged");
+        var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+        // Pas un utilisateur de l'Active Directory ?
+        if (oFormValues["domain"] === null) {
+            var oPasswordInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password']");
+            var oPasswordConfirmInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password_confirm']");
+            if (oPasswordInput.value !== "" && oPasswordInput.value === oPasswordConfirmInput.value && oFormValues["user_id"] === userSrvc["id"]) {
+                // Injection des services.
+                var sessionSrvc = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["sessionSrvc"]);
+                // Déconnexion de l'application.
+                sessionSrvc["disconnect"]();
+            }
+        }
+        // Décryptage de la clé secrète.
+        if (oFormValues['dataencrypt'] === true && (goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) === "0x")) {
+            var key = oFormValues['login'];
+            // Décrypte et Suprimme les caractères "NULL".
+            oFormValues['secretkey'] = des(key, hexToString(oFormValues['secretkey']), 0, 0).replace(/\x00/g, "");
+        }
+    };
+
+    /**
+     * loadLogsJob function.
+     * Paramétrage avant la compilation du template des logs.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadLogsJob"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        // Passage en mode "Update" (pour le formulaire).
+        envSrvc["sMode"] = "update";
+        $log.info("loadLogsJob");
+    };
+
+    /**
+     * loadConfiguration function.
+     * Paramétrage avant la compilation du template de configuration.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadConfiguration"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        // Passage en mode "Update" (pour le formulaire).
+        envSrvc["sMode"] = "update";
+        $log.info("loadConfiguration");
+    };
+
+    /**
+     * setPropertiesFormValues function.
+     * Affiche les valeurs du formulaire de l'onglet "configuration" (properties).
+     * @param {array} aPropertiesToCopy Tableau de properties à copier.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["setPropertiesFormValues"] = function (aPropertiesToCopy) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("setPropertiesFormValues");
+        var scope = this;
+        // Pas de surcharge des valeurs du form. (sinon problème avec les options de <select> passés dans la structure).
+        if (typeof (envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]) === "undefined" || goog.object.isEmpty(envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]])) {
+            var clearListener = scope.$root.$on('formDefinitionLoaded', function (event, sFormDefinitionName) {
+                // Suppression du "listener".
+                clearListener();
+                //
+                var i = 0;
+                var oFormElementDefinition;
+                var aPropertiesKeys = Object.keys(propertiesSrvc);
+                envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]] = {
+                    "log_directories": propertiesSrvc["log_directories"]
+                };
+                // Properties à copier en options.
+                if (!Array.isArray(aPropertiesToCopy))
+                    aPropertiesToCopy = [];
+                aPropertiesToCopy.forEach(function (sPropertieName) {
+                    envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]][sPropertieName] = angular.copy(propertiesSrvc[sPropertieName]);
+                });
+                //
+                while (i < aPropertiesKeys.length) {
+                    oFormElementDefinition = formSrvc["getFormElementDefinition"](aPropertiesKeys[i], envSrvc["sFormDefinitionName"]);
+                    if (typeof (oFormElementDefinition) !== "undefined") {
+                        if (oFormElementDefinition["type"] === "select")
+                            envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]][aPropertiesKeys[i]] = {"selectedOption": {"value": angular.copy(propertiesSrvc[aPropertiesKeys[i]])}};
+                        else
+                            envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]][aPropertiesKeys[i]] = angular.copy(propertiesSrvc[aPropertiesKeys[i]]);
+                    }
+                    i++;
+                }
+                // max_upload_file_size
+                var iMaxUploadFileSize = parseInt(envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["max_upload_file_size"]);
+                if (iMaxUploadFileSize === "NaN")
+                    iMaxUploadFileSize = "";
+                else if (iMaxUploadFileSize > 0)
+                    iMaxUploadFileSize = parseInt(iMaxUploadFileSize / (1024 * 1024));
+                envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["max_upload_file_size"] = iMaxUploadFileSize;
+
+                // rows_per_page (conversion en type "string").
+                if (typeof (envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["rows_per_page"]) != "undefined")
+                    envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["rows_per_page"]["selectedOption"]["value"] = String(envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["rows_per_page"]["selectedOption"]["value"]);
+
+                // Sauve les valeurs du formulaire.
+                envSrvc["oFormDefaultValues"][envSrvc["sFormDefinitionName"]] = angular.copy(envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]);
+            });
+        }
+    };
+
+    /**
+     * revoke vitis_user of an user to disable his account
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["unsubscribeAccount"] = function () {
+        console.log("unsubscribe");
+        // Injection des services.
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+
+        ajaxRequest({
+            "method": "PUT",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/accounts/" + sessionStorage['user_id'] + "/unsubscribe",
+            "data": {
+                'login': sessionStorage['user_login']
+            },
+            "success": function (response) {
+                console.log(response)
+                if (response["data"]["status"] === 1) {
+                    angular.element(vitisApp.appMainDrtv).scope()["disconnect"]();
+                } else {
+                    $.notify(response["data"]["message"], "error");
+                }
+            }
+        });
+    };
+
+    /**
+     *
+     */
+    angular.element(vitisApp.appHtmlFormDrtv).scope()["testPublicConnection"] = function () {
+        // Injection des services.
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("testPublicConnection");
+        //
+        var scope = this.$new();
+        var sPublicUser = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["public_login"]["selectedOption"]["value"];
+        var sPublicPassword = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["public_password"];
+        ajaxRequest({
+            "method": "POST",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/PrivateToken",
+            "data": {"user": sPublicUser, "password": sPublicPassword},
+            "scope": scope,
+            "success": function (response) {
+                if (response["data"]["status"] === 1) {
+                    var oOptions = {"className": "modal-success"};
+                    scope["modalWindow"]("dialog", "Connexion Réussie", oOptions);
+                } else {
+                    // Message d'erreur.
+                    var oOptions = {"className": "modal-danger"};
+                    // Message d'erreur ?
+                    if (response["data"]["errorMessage"] !== null)
+                        oOptions["message"] = response["data"]["errorMessage"];
+                    scope["modalWindow"]("alert", "ERROR_BIND_ACTIVE_DIRECTORY_USERS_USER", oOptions);
+                }
+            }
+        });
+    };
+
+    /**
+     * loadUser function.
+     * Paramètrage avant l'édition du compte de l'utilisateur connecté.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadUser"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var userSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["userSrvc"]);
+        //
+        $log.info("loadUser");
+        envSrvc["sId"] = userSrvc["id"];
+        //
+        var scope = this;
+        var sFunctionName = "before" + goog.string.toTitleCase(envSrvc["oSelectedObject"]["name"], "_").replace(/_/g, "") + "Edition";
+        scope.$root[sFunctionName]();
+        //
+        angular.element(vitisApp.appMainDrtv).scope()['loadSimpleForm']();
+    };
+
+    /**
+     * appUserRoleColumn directive.
+     * Mise en forme de la colonne "role" dans la liste de l'onglet "users_user" (Utilisateurs).
+     * @param {service} $translate Translate service.
+     * @ngInject
+     **/
+    vitisApp.appUserRoleColumnDrtv = function ($translate) {
+        return {
+            link: function (scope, element, attrs) {
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                var clearObserver = attrs.$observe("appUserRoleColumn", function (value) {
+                    // Si le champ est vide : supprime l'icône.  
+                    if (scope["row"]["entity"][scope["col"]["field"]] === null || scope["row"]["entity"][scope["col"]["field"]] === "")
+                        element[0].className = "";
+                    else {
+                        var sUserRoleClassName;
+                        // Classe css suivant le rôle.
+                        if (value === "admin")
+                            sUserRoleClassName = "admin-role";
+                        else if (value === "user")
+                            sUserRoleClassName = "user-role";
+                        // Classes css (ui-grid + spécifiques).
+                        element[0].className = "ui-grid-cell-contents " + sUserRoleClassName;
+                        // Traduction du titre et du contenu.
+                        $translate(["USER_ROLE_TOOLTIP_TITLE_USERS_USER", "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER", "USER_ROLE_USER_TOOLTIP_CONTENT_USERS_USER"]).then(function (translations) {
+                            // Création du "tooltip".
+                            $(element)["popover"]({
+                                "trigger": "hover",
+                                "container": "body",
+                                "title": translations["USER_ROLE_TOOLTIP_TITLE_USERS_USER"],
+                                "content": function () {
+                                    var sContent = "";
+                                    if (scope["row"]["entity"][scope["col"]["field"]] === "admin")
+                                        sContent = translations["USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER"];
+                                    else if (scope["row"]["entity"][scope["col"]["field"]] === "user")
+                                        sContent = translations["USER_ROLE_USER_TOOLTIP_CONTENT_USERS_USER"];
+                                    return sContent;
+                                },
+                                // Placement du tooltip à gauche ou à droite suivant la position horizontale de l'élément.
+                                "placement": function (oPopoverNode, oElementNode) {
+                                    return scope.$root["workspaceTooltipPlacement"](oElementNode);
+                                }
+                            });
+                        });
+                    }
+                });
+                // Attends la suppression du scope.
+                scope.$on("$destroy", function () {
+                    // Supprime le tooltip.
+                    $(element)["popover"]("destroy");
+                    // Supprime l'observateur.
+                    clearObserver();
+                });
+            }
+        };
+    };
+    vitisApp["compileProvider"].directive("appUserRoleColumn", vitisApp.appUserRoleColumnDrtv);
+
+    /**
+     * hideExcludedUserPrivileges function.
+     * Cache les privilèges protégés de l'utilisateur de la liste des options sélectionnées d'un "double-select".
+     * @param {string} sFormElementName Nom du champ de formulaire.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["hideExcludedUserPrivileges"] = function (sFormElementName) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $timeout = angular.element(vitisApp.appMainDrtv).injector().get(["$timeout"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var userSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["userSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("hideExcludedUserPrivileges");
+        //
+        if (envSrvc["sId"] === userSrvc["id"]) {
+            // Attends un cycle de "$digest".
+            $timeout(function () {
+                // Privilèges à exclure.
+                var aUserPrivileges = ["vitis_admin", "vitis_user"];
+                // Id et nom des 2 <select>.
+                var oFormElementDefinition = formSrvc["getFormElementDefinition"](sFormElementName, envSrvc["sFormDefinitionName"]);
+                var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+                var aSelectId = [oFormElementDefinition["id"], oFormElementDefinition["id_from"]];
+                var aSelectName = [sFormElementName, oFormElementDefinition["name_from"]];
+                // Cache les privilèges exclus dans les 2 <select>.
+                var i, oSelect;
+                var j = 0;
+                while (j < aSelectId.length) {
+                    i = 0;
+                    oSelect = document.getElementById(aSelectId[j]);
+                    while (oSelect.options.length > i) {
+                        oSelect.options[i].style.display = "";
+                        if (aUserPrivileges.indexOf(oSelect.options[i].text) !== -1) {
+                            oSelect.options[i].style.display = "none";
+                            oFormValues[aSelectName[j]]["options"][i]["disabled"] = true;
+                        }
+                        i++;
+                    }
+                    j++;
+                }
+            });
+        }
+    };
+
+    /**
+     * ImportFromAd function.
+     * Affichage de la fenêtre modale et du formulaire de connexion au serveur AD.
+     * @param {string} sObject Types d'enregistrements (users/groups).
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["ImportFromAd"] = function (sObject) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var modesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["modesSrvc"]);
+        //
+        $log.info("ImportFromAd");
+        // Crée un nouveau scope.
+        var scope = this.$new();
+        // Sauve le nouveau scope crée dans la définition de l'onglet.
+        //modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], scope);
+        //
+        scope["oActiveDirectoryParameters"] = {"sObject": sObject};
+        if (sObject == "person")
+            scope["oActiveDirectoryParameters"]["sWebServicePath"] = "Users";
+        else
+            scope["oActiveDirectoryParameters"]["sWebServicePath"] = "Groups";
+        //
+        var sFormId = "form_active_directory_connection_" + envSrvc["oSelectedObject"]["name"];
+        // Traduction du titre et affichage de la fenêtre modale.
+        var oOptions = {
+            "className": "dialog-modal-window dialog-modal-window-ad-connection",
+            "message": '<div id="' + sFormId + '"></div>',
+        };
+        scope["modalWindow"]("dialog", "TITLE_ACTIVE_DIRECTORY_CONNECTION", oOptions);
+
+        // Nom + url du formulaire.
+        scope["sFormDefinitionName"] = envSrvc["oSelectedObject"]["name"] + "_import_ad_form";
+        envSrvc["sFormDefinitionName"] = scope["sFormDefinitionName"];
+        // Paramètres pour la requête ajax du subform.
+        scope["oFormRequestParams"] = {
+            "sUrl": "modules/vitis/forms/users/active_directory_connection.json",
+        };
+        // Suppression de la définition et des données du formulaire (sinon problème de cache...).
+        //formSrvc["clearFormData"](scope["sFormDefinitionName"]);
+        scope.$root["clearFormData"](scope["sFormDefinitionName"], scope);
+        // Pas de données de form. à charger.
+        scope["bLoadFormValues"] = false;
+        envSrvc["oFormValues"][scope["sFormDefinitionName"]] = {};
+
+        // Compile le template de formulaire.
+        var sTemplateUrl = 'templates/formTpl.html';
+        $templateRequest(sTemplateUrl).then(function (sTemplate) {
+            $compile($("#" + sFormId).html(sTemplate).contents())(scope);
+        });
+        $log.info('compileObjectTemplate : ' + sTemplateUrl);
+        // Attends la fin de l'affichage formulaire.
+        var clearListener = scope.$root.$on('endFormNgRepeat', function (event) {
+            // Supprime le "listener".
+            clearListener();
+            // Crée l'élément pour afficher le domaine sélectionné après le login.
+            var oLoginDomainElement = document.createElement("span");
+            oLoginDomainElement["id"] = envSrvc["sFormDefinitionName"] + "_login_domain";
+            oLoginDomainElement["className"] = "dialog-modal-window-login-domain";
+            document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] .row:nth-child(2)").appendChild(oLoginDomainElement);
+            // Attends la fin du chargement de la liste des domaines.
+            var clearListener2 = scope.$root.$on('webServiceSelectOptionsloaded', function (event) {
+                // Supprime le "listener".
+                clearListener2();
+                // Si aucun domaine dans la base : supprime l'option vide crée par angular.
+                if (envSrvc["oFormValues"][scope["sFormDefinitionName"]]["domain"]["options"].length == 0)
+                    document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] select[name='domain']")["options"]["length"] = 0
+                else
+                    oLoginDomainElement.innerHTML = "@" + envSrvc["oFormValues"][scope["sFormDefinitionName"]]["domain"]["selectedOption"]["value"];
+            });
+            // Evènement sur le <select> des domaines.
+            document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] select[name='domain']").addEventListener("change", function () {
+                oLoginDomainElement.innerHTML = "@" + this["selectedOptions"][0]["value"];
+            });
+        });
+    };
+
+    /**
+     * loadImportForm function.
+     * Connexion au serveur AD et compilation du template (arborescence, form. de recherche et liste).
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadImportForm"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $q = angular.element(vitisApp.appMainDrtv).injector().get(["$q"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var modesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["modesSrvc"]);
+        //
+        $log.info("loadImportForm");
+        var scope = this;
+        // Sauve le scope parent dans la définition de l'onglet.
+        modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], scope);
+        var scope = scope.$new();
+        // Sauve le nouveau scope crée dans la définition de l'onglet.
+        modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], scope);
+        var deferred = $q.defer();
+        var promise = deferred.promise;
+        var oFormValues = envSrvc["oFormValues"][scope["sFormDefinitionName"]];
+        //
+        var key = oFormValues['login'] + "@" + oFormValues['domain']['selectedOption']["value"];
+        var ciphertext = des(key, oFormValues['password'], 1, 0);
+        // Test du domaine
+        var oParams = {
+            "login": oFormValues['login'],
+            "password": stringToHex(ciphertext),
+            "object": scope["oActiveDirectoryParameters"]["sObject"],
+            //"language": propertiesSrvc["language"],
+            "domain": oFormValues['domain']['selectedOption']["value"]
+        };
+        // Charge les données du formulaire.
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/ActiveDirectory/Test",
+            "params": oParams,
+            "scope": scope,
+            "success": function (response) {
+                if (response["data"]["status"] === 1) {
+                    // Connexion ok : suppression de la fenêtre de connexion.
+                    bootbox["hideAll"]();
+                    // Sauve les données de connexion au serveur AD.
+                    scope["oLdap"] = envSrvc["extractWebServiceData"]("activedirectory", response["data"])[0];
+                    //
+                    envSrvc["oSelectedObject"] = {
+                        "actions": [],
+                        "columns": [],
+                        "mode_id": envSrvc["oSelectedMode"]["mode_id"],
+                        "name": "active_directory_" + envSrvc["oSelectedObject"]["name"],
+                        //"ressource_id": "gtf/workspaces",
+                        "sections": "",
+                        "template_name": "activeDirectoryTree",
+                        "aScope": envSrvc["oSelectedObject"]["aScope"]
+                    };
+                    // Sauve le nouvel onglet.
+                    var oMode = modesSrvc["getMode"](envSrvc["oSelectedMode"]["mode_id"]);
+                    oMode["objects"].push(envSrvc["oSelectedObject"]);
+                    // Sauve le nouveau scope crée dans la définition de l'onglet.
+                    modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], scope);
+                    // Compilation du template "doubleFormTpl".
+                    var sTemplateUrl = 'templates/doubleFormTpl.html';
+                    $templateRequest(sTemplateUrl).then(function (sTemplate) {
+                        $compile($("#container_mode_" + envSrvc["oSelectedMode"]["mode_id"]).html(sTemplate).contents())(scope);
+                    });
+                    $log.info('compileObjectTemplate : ' + sTemplateUrl);
+                    //
+                    deferred.resolve();
+                } else {
+                    // Message d'erreur.
+                    scope["aSelection"] = [];
+                    var oOptions = {"className": "modal-danger"};
+                    // Message d'erreur ?
+                    if (response["data"]["errorMessage"] !== null)
+                        oOptions["message"] = response["data"]["errorMessage"];
+                    scope["modalWindow"]("alert", "ERROR_BIND_ACTIVE_DIRECTORY_USERS_USER", oOptions);
+                }
+            }
+        });
+        // Retourne la promesse.
+        return promise;
+    };
+
+    /**
+     * updateProperties function.
+     * Sauve les properties du module.
+     * @param {string} sModuleName Nom du module.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["updateProperties"] = function (sModuleName) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var $window = angular.element(vitisApp.appMainDrtv).injector().get(["$window"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("updateProperties");
+        var scope = this;
+        // Paramètres du webservice.
+        var oElem = {
+            "properties": formSrvc["getFormData"](envSrvc["sFormDefinitionName"], true),
+            "module_name": sModuleName
+        };
+        // Mise à jour des properties.
+        ajaxRequest({
+            "method": "PUT",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/Properties/" + sModuleName,
+            "data": oElem,
+            "scope": scope,
+            "success": function (response) {
+                if (response["data"]["status"] === 1) {
+                    // MAJ des properties OK.
+                    $translate("FORM_VALIDATION_OK").then(function (sTranslation) {
+                        $.notify(sTranslation, "success");
+                    });
+                    // Rechargement de la page si la langue est modifiée.
+                    if (sModuleName === "vitis" && propertiesSrvc["language"] !== oElem["properties"]["language"]) {
+                        var oOptions = {
+                            "className": "modal-warning",
+                            "message": "PAGE_RELOAD_CONFIRM_CONFIGURATION",
+                            "callback": function (bResponse) {
+                                if (bResponse)
+                                    $window.location.reload();
+                            }
+                        };
+                        scope["modalWindow"]("confirm", "", oOptions);
+                    }
+                    // Recharge les properties.
+                    propertiesSrvc["getFromServer"]();
+                } else {
+                    // Message d'erreur.
+                    var oOptions = {"className": "modal-danger"};
+                    // Message d'erreur ?
+                    if (response["data"]["errorMessage"] !== null)
+                        oOptions["message"] = response["data"]["errorMessage"];
+                    scope["modalWindow"]("alert", "FORM_VALIDATION_ERROR", oOptions);
+                }
+            }
+        });
+    };
+
+    /**
+     * beforeUsersVitisUsersEdition function.
+     * Données non modifiables si l'utilisateur vient de l'Active Directory.
+     * @param {object} sId Id de l'enregistrement sélectionné dans la liste.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["beforeUsersVitisUsersEdition"] = function (sId) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("beforeUsersVitisUsersEdition");
+        var scope = this;
+        var clearListener = scope.$root.$on('formDefinitionLoaded', function (event, sFormDefinitionName) {
+            // Suppression du "listener".
+            clearListener();
+            //
+            if (envSrvc["oFormValues"][sFormDefinitionName]["domain"] != null) {
+                var oFormElementDefinition = formSrvc["getAllFormElementDefinition"](sFormDefinitionName);
+                var i = 0;
+                while (i < oFormElementDefinition.length) {
+                    switch (oFormElementDefinition[i]["name"]) {
+                        case "name":
+                        case "email":
+                        case "company":
+                        case "department":
+                            oFormElementDefinition[i]["type"] = "label";
+                            break;
+                        case "new_password_title":
+                        case "password":
+                        case "password_confirm":
+                            oFormElementDefinition[i]["visible"] = false;
+                            break;
+                        case "groups":
+                        case "privileges":
+                            if (!propertiesSrvc["mixed_rights_management"])
+                                oFormElementDefinition[i]["visible"] = false;
+                            break;
+                            // Groupes du domaine dont l'utilisateur est membre.
+                        case "active_directory_groups":
+                            oFormElementDefinition[i]["visible"] = true;
+                            ajaxRequest({
+                                "method": "GET",
+                                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/ActiveDirectory/UserGroups/" + sId,
+                                "scope": scope,
+                                "success": function (response) {
+                                    if (response["data"]["status"] === 1) {
+                                        envSrvc["oFormValues"][sFormDefinitionName]["active_directory_groups"] = response["data"]["activedirectory"][0]["adGroups"];
+                                        envSrvc["oFormValues"][sFormDefinitionName]["all_groups"] = response["data"]["activedirectory"][0]["allGroups"];
+                                    }
+                                }
+                            });
+                            break;
+                            // Récapitulatif de tous les groupes de l'utilisateur.
+                        case "all_groups":
+                            if (propertiesSrvc["mixed_rights_management"])
+                                oFormElementDefinition[i]["visible"] = true;
+                            break;
+                    }
+                    i++;
+                }
+            }
+        });
+    };
+
+    /**
+     * beforeUserVitisUserEdition function.
+     * Données non modifiables si l'utilidateur vient de l'Active Directory .
+     * @param {object} sId Id de l'enregistrement sélectionné dans la liste.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["beforeUserVitisUserEdition"] = function (sId) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("beforeUserVitisUserEdition");
+        var scope = this;
+        var clearListener = scope.$root.$on('formDefinitionLoaded', function (event, sFormDefinitionName) {
+            // Supprime le listener.
+            clearListener();
+            //
+            var oFormValues = envSrvc["oFormValues"][sFormDefinitionName];
+            if (oFormValues["domain"] !== null) {
+                var oFormElementDefinition = formSrvc["getAllFormElementDefinition"](sFormDefinitionName);
+                var i = 0;
+                while (i < oFormElementDefinition.length) {
+                    switch (oFormElementDefinition[i]["name"]) {
+                        case "new_password_title":
+                        case "password":
+                        case "password_confirm":
+                            oFormElementDefinition[i]["visible"] = false;
+                            break;
+                    }
+                    i++;
+                }
+            }
+            // Chargement de la clé secrète (le web service vitis/users ne doit pas la retourner).
+            if (oFormValues['dataencrypt'] === true) {
+                var oUrlParams = {
+                    "schema": "s_vitis",
+                    "table": "user",
+                    "filter": {
+                        "relation": "AND",
+                        "operators": [{
+                                "column": "user_id",
+                                "compare_operator": "=",
+                                "value": oFormValues["user_id"]
+                            }]
+                    },
+                    "attributs": "secretkey"
+                };
+                ajaxRequest({
+                    "method": "GET",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/genericquerys/user",
+                    "params": oUrlParams,
+                    "success": function (response) {
+                        if (response["data"]["status"] != 0) {
+                            // Décryptage de la clé secrète.
+                            var oUserSecretKey = envSrvc["extractWebServiceData"]("genericquerys", response["data"])[0];
+                            if (goog.isDefAndNotNull(oUserSecretKey['secretkey']) && oUserSecretKey['secretkey'] != "" && oUserSecretKey['secretkey'].substr(0, 2) === "0x") {
+                                oFormValues['secretkey'] = des (oFormValues['login'], hexToString(oUserSecretKey['secretkey']), 0, 0).replace(/\x00/g, "");
+                            }
+                        }
+                    }
+                });
+            }
+        });
+    };
+
+    /**
+     * beforeSendingDomainForm function.
+     * Actions à effectuer avant l'envoi du form. d'un domaine.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["beforeSendingDomainForm"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("beforeSendingDomainForm");
+        // Cryptage du mot de passe avant la sauvegarde dans la base.
+        var scope = this;
+        var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+        if (oFormValues['login'] != null) {
+            // Ajoute "@" + domaine.
+            if (oFormValues['login'].indexOf("@") === -1)
+                oFormValues['login'] += "@" + oFormValues['domain'];
+            // Crypte le mdp.
+            if (oFormValues['password'] != null) {
+                // Ne crypte pas 2 fois le mdp.
+                if (oFormValues['password'].substr(0, 2) !== "0x") {
+                    var key = oFormValues['login'];
+                    var ciphertext = des(key, oFormValues['password'], 1, 0);
+                    oFormValues['password'] = stringToHex(ciphertext);
+                }
+            }
+        }
+    };
+
+    /**
+     * getUsers2DomainFilter function.
+     * Actions à effectuer avant l'envoi du form. d'un domaine.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["getUsers2DomainFilter"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("getUsers2DomainFilter");
+        if (!propertiesSrvc["mixed_rights_management"])
+            return "IS NULL";
+    };
+
+    /**
+     * isImgFile function.
+     * @param {string} sFile FilesName
+     * @return {boolean} true if it's an image
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["isImgFile"] = function (sFile) {
+        //liste des extension image
+        var sExtAccepted = ["jpg", "png", "jpeg"];
+        if (sFile.indexOf('?') !== -1) {
+            sFile = sFile.substr(0, sFile.indexOf('?'));
+        }
+        //récupération de l'extension dufichier courant
+        var aExt = sFile.split(".");
+        return (sExtAccepted.indexOf(aExt[aExt.length - 1].toLowerCase()) > -1);
+    };
+
+    /**
+     * appSignaletiqueImgViewer directive.
+     * Visualisation photo.
+     * @ngInject
+     **/
+    vitisApp.appDocumentViewerDrtv = function () {
+        return {
+            replace: true,
+            template: '<div>' +
+                    '<img ng-if="responseHavePicture && !bFileIsPdf" class="miniature_picture ui-grid-cell-contents" width="50" height="50" ng-src="{{urlToPicture}}" ng-hide="true"></img>' +
+                    '<span ng-show="responseHavePicture && !bFileIsPdf" ng-click="openViewer()" class="glyphicon glyphicon-picture grid-column-glyph-icon"></span>' +
+                    '<a ng-show="responseHavePicture && bFileIsPdf" ng-href="{{urlToPicture}}" target="_blank"><span class="glyphicon glyphicon-link grid-column-glyph-icon"></span></a>' +
+                    '</div>',
+            link: function (scope, element, attrs) {
+
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                //console.log(attrs);
+                var clearObserver = attrs.$observe("file", function () {
+                    if (attrs.file === null || attrs.file === "") {
+                        element[0].children[1].className = "";
+                        scope["responseHavePicture"] = false;
+                    } else {
+                        scope["responseHavePicture"] = true;
+                    }
+                    if (!goog.isDefAndNotNull(attrs["path"])) {
+                        console.error("Path attribute is not present on directive caller");
+                        return;
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["file"])) {
+                        console.error("File attribute is not present on directive caller");
+                        return;
+                    } else if (attrs["file"] === "") {
+                        return;
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["alias"])) {
+                        console.warn("alias attribute is not present on directive caller (set with default value : public_alias)");
+                        attrs["alias"] = "public_alias";
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["maxPopover"])) {
+                        console.warn("maxPopover attribute is not present on directive caller (set with default value : 200)");
+                        attrs["maxPopover"] = 200;
+                    } else if (attrs["maxPopover"] === "") {
+                        console.warn("File attribute is an empty string (set with default value : 200)");
+                        attrs["maxPopover"] = 200;
+                    } else if (goog.isString(attrs["maxPopover"])) {
+                        attrs["maxPopover"] = parseInt(attrs["maxPopover"]);
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["imgClass"])) {
+                        attrs["imgClass"] = "";
+                    } else if (!goog.isString(attrs["imgClass"]) /*&& !goog.isFunction(attrs["imgClass"])*/) {
+                        attrs["imgClass"] = "";
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["popoverClass"])) {
+                        attrs["popoverClass"] = "";
+                    } else if (!goog.isString(attrs["popoverClass"]) /*&& !goog.isFunction(attrs["popoverClass"])*/) {
+                        attrs["popoverClass"] = "";
+                    }
+
+                    scope["oProperties"] = angular.element("#works_line").scope()["oProperties"];
+                    if (goog.isDefAndNotNull(scope[attrs.path])) {
+                        scope["path"] = scope[attrs.path];
+                    } else {
+                        scope["path"] = attrs.path;
+                    }
+
+                    scope["urlToPicture"] = scope["oProperties"]["web_server_name"] + "/" + scope["oProperties"][attrs["alias"]] + "/" + scope["path"] + "/" + attrs["file"];
+                    if (/^https?:\/\//.test(attrs["file"])) {
+                        scope["urlToPicture"] = attrs["file"];
+                    }
+
+                    scope["bFileIsPdf"] = !scope.$root["isImgFile"](attrs.file);
+
+                    /*img[0].onload = function () {
+                     scope.$applyAsync(function () {
+                     scope["responseHavePicture"] = true;
+                     });
+                     };*/
+
+                    //var aExt = attrs.file.split(".");
+                    scope["bFileIsPdf"] = !scope.$root["isImgFile"](attrs.file);
+                    element[0].parentNode.style.textAlign = "center";
+                    if (!scope["bFileIsPdf"]) {
+                        // Si le champ est vide : supprime le lien.
+                        if (attrs.file === null || attrs.file === "") {
+                            element[0].children[1].className = "";
+                            // Attends la suppression du scope.
+                        } else {
+                            var img = element.find("img");
+                            if (goog.isDefAndNotNull(img[0])) {
+                                img[0].onerror = function () {
+                                    console.error('Fail to load image', attrs.file);
+                                };
+                            }
+                            var options = {
+                                "inline": false,
+                                "button": true,
+                                "navbar": false,
+                                "title": 2,
+                                "toolbar": 2,
+                                "tooltip": true,
+                                "fullscreen": false,
+                                "url": function () {
+                                    return scope["urlToPicture"];
+                                }
+                            };
+                            if (goog.isDefAndNotNull(scope["viewer"])) {
+                                scope["viewer"].update();
+                            } else {
+                                scope["viewer"] = new Viewer(element[0].children[0], options);
+                            }
+                            scope["openViewer"] = function () {
+                                scope["viewer"].show();
+                                angular.element(".viewer-prev").remove();
+                                angular.element(".viewer-next").remove();
+                            };
+                            // Création du "tooltip".
+                            var oPopover = $(element).children("span")["popover"]({
+                                "trigger": "hover",
+                                "container": "body",
+                                "title": "",
+                                "content": function () {
+                                    var oImg = document.createElement("img");
+                                    oImg.src = scope["urlToPicture"];
+                                    var maxSizePopover = attrs["maxPopover"];
+                                    var realWidth = oImg.naturalWidth;
+                                    var realHeight = oImg.naturalHeight;
+                                    var ScalingFactor = (realWidth < realHeight) ? realHeight / maxSizePopover : realWidth / maxSizePopover;
+                                    oImg.width = (ScalingFactor > 0) ? realWidth / ScalingFactor : realWidth;
+                                    oImg.height = (ScalingFactor > 0) ? realHeight / ScalingFactor : realHeight;
+                                    oImg.className = attrs["imgClass"];
+                                    oImg.onerror = function () {
+                                        console.error('Fail to load image', this);
+                                        // Détruit la modale si le chargement de l'image est en erreur.
+                                        $(oPopover).popover('destroy');
+                                    };
+
+                                    return oImg.outerHTML;
+                                },
+                                "html": true,
+                                "template": '<div class="popover ' + attrs["popoverClass"] + ' " role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+                            });
+                            // Attends la suppression du scope.
+                            scope.$on("$destroy", function () {
+                                // Supprime le tooltip.
+                                $(element[0].children[1])["popover"]("destroy");
+                                scope["viewer"].destroy();
+                                // Supprime l'observateur.
+                                clearObserver();
+                            });
+                        }
+                    }
+                });
+            }
+        };
+    };
+    vitisApp["compileProvider"].directive("appDocumentViewer", vitisApp.appDocumentViewerDrtv);
+
+    /**
+     * appLinker directive.
+     * Lien entre ce champs et un autre champs d'une autre table correspondant au code.
+     * @param {object} $timeout Angular Tiemout service.
+     * @ngInject
+     *
+     **/
+//    vitisApp.appLinkerDrtv = function ($timeout) {
+//        return {
+//            replace: false,
+//            template: '<a ng-click="goToItem()">{{itemData}}</a>',
+//            link: function (scope, element, attrs) {
+//
+//                var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+//                var clearObserver = attrs.$observe("itemData", function () {
+//                    if (!goog.isDefAndNotNull(attrs["itemData"] || attrs["itemData"] === "")) {
+//                        console.warn("No data display in column");
+//                        attrs["itemData"] = "";
+//                    }
+//
+//                    if (!goog.isDefAndNotNull(attrs["mode"] || attrs["mode"] === "")) {
+//                        console.warn("No mode selected (set to 'update' as default value)");
+//                        attrs["mode"] = "update";
+//                    }
+//
+//                    if (!goog.isDefAndNotNull(attrs["object"])) {
+//                        console.error("No object define");
+//                        return;
+//                    } else if (attrs["object"] === "") {
+//                        console.error("objet name is empty");
+//                        return;
+//                    }
+//
+//                    if (!goog.isDefAndNotNull(attrs["fieldToSelect"])) {
+//                        console.error("No fieldToSelect define");
+//                        return;
+//                    } else if (attrs["fieldToSelect"] === "") {
+//                        console.error("fieldToSelect name is empty");
+//                        return;
+//                    }
+//                    scope["itemData"] = attrs["itemData"];
+//                    //scope["modeToSelect"] = attrs["modetoSelect"];
+//
+//                    scope["goToItem"] = function () {
+//                        //var scope_ = scope;
+//
+//                        angular.element("#object_column").scope()["selectObject"](attrs["object"], undefined, {});
+//                        $timeout(function () {
+//                            envSrvc["setSectionForm"](attrs["mode"], attrs["fieldToSelect"]);
+//                        }, 800);
+//                    };
+//                    // Attends la suppression du scope.
+//                    scope.$on("$destroy", function () {
+//                        // Supprime l'observateur.
+//                        clearObserver();
+//                    });
+//                });
+//            }
+//        };
+//    };
+//    vitisApp["compileProvider"].directive("appLinker", vitisApp.appLinkerDrtv);
+
+
+    /**
+     * appLinker directive.
+     * Permet de faire un lien dans une liste qui renvoie sur un objet en question
+     * data-mode-id permet de féfinir le mode_id
+     * data-object permet de féfinir le object_id
+     * data-mode (update/display)
+     * data-field-to-select définit l'identifiant de l'objet à éditer/visualiser
+     *
+     * @param {object} $timeout Angular Tiemout service.
+     * @ngInject
+     *
+     **/
+    vitisApp.appLinkerDrtv = function ($timeout) {
+        return {
+            replace: false,
+            template: '<a href="#" ng-click="goToItem()">{{itemData}}</a>',
+            link: function (scope, element, attrs) {
+
+                var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+                var mainDrtv = angular.element(vitisApp.appMainDrtv).scope();
+
+                var clearObserver = attrs.$observe("itemData", function () {
+                    if (!goog.isDefAndNotNull(attrs["itemData"] || attrs["itemData"] === "")) {
+                        console.warn("No data display in column");
+                        attrs["itemData"] = "";
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["mode"] || attrs["mode"] === "")) {
+                        console.warn("No mode selected (set to 'update' as default value)");
+                        attrs["mode"] = "update";
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["object"])) {
+                        console.error("No object define");
+                        return;
+                    } else if (attrs["object"] === "") {
+                        console.error("objet name is empty");
+                        return;
+                    }
+
+                    if (!goog.isDefAndNotNull(attrs["fieldToSelect"])) {
+                        console.error("No fieldToSelect define");
+                        return;
+                    } else if (attrs["fieldToSelect"] === "") {
+                        console.error("fieldToSelect name is empty");
+                        return;
+                    }
+                    scope["itemData"] = attrs["itemData"];
+                    scope["goToItem"] = function () {
+                        var sModeId = goog.isDefAndNotNull(attrs["modeId"]) ? attrs["modeId"] : envSrvc["oSelectedMode"]["mode_id"];
+                        var sObjectId = attrs["object"];
+                        var sElemId = attrs["fieldToSelect"];
+                        var sMode = goog.isDefAndNotNull(attrs["mode"]) ? attrs["mode"] : 'update';
+                        mainDrtv['selectElement'](sModeId, sObjectId, sElemId, sMode);
+                    };
+                    // Attend la suppression du scope.
+                    scope.$on("$destroy", function () {
+                        // Supprime l'observateur.
+                        clearObserver();
+                    });
+                });
+            }
+        };
+    };
+    vitisApp["compileProvider"].directive("appLinker", vitisApp.appLinkerDrtv);
+
+    /**
+     * Set the locked work esi
+     * @param {string} sModule Module's name to organize work Objects
+     * @param {string} sObjectName Object's name to call work Object
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["setWorkObject"] = function (sModule, sObjectName) {
+
+        var $log = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$log"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var appWorkspaceListScope = angular.element(vitisApp.appWorkspaceListDrtv).scope();
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        var appMainScope = angular.element(vitisApp.appMainDrtv).scope();
+        var config = angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["config"];
+        // Vérifie si le module signaletique est utilisable pour l'utilisateur
+
+        if (!(sessionStorage["application_modules"].split(',').indexOf(sModule) !== -1))
+            return 0;
+        $log.info("setWorkObject for module : " + sModule + " on Object " + sObjectName);
+        var aSelectedRows = appWorkspaceListScope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["getSelectedRows"]();
+        if (!goog.isArray(aSelectedRows)) {
+            console.error('aSelectedRows is not an array');
+            return 0;
+        }
+
+        if (aSelectedRows.length !== 1) {
+            bootbox.alert('<h4>Veuillez sélectionner un(e) unique ' + sObjectName + '</h4>');
+            return 0;
+        }
+
+        var oParams = {
+            'user_id': sessionStorage['user_id']
+        };
+        oParams[config["sFieldId"]] = aSelectedRows[0][config["sFieldId"]];
+        ajaxRequest({
+            "method": "POST",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/" + config["sWebService"],
+            "params": oParams,
+            "success": function (response) {
+                if (!goog.isDef(response['data'])) {
+                    bootbox.alert('<h4>Erreur lors de la définition du ' + sObjectName + ' de travail</h4>');
+                    console.error("response: ", response);
+                }
+                if (goog.isDef(response['data']['errorMessage'])) {
+                    bootbox.alert('<h4>Erreur lors de la définition du ' + sObjectName + ' de travail</h4>' + '<br>' + response['data']['errorType'] + '<br>' + response['data']['errorMessage']);
+                    console.error("response: ", response);
+                }
+                // Recharge la liste
+                angular.element(vitisApp.appWorkspaceListDrtv).scope()["refreshGrid"](appWorkspaceListScope, envSrvc["oGridOptions"][envSrvc["sSelectedGridOptionsName"]]);
+                angular.element("#" + config["sIdButtonLock"]).prop("disabled", true);
+                angular.element("#" + config["sIdButtonUnlock"]).prop("disabled", false);
+                angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["value"] = aSelectedRows[0][config["sFieldId"]];
+                /*appMainScope.$evalAsync(function () {
+                 appMainScope.updateWorkObject();
+                 });*/
+            },
+            "error": function (response) {
+                bootbox.alert('<h4>Erreur lors de la définition du ' + sObjectName + ' de travail:</h4><br>' + response["status"]);
+                console.error("response: ", response["status"]);
+            }
+        });
+    };
+    /**
+     * appPostsEsi directive.
+     * Mise en forme de la colonne "itinéraire" dans la liste de l'onglet "users_user" (Utilisateurs).
+     * @param {service} $translate Translate service.
+     * @ngInject
+     **/
+    vitisApp.appTextPopoverDisplayDrtv = function ($translate) {
+        return {
+            link: function (scope, element, attrs) {
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                var clearObserver = attrs.$observe("text", function () {
+                    if (goog.isDef(attrs["text"]) && attrs["text"] !== "") {
+                        if (goog.isDefAndNotNull(attrs["icon"])) {
+                            element[0].className = "ui-grid-cell-contents " + attrs["icon"];
+                        } else {
+                            element[0].className = "ui-grid-cell-contents info-icon";
+                        }
+
+                        if (attrs["mode"] === 'html' && goog.isDefAndNotNull(attrs["splitter"])) {
+                            attrs["text"] = attrs["text"].split(attrs["splitter"]).join("<br/>");
+                        }
+
+                        $(element)["popover"]({
+                            "trigger": "hover",
+                            "container": "body",
+                            "title": attrs["title"],
+                            "content": function () {
+                                var sContent = "";
+                                sContent = attrs["text"];
+                                return sContent;
+                            },
+                            "html": (attrs["mode"] === 'html'),
+                            // Placement du tooltip à gauche ou à droite suivant la position horizontale de l'élément.
+                            "placement": function (oPopoverNode, oElementNode) {
+                                return scope.$root["workspaceTooltipPlacement"](oElementNode);
+                            }
+                        });
+                    } else {
+                        element[0].className = "";
+                    }
+                    scope.$on("$destroy", function () {
+                        // Supprime le tooltip.
+                        $(element)["popover"]("destroy");
+                        // Supprime l'observateur.
+                        clearObserver();
+                    });
+                });
+            }
+        };
+    };
+    vitisApp["compileProvider"].directive("appTextPopoverDisplay", vitisApp.appTextPopoverDisplayDrtv);
+
+
+    /**
+     * appPostsEsi directive.
+     * Mise en forme de la colonne "itinéraire" dans la liste de l'onglet "users_user" (Utilisateurs).
+     * @param {service} $translate Translate service.
+     * @ngInject
+     **/
+    vitisApp.appNavBarDrtv = function ($translate) {
+        return {
+            replace: true,
+            template: '<div class="progress" style="margin: 5px 10px 10px;position:relative">' +
+                    '<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width:{{row.entity[col.field]}}%"></div>' +
+                    '<div style="font-weight:700;position:absolute;width:100%;text-align:center;top:2px;">{{textValue}}</div>' +
+                    '</div>',
+            link: function (scope, element, attrs) {
+
+                scope.textValue = (goog.isDefAndNotNull(attrs["hidevalue"])) ? "" : scope["row"]["entity"][scope["col"]["field"]] + "%";
+
+                if (goog.isDefAndNotNull(attrs["mode"]))
+                    element[0].firstChild.className = element[0].firstChild.className + " progress-bar-" + attrs["mode"];
+
+                if (goog.isDefAndNotNull(attrs["striped"])) {
+                    element[0].firstChild.className = element[0].firstChild.className + " progress-bar-striped"; // Not available in IE9 and below
+                    if (goog.isDefAndNotNull(attrs["active"])) {
+                        element[0].firstChild.className = element[0].firstChild.className + " active"; // Not available in IE9 and below
+                    }
+                }
+            }
+        };
+    };
+    vitisApp["compileProvider"].directive("appNavbar", vitisApp.appNavBarDrtv);
+
+    /**
+     * durationCalculator directive.
+     * Mise en forme de la colonne "itinéraire" dans la liste de l'onglet "users_user" (Utilisateurs).
+     * @param {service} $translate Translate service.
+     * @ngInject
+     **/
+    vitisApp.durationCalculator = function ($translate) {
+        return {
+            replace: true,
+            scope: {"value": "=appDurationCalculator"},
+            template: '<div> {{duration}} </div>',
+            link: function (scope, element, attrs) {
+                scope.$watch("value", function (val) {
+                    var aDuration = [/*0,*/0, 0, 0];
+                    var aNbSecondPerPeriod = [/*86400,*/3600, 60, 1];
+                    var i = 0
+                    scope["duration"] = "";
+                    // duration in second
+                    if (goog.isDefAndNotNull(scope["value"])) {
+                        if (scope["value"] >= 0) {
+                            // set first value to the total duration
+                            aDuration[0] = scope["value"];
+                            // calculation loop
+                            while (i < aNbSecondPerPeriod.length) {
+                                //Calculation
+                                var iValNext = aDuration[i] % aNbSecondPerPeriod[i];
+                                var iValCurrent = (aDuration[i] - iValNext) / aNbSecondPerPeriod[i];
+
+                                //console.log(i + " : next " + iValNext + " current " + iValCurrent)
+
+                                aDuration[i] = (iValCurrent < 10) ? "0" + iValCurrent : "" + iValCurrent;
+
+                                if (iValNext === 0) {
+                                    break
+                                } else {
+                                    aDuration[i + 1] = iValNext;
+                                }
+                                i++;
+                            }
+                            scope["duration"] = aDuration.join(":");
+                        } else {
+                            scope["duration"] = "NEG_VAL";
+                        }
+                    }
+                });
+            }
+        }
+    };
+    vitisApp["compileProvider"].directive("appDurationCalculator", vitisApp.durationCalculator);
+
+    /**
+     * Clear the locked work Object
+     * @param {string} sModule Module's name to organize work Objects
+     * @param {string} sObjectName Object's name to call work Object
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["clearWorkObject"] = function (sModule, sObjectName) {
+
+        var $log = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$log"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var appWorkspaceListScope = angular.element(vitisApp.appWorkspaceListDrtv).scope();
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        var appMainScope = angular.element(vitisApp.appMainDrtv).scope();
+        var config = angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["config"];
+        // Vérifie si le module pdesi est utilisable pour l'utilisateur
+        if (!(sessionStorage["application_modules"].split(',').indexOf(sModule) !== -1))
+            return 0;
+        $log.info("clearWorkPost for module : " + sModule + " on Object " + sObjectName);
+        ajaxRequest({
+            "method": "DELETE",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/" + config["sWebService"] + "/" + sessionStorage['user_id'],
+            "success": function (response) {
+                if (!goog.isDef(response['data'])) {
+                    bootbox.alert('<h4>Erreur lors de la libération du ' + sObjectName + ' de travail</h4>');
+                    console.error("response: ", response);
+                }
+                if (goog.isDef(response['data']['errorMessage'])) {
+                    bootbox.alert('<h4>Erreur lors de la libération du ' + sObjectName + ' de travail</h4>' + '<br>' + response['data']['errorType'] + '<br>' + response['data']['errorMessage']);
+                    console.error("response: ", response);
+                }
+
+                // Recharge la liste
+                angular.element(vitisApp.appWorkspaceListDrtv).scope()["refreshGrid"](appWorkspaceListScope, envSrvc["oGridOptions"][envSrvc["sSelectedGridOptionsName"]]);
+                angular.element("#" + config["sIdButtonLock"]).prop("disabled", false);
+                angular.element("#" + config["sIdButtonUnlock"]).prop("disabled", true);
+                angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["value"] = false;
+                // Update le workObject et affiche ou pas les boutons ajouter et supprimer de la liste ESI
+                /*appMainScope.$evalAsync(function () {
+                 appMainScope.updateWorkObject();
+                 });*/
+            },
+            "error": function (response) {
+                bootbox.alert('<h4>Erreur lors de la libération du ' + sObjectName + ' de travail:</h4><br>' + response["status"]);
+                console.error("response: ", response["status"]);
+            }
+        });
+    };
+
+    /**
+     * initialize a work Object
+     * @param {string} sModule Module's name to organize work Objects
+     * @param {string} sObjectName Object's name to call work Object
+     * @param {object} oParams Parameters needed to use function set clear and look
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["initWorkObject"] = function (sModule, sObjectName, oParams) {
+        if (!goog.isDefAndNotNull(angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"]))
+            angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"] = {};
+        angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule] = {};
+        angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName] = {};
+        angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["value"] = false;
+        angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["config"] = oParams;
+    };
+
+    /**
+     * return value of a work Object
+     * @param {string} sModule Module's name to organize work Objects
+     * @param {string} sObjectName Object's name to call work Object
+     * @return {integer / boolean} false if workObject is empty or id of workObject Selected
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["getWorkObject"] = function (sModule, sObjectName) {
+        return angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["value"];
+    };
+
+    /**
+     * test if a work Object is already exist for a defined Object
+     * @param {string} sModule Module's name to organize work Objects
+     * @param {string} sObjectName Object's name to call work Object
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["lookWorkObjectIsAlreadyLock"] = function (sModule, sObjectName) {
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var config = angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["config"];
+        ajaxRequest({
+            "method": "GET",
+            'headers': {'Accept': "application/x-vm-json"},
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/" + config["sWebService"],
+            "params": {
+                "filter": {
+                    "relation": "AND",
+                    "operators": [{
+                            "column": "user_id",
+                            "compare_operator": "=",
+                            "value": sessionStorage['user_id']
+                        }]
+                },
+                'distinct': true
+            },
+            "success": function (response) {
+                if (!goog.isDef(response['data'])) {
+                    bootbox.alert('<h4>Erreur lors de la définition du ' + sObjectName + '</h4>');
+                    console.error("response: ", response);
+                }
+                if (goog.isDef(response['data']['errorMessage'])) {
+                    bootbox.alert('<h4>Erreur lors de la définition du ' + sObjectName + '</h4>' + '<br>' + response['data']['errorType'] + '<br>' + response['data']['errorMessage']);
+                    console.error("response: ", response);
+                }
+
+                if (response["data"]["list_count"] === 1) {
+                    angular.element(vitisApp.appMainDrtv).scope()["oWorkObjects"][sModule][sObjectName]["value"] = response["data"]["data"][0][config["sFieldId"]];
+                    angular.element("#" + config["sIdButtonLock"]).prop("disabled", true);
+                    angular.element("#" + config["sIdButtonUnlock"]).prop("disabled", false);
+                } else {
+                    angular.element("#" + config["sIdButtonLock"]).prop("disabled", false);
+                    angular.element("#" + config["sIdButtonUnlock"]).prop("disabled", true);
+                }
+            },
+            "error": function (response) {
+                bootbox.alert('<h4>Erreur lors de la récupération du ' + sObjectName + ':</h4><br>' + response["status"]);
+                console.error("response: ", response["status"]);
+            }
+        });
+    };
+
+    /**
+     * loadHelp function.
+     * Chargement des sections du mode "help".
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadHelp"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("loadHelp");
+        // Passage en mode "Update" (pour afficher les sections).
+        envSrvc["sMode"] = "update";
+    };
+
+    angular.element(vitisApp.appMainDrtv).scope().getProj = function () {
+        var appMainScope = angular.element(vitisApp.appMainDrtv).scope();
+        // Get fichier de langue
+        ajaxRequest({
+            "method": "GET",
+            "url": "modules/vitis/data/proj.json",
+            "scope": appMainScope,
+            "success": function (response) {
+                // Utilisé par les autres cpmposants
+                appMainScope['proj'] = response["data"];
+            },
+            "error": function (response) {
+                console['error']('ERROR : (AJAX request : ' + response["status"] + ' ) On loading Projections, contact Veremes please');
+            }
+        });
+    };
+    angular.element(vitisApp.appMainDrtv).scope().getProj();
+
+    /**
+     * deleteUsers function.
+     * Suppression des utilisateurs sélectionnés (sauf l'utilisateur connecté).
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["deleteUsers"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var userSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["userSrvc"]);
+        //
+        $log.info("deleteUsers");
+        // Désélectionne l'utilisateur connecté.
+        var scope = angular.element(vitisApp.appWorkspaceListDrtv).scope();
+        var aSelectedRows = scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["getSelectedRows"]();
+        var bDeleteUsers = true;
+        aSelectedRows.forEach(function (oRow) {
+            if (oRow["user_id"] == userSrvc["id"]) {
+                bDeleteUsers = false;
+                scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["unSelectRow"](oRow);
+                $translate(["ERROR_DELETING_OWN_USER"]).then(function (aTranslations) {
+                    var oOptions = {
+                        "className": "modal-danger",
+                        "message": aTranslations["ERROR_DELETING_OWN_USER"]
+                    };
+                    scope.$root["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+                });
+            }
+        });
+        // Supprime les utilisateurs.
+        if (bDeleteUsers)
+            scope.$root["DeleteSelection"]();
+    };
+
+    /**
+     * hideCurrentUserFromExcludedPrivileges function.
+     * Cache l'utilisateur connecté de la liste "Utilisateurs liés au groupe" (Utilisateurs > Privilèges).
+     * @param {string} sFormElementName Nom du champ de formulaire.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["hideCurrentUserFromExcludedPrivileges"] = function (sFormElementName) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $timeout = angular.element(vitisApp.appMainDrtv).injector().get(["$timeout"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var userSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["userSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("hideCurrentUserFromExcludedPrivileges");
+        //
+        // Privilèges à exclure.
+        var aUserPrivileges = ["vitis_admin", "vitis_user"];
+        if (aUserPrivileges.indexOf(envSrvc["sId"]) != -1) {
+            // Attends un cycle de "$digest".
+            $timeout(function () {
+                // Id et nom des 2 <select>.
+                var oFormElementDefinition = formSrvc["getFormElementDefinition"](sFormElementName, envSrvc["sFormDefinitionName"]);
+                var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+                var aSelectId = [oFormElementDefinition["id"], oFormElementDefinition["id_from"]];
+                var aSelectName = [sFormElementName, oFormElementDefinition["name_from"]];
+                // Cache les privilèges exclus dans les 2 <select>.
+                var i, oSelect;
+                var j = 0;
+                while (j < aSelectId.length) {
+                    i = 0;
+                    oSelect = document.getElementById(aSelectId[j]);
+                    while (oSelect.options.length > i) {
+                        oSelect.options[i].style.display = "";
+                        if (userSrvc["id"] == oSelect.options[i].value) {
+                            oSelect.options[i].style.display = "none";
+                            oFormValues[aSelectName[j]]["options"][i]["disabled"] = true;
+                        }
+                        i++;
+                    }
+                    j++;
+                }
+            });
+        }
+    };
+    /**
+     * loadModes function.
+     * Chargement de la section "Calques de la carte" dans l'onglet "Cartes".
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadModes"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("loadModes");
+        var scope = this;
+        // Classe spécifique pour séparer la liste ui-grid de la liste des sections.
+        var oSectionContainer = document.getElementById("container_section_" + envSrvc["oSelectedObject"]["name"] + "_modes");
+        oSectionContainer.className = oSectionContainer.className + " section-container-workspace-list";
+
+        // Paramétrage du module ui-grid
+        scope["gridOptions"] = {
+            "enableRowSelection": true,
+            "enableSelectAll": false,
+            "enablePagination": false,
+            "enablePaginationControls": false,
+            "multiSelect": false,
+            "useExternalPagination": true,
+            "paginationPageSize": 999, // Pas de pagination
+            "enableColumnMenus": false,
+            "enableColumnResizing": false,
+            "appHeader": true,
+            "appHeaderTitleBar": true,
+            "appHeaderSearchForm": false,
+            "appHeaderOptionBar": false,
+            "appLoadGridData": true,
+            //"oFilter": ["action=getAll"],
+            "appGridTitle": "LIST_TITLE_GRID_MODES",
+            "appFooter": false,
+            "appShowPagination": false,
+            "appEnableDragAndDrop": true,
+            "appDragAndDropEvent": {
+                "rowFinishDrag": "updateModesSorting"
+            },
+            "appActions": [],
+            "oUrlParams": {
+                "action": "getAll",
+                "distinct": true,
+                "order_by": "index",
+                "sort_order": "ASC"
+            }
+        };
+        // Pas de chargement de données.
+        scope["bLoadFormValues"] = false;
+
+        // Id de traduction des libellés des colonnes de la liste.
+        var aTranslationsId = ["LIST_MODE_ICONE_MODE_CONFIGURATION",
+            "LIST_MODE_ID_MODE_CONFIGURATION",
+            "LIST_MODE_INDEX_CONFIGURATION"
+        ];
+        // Définition des colonnes de la liste.
+        $translate(aTranslationsId).then(function (aTranslations) {
+            scope["gridOptions"]["columnDefs"] = [
+                {"name": aTranslations["LIST_MODE_INDEX_CONFIGURATION"], "displayName": aTranslations["LIST_MODE_INDEX_CONFIGURATION"], "field": "index", "visible": false, "width": 50, "enableSorting": false, "type": "number", "enableColumnMoving": false, "enableColumnResizing": false, "headerCellClass": "vitis_mode_" + envSrvc["oSelectedObject"]["name"] + "_index"},
+                {"name": aTranslations["LIST_MODE_ID_MODE_CONFIGURATION"], "displayName": aTranslations["LIST_MODE_ID_MODE_CONFIGURATION"], "field": "mode_id", "width": 300, "enableSorting": false, "type": "string", "enableColumnMoving": false, "enableColumnResizing": false, "headerCellClass": "vitis_mode_" + envSrvc["oSelectedObject"]["name"] + "_mode_id"},
+                {"name": aTranslations["LIST_MODE_ICONE_MODE_CONFIGURATION"], "displayName": aTranslations["LIST_MODE_ICONE_MODE_CONFIGURATION"], "field": "mode_id", "width": 50, "enableSorting": false, "type": "number", "enableColumnMoving": false, "enableColumnResizing": false, "headerCellClass": "vitis_mode_" + envSrvc["oSelectedObject"]["name"] + "_index", "cellClass": "cell-align-center", "cellTemplate": "<div style=\"font-size:16px;color:#9a9a9a;margin-top:5px;vertical-align:middle\" class=\"icon-{{row.entity[col.field]}}\"></div>"}
+            ];
+        });
+    };
+
+    /**
+     * updateModesSorting function.
+     * Change l'ordre des calques sélectionnés d'une carte.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["updateModesSorting"] = function () {
+        //
+        $log.info("updateMapLayerSorting");
+        var scope = this;
+        // Sauve la liste des id des modes.
+        var oGridOptions = envSrvc["oGridOptions"][envSrvc["sSelectedGridOptionsName"]];
+        var i = 0, aModesId = [];
+        while (i < oGridOptions["data"].length) {
+            aModesId.push(oGridOptions["data"][i]["mode_id"]);
+            i++;
+        }
+
+        // Mise à jour de l'index des calques de la carte dans la base.
+        ajaxRequest({
+            "method": "PUT",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/modes/sorting",
+            "data": {"modes_id": aModesId.join("|")},
+            "scope": scope,
+            "success": function (response) {
+                // Erreur ?
+                if (response["data"]["status"] === 0) {
+                    var oOptions = {
+                        "className": "modal-danger",
+                        "message": response["data"]["errorMessage"]
+                    };
+                    scope["modalWindow"]("dialog", "ERROR_ADD_MAP_LAYERS_VMAP_MAP_MAP_LAYERS", oOptions);
+                }
+            }
+        });
+    };
+
+    /**
+     * reloadSectionForm function.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()['reloadWebsocketStatus'] = function () {
+        var i = 0;
+        var tryReloadWebsocketStatus = function () {
+            if (i > 10) {
+                return 0;
+            }
+            var websocketConfigScope = angular.element($('[data-app-websocket-configuration=""]')).scope();
+            if (goog.isDefAndNotNull(websocketConfigScope)) {
+                if (goog.isDefAndNotNull(websocketConfigScope['ctrl'])) {
+                    angular.element($('[data-app-websocket-configuration=""]')).scope()['ctrl']['reloadWebsocketStatus']();
+                } else {
+                    setTimeout(function () {
+                        tryReloadWebsocketStatus();
+                    }, 500);
+                }
+            } else {
+                setTimeout(function () {
+                    tryReloadWebsocketStatus();
+                }, 500);
+            }
+            i++;
+        };
+        setTimeout(function () {
+            tryReloadWebsocketStatus();
+        });
+    };
+
+    /**
+     * checkSmtpServerConnection function.
+     * Vérification de la connexion au serveur Smtp.
+     */
+    angular.element(vitisApp.appWorkspaceListDrtv).scope()["checkSmtpServerConnection"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        // Log.
+        $log.info("checkSmtpServerConnection");
+        // Charge le résumé de la supervision.
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/smtpserver/Check",
+            "success": function(response) {
+                if (response["data"]["status"] === 0) {
+                    var oOptions = {
+                        "className": "modal-danger",
+                        "message": response["data"]["errorMessage"]
+                    };
+                    $rootScope["modalWindow"]("alert", "MODAL_TITLE_CHECK_SMTP_CONNECTION_CONFIGURATION", oOptions);
+                }
+                else {
+                    // Affichage du message de succés.
+                    $translate("MODAL_CONTENT_SUCCESS_CHECK_SMTP_CONNECTION_CONFIGURATION").then(function (sTranslation) {
+                        $.notify(sTranslation, "success");
+                    });
+                }
+            }
+        });
+    };
+
+    /**
+     * callBoMethod function.
+     * call a method define in WAB for a workflow.
+     * @expose
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["callBoMethod"] = function (sMethod) {
+        // the button that call this method have to be a submit button
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+
+        // ajout dynamique d'un faux champ caché pour envoi de la méthode au serveur
+        var aMethodFields = {"fields":[{
+            "type": "hidden",
+            "name": "tr_status_method"
+        }]};
+
+        envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["rows"].push(aMethodFields);
+        envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["tr_status_method"] = sMethod;
+        // l'event submit du formulaire sera appelé après cette fonction 
+    };
+});
\ No newline at end of file
diff --git a/client/modules/vitis/lang/lang-en.json b/client/modules/vitis/lang/lang-en.json
new file mode 100755
index 00000000..c8132242
--- /dev/null
+++ b/client/modules/vitis/lang/lang-en.json
@@ -0,0 +1,330 @@
+{
+    "TITLE_MODE_USER": "User",
+    "TITLE_MODE_USERS": "Users",
+    "TITLE_MODE_CONFIGURATION": "Settings",
+    "TITLE_MODE_LOGS": "Logs",
+    "TITLE_MODE_HELP": "Help",
+    "TEXT_MODE_USER": "User settings",
+    "TEXT_MODE_USERS": "User management",
+    "TEXT_MODE_CONFIGURATION": "Configure the settings",
+    "TEXT_MODE_LOGS": "Daily application logs",
+    "TEXT_MODE_HELP": "{{app_name}} help",
+    "": "",
+    "FILE_TOO_BIG_LOGS": "The file is too big to be visualized.",
+    "DELETE_FILE_SUCCESS_LOGS": "The file was successfully deleted.",
+    "DELETE_FILES_SUCCESS_LOGS": "The files were successfully deleted.",
+    "DELETE_FILE_ERROR_LOGS": "Error while deleting the file.",
+    "DELETE_FILES_ERROR_LOGS": "Error while deleting the files.",
+    "LOADING_FILE_ERROR_LOGS": "Error while downloading the file.",
+    "DELETE_FILE_CONFIRM_LOGS": "Delete file?",
+    "DELETE_HISTORY_CONFIRM_LOGS": "Delete files older than {{min_days_files}} days?",
+    "FILE_NOT_FOUND_LOGS": "File not found.",
+    "FORM_TITLE_LOGS": "Logs",
+    "FORM_BTN_DELETE_HISTORY_LOGS": "Delete history",
+    "FORM_BTN_REFRESH_LOGS": "Refresh logs",
+    "FORM_BTN_DELETE_FILE_LOGS": "Delete file",
+    "DELETE_FILE_ERROR_PERMISSION_DENIED_LOGS": "Can not Delete the file (permission denied)",
+    "": "",
+    "SECTION_UPDATE_TITLE_USERS_VITIS_GROUP": "Group n°{{sId}}",
+    "SECTION_DISPLAY_TITLE_USERS_VITIS_GROUP": "Group n°{{sId}}",
+    "SECTION_INSERT_TITLE_USERS_VITIS_GROUP": "Group",
+    "SECTION_UPDATE_TITLE_HELP_VITIS_HELP": "Help",
+    "SECTION_UPDATE_TITLE_USERS_VITIS_USERS": "User n°{{sId}}",
+    "SECTION_DISPLAY_TITLE_USERS_VITIS_USERS": "User n°{{sId}}",
+    "SECTION_INSERT_TITLE_USERS_VITIS_USERS": "User",
+    "": "",
+    "SECTION_UPDATE_TITLE_CONFIGURATION_VITIS_CONFIGURATION": "Setting",
+    "FORM_GENERAL_SECTION_CONFIGURATION": "General",
+    "FORM_APP_NAME_CONFIGURATION": "Application name",
+    "FORM_INSTANCE_IDENTIFIER_CONFIGURATION": "Application Identifier(Used when we notice administrator)",
+    "FORM_LANGUAGE_CONFIGURATION": "Language",
+    "FORM_COOKIE_LIFETIME_CONFIGURATION": "Session lifetime in minutes",
+    "FORM_COOKIE_PATH_CONFIGURATION": "Cookies reach",
+    "FORM_MAX_UPLOAD_FILE_SIZE_CONFIGURATION": "Max uploaded file size in Mb",
+    "FORM_MAX_EXECUTION_TIME_CONFIGURATION": "Max execution time in seconds",
+    "FORM_MAX_REQUEST_TIME_CONFIGURATION": "Max request timeout in seconds",
+    "FORM_REFRESH_PERIOD_CONFIGURATION": "GUI refresh period in seconds",
+    "FORM_MINIMUM_REFRESH_PERIOD_CONFIGURATION": "Grids minimum refresh period in milliseconds",
+    "FORM_FORBIDDEN_EXTENSION_CONFIGURATION": "File extensions denied",
+    "FORM_ROWS_PER_PAGE_CONFIGURATION": "Number of rows per page",
+    "FORM_WEB_SERVER_NAME_CONFIGURATION": "Server base URL",
+    "FORM_VAS_HOME_CONFIGURATION": "VAS directory",
+    "FORM_WEB_SERVER_UPLOAD_DIRECTORY_CONFIGURATION": "Upload directory path",
+    "FORM_DATE_FORMAT_CONFIGURATION": "Date format",
+    "FORM_SIGN_UP_CONFIGURATION" : "Enabled sign up ?",
+    "FORM_SIGN_UP_CONFIGURATION_YES" : "Yes",
+    "FORM_SIGN_UP_CONFIGURATION_NO" : "No",
+    "FORM_FPWD_CONFIGURATION" : "Enabled password recuperation ?",
+    "FORM_FPWD_CONFIGURATION_YES" : "Yes",
+    "FORM_FPWD_CONFIGURATION_NO" : "No",
+    "FORM_REMEMBER_ME_CONFIGURATION" : "Enabled remember me ?",
+    "FORM_REMEMBER_ME_DEFAULT_CONFIGURATION" : "Remember me default value",
+    "FORM_LOG_SECTION_CONFIGURATION": "Log",
+    "FORM_LOG_MODE_CONFIGURATION": "Write log files",
+    "FORM_LOG_MODE_TRUE_CONFIGURATION": "Yes",
+    "FORM_LOG_MODE_FALSE_CONFIGURATION": "No",
+    "FORM_DEBUG_MODE_CONFIGURATION": "Debug mode",
+    "FORM_DEBUG_MODE_TRUE_CONFIGURATION": "Yes",
+    "FORM_DEBUG_MODE_FALSE_CONFIGURATION": "No",
+    "FORM_LOG_PERIOD_CONFIGURATION": "Log period",
+    "FORM_LOG_SIZE_CONFIGURATION": "Max log files size to show (in Ko)",
+    "FORM_HTTP_SERVER_SECTION_CONFIGURATION": "Http server",
+    "FORM_CLIENT_ALIAS_CONFIGURATION": "Alias on client directory (only used by Rest API)",
+    "FORM_UPDATE_ALIAS_CONFIGURATION": "Alias on update directory",
+    "FORM_PUBLIC_ALIAS_CONFIGURATION": "Alias on public directory",
+    "FORM_SHARED_DIR_CONFIGURATION": "Shared Directory",
+    "FORM_UPDATE_SECTION_CONFIGURATION": "Update",
+    "FORM_WEB_SERVER_UPDATE_CONFIGURATION": "Update URL server ",
+    "FORM_SECURITY_SECTION_CONFIGURATION": "Security",
+    "FORM_MIXED_RIGHTS_MANAGEMENT_CONFIGURATION": "Authorize domain users to belong to local groups (mixed management)",
+    "FORM_ALLOW_PUBLIC_CONNECTION_CONFIGURATION": "Authorize public connexion",
+    "FORM_PUBLIC_LOGIN_CONFIGURATION": "Public account",
+    "FORM_PUBLIC_PASSWORD_CONFIGURATION": "Public account password",
+    "FORM_TEST_CONNECTION_CONFIGURATION": "Test connection",
+    "FORM_DATABASE_TITLE_CONFIGURATION": "Database",
+    "FORM_SGBD_CONFIGURATION": "SGBD",
+    "FORM_SERVER_CONFIGURATION": "Server",
+    "FORM_PORT_CONFIGURATION": "Port",
+    "FORM_SCHEMA_CONFIGURATION": "Schema",
+    "FORM_MIXED_RIGHTS_MANAGEMENT_TRUE_CONFIGURATION": "Yes",
+    "FORM_MIXED_RIGHTS_MANAGEMENT_FALSE_CONFIGURATION": "No",
+    "FORM_EXTRACT_DIR_CONFIGURATION": "Temporary directory",
+    "FORM_PUBLIC_TOKEN_CONFIGURATION": "Public token",
+    "FORM_SERVICES_ALIAS_CONFIGURATION": "Alias on api_rest directory (only used by Rest API)",
+    "FORM_DOC_ALIAS_CONFIGURATION": "Alias on doc directory",
+    "FORM_ERROR_FILE_WRITING_CONFIGURATION": "Writing error of the properties.inc file",
+    "PAGE_RELOAD_CONFIRM_CONFIGURATION": "Vous avez changé la langue de l'application.<br>La page doit être actualisée pour appliquer la mise à jour des propriétés.",
+    "FORM_APACHE_LOG_DIRECTORIE_CONFIGURATION": "Directory Apache logs",
+    "FORM_PRIVATE_CAPTCHA_KEY_CONFIGURATION": "ReCaptcha secret key (Google)",
+    "FORM_WS_DATA_ALIAS_CONFIGURATION": "Alias on data directory",
+    "PUBLIC_TOKEN_TOOLTIP_TITLE_CONFIGURATION": "Public token",
+    "PUBLIC_TOKEN_TOOLTIP_CONTENT_CONFIGURATION": "The accepted characters are the numbers and the letters as well as the characters '-' and ','",
+    "FORM_PROXY_CHECK_SSL_CONFIGURATION": "Verify the validity of the SSL certificate",
+    "FORM_PROXY_CHECK_SSL_TRUE_CONFIGURATION": "Yes",
+    "FORM_PROXY_CHECK_SSL_FALSE_CONFIGURATION": "No",
+    "PROXY_CHECK_SSL_TOOLTIP_TITLE_CONFIGURATION": "Validity of the SSL certificate",
+    "PROXY_CHECK_SSL_TOOLTIP_CONTENT_CONFIGURATION": "Verify the validity of the SSL certificate for requests sent to the proxy server.",
+	"FORM_TIMEZONE_ID_CONFIGURATION" : "Time zone",	"FORM_SMTP_AUTHENTIFICATION_TRUE_CONFIGURATION": "Yes",
+    "FORM_SMTP_AUTHENTIFICATION_FALSE_CONFIGURATION": "No",
+	"": "",
+    "VERSION_SECTION_TITLE_VERSION_CONFIGURATION": "Version",
+    "CLIENT_VERSION_CONFIGURATION": "Client : ",
+    "BUILD_VERSION_CONFIGURATION": "Build : ",
+    "NO_NEEDED_UPDATE_CONFIGURATION": "Your application is up to date",
+    "NEEDED_UPDATE_CONFIGURATION": "An update (version {{appVersion}}) is available on the site of veremes",
+    "ERROR_RETRIEVE_UPDATE_CONFIGURATION": "An error was encountered while checking for updates",
+    "INSTALLATION_SECTION_TITLE_VERSION_CONFIGURATION": "Installation status",
+    "PHP_VERSION_CONFIGURATION": "PHP {{php_version}}",
+    "PDO_VERSION_CONFIGURATION": "PDO",
+    "POSTGRESQL_PDO_VERSION_CONFIGURATION": "PDO for PostgreSQL",
+    "CURL_VERSION_CONFIGURATION": "cURL",
+    "POSTGRESQL_VERSION_CONFIGURATION": "PostgreSQL {{postgresql_version}}",
+    "LDAP_VERSION_CONFIGURATION": "LDAP (optional)",
+    "POSTGIS_VERSION_CONFIGURATION": "PostGIS {{postgis_version}} (optional)",
+    "SERVER_INFORMATIONS_SECTION_TITLE_VERSION_CONFIGURATION": "Server informations",
+    "OS_VERSION_CONFIGURATION": "Operating system : ",
+    "DISK_VERSION_CONFIGURATION": "Disk informations : ",
+    "DISK_VERSION_CONFIGURATION_VALUE": "{{::disk_free_space}} available on {{::disk_total_space}}",
+    "WEB_SERVER_SECTION_TITLE_VERSION_CONFIGURATION": "Web server",
+    "SERVER_ADDR_VERSION_CONFIGURATION": "IP: ",
+    "SERVER_NAME_VERSION_CONFIGURATION": "Name: ",
+    "SERVER_PORT_VERSION_CONFIGURATION": "Port: ",
+    "": "",
+    "FORM_DELETE_LOGS_LOG": "Delete files older than",
+    "FORM_DAYS_LOGS_LOG": "Days",
+    "": "",
+    "UPDATE_PASSWORD_USER_USER": "You are modifying your user's password.<br>You will be logged out.<br>Do you wish to continue?",
+    "ERROR_PASSWORD_CONFIRM_USER_USER": "The confirmation password is different than the password",
+    "WARNING_PASSWORD_CHANGE_USER_USER": "Modifying your password",
+    "FORM_LOGIN_USER_USER": "User",
+    "FORM_NAME_USER_USER": "Name",
+    "FORM_EMAIL_USER_USER": "Email",
+    "FORM_AGENCY_USER_USER": "Company",
+    "FORM_DEPARTMENT_USER_USER": "Department",
+    "FORM_USER_PASSWORD_USER_USER": "Password",
+    "FORM_USER_CONFIRM_PASSWORD_USER_USER": "Password confirmation",
+    "FORM_INFORMATIONS_USER_USER": "Informations",
+    "FORM_NEW_PASSWORD_USER_USER": "New password",
+    "FORM_DATAENCRYPT_USER_USER" : "Data encryption",
+    "FORM_SECRETKEY_USER_USER" : "Secret key",
+    "FORM_BILLINGGROUP_ID_USERS_USER" : "Billing Group",
+    "FORM_ACCEPTNOTIFICATION_USER_USER" : "Do you want be notified by SMS ?",
+    "FORM_PHONE_USER_USER" : "Telephone number (for SMS) in international E.164 format (+33 6 xx xx xx xx)",
+    "FORM_TIMEZONE_ID_USER_USER" : "Time Zone",
+    "FORM_FORMATDATE_ID_USER_USER" : "Date display format",
+    "": "",
+    "USER_ROLE_TOOLTIP_TITLE_USERS_USER": "Description",
+    "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER": "Administrator",
+    "USER_ROLE_USER_TOOLTIP_CONTENT_USERS_USER": "User",
+    "FORM_LOGIN_ACTIVE_DIRECTORY_CONNECTION": "User",
+    "FORM_PASSWORD_ACTIVE_DIRECTORY_CONNECTION": "Password",
+    "TITLE_ACTIVE_DIRECTORY_CONNECTION": "AD connection",
+    "FORM_CONNECTION_ACTIVE_DIRECTORY_CONNECTION": "Connection",
+    "TITLE_SECTION_ACTIVE_DIRECTORY_USERS_VITIS_USERS": "AD server",
+    "ERROR_BIND_ACTIVE_DIRECTORY_USERS_USER": "Error while trying to bind",
+    "ERROR_INVALID_CREDENTIALS_ACTIVE_DIRECTORY_USERS_USER": "Invalid credentials",
+    "ERROR_CONTACT_DOMAIN_ACTIVE_DIRECTORY_USERS_USER": "Can't contact LDAP server",
+    "ERROR_ERROR_DOMAIN_ACTIVE_DIRECTORY_USERS_USER": "Error domain name",
+    "TITLE_TAB_TREE_ACTIVE_DIRECTORY_USERS_USER": "Browsing in the tree",
+    "TITLE_TAB_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Search",
+    "NAME_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Name",
+    "ACCOUNT_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Account",
+    "EMAIL_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "E-mail",
+    "AGENCY_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Agency",
+    "DEPARTMENT_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Department",
+    "GROUP_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Name of the group",
+    "FORM_ACCOUNT_ACTIVE_DIRECTORY_USERS_USER": "Account",
+    "FORM_GROUP_ACTIVE_DIRECTORY_USERS_USER": "Groups",
+    "FORM_DEPARTMENT_ACTIVE_DIRECTORY_USERS_USER": "Department",
+    "FORM_SEARCH_BTN_ACTIVE_DIRECTORY_USERS_USER": "Search",
+    "FORM_ACCOUNT_INFO_ACTIVE_DIRECTORY_USERS_USER": "Seize the beginning of the account",
+    "FORM_GROUP_INFO_ACTIVE_DIRECTORY_USERS_USER": "Groups list, separated by commas",
+    "FORM_DEPARTMENT_INFO_ACTIVE_DIRECTORY_USERS_USER": "Seize the beginning of the department name",
+    "BTN_IMPORT_SELECTION_ACTIVE_DIRECTORY_USERS_VITIS_USERS": "Import",
+    "SUCCESFULL_IMPORTATION_ACTIVE_DIRECTORY_USERS_VITIS_USERS": "Import successfully done",
+    "FORM_ACTIVE_DIRECTORY_USER_GROUPS_USERS_USER": "Member of the domain groups",
+    "FORM_ALL_USER_GROUPS_USERS_USER": "Synthesis of the memberships",
+    "FORM_DOMAIN_ACTIVE_DIRECTORY_CONNECTION": "Domain",
+    "FORM_LOGIN_USERS_USER": "User",
+    "FORM_NAME_USERS_USER": "Name",
+    "FORM_EMAIL_USERS_USER": "Email",
+    "FORM_AGENCY_USERS_USER": "Company",
+    "FORM_DEPARTMENT_USERS_USER": "Department",
+    "FORM_DOMAIN_USERS_USER": "Domain",
+    "FORM_IP_USERS_USER": "Workstation IP address",
+    "FORM_ID_USERS_USER": "ID",
+    "FORM_LAST_CONNECTION_USERS_USER": "Last connection",
+    "FORM_LOCAL_GROUPS_USERS_USER": "Local groups",
+    "FORM_GROUPS_AVAILABLE_USERS_USER": "Not member of the groups",
+    "FORM_GROUPS_USER_USERS_USER": "Member of the groups",
+    "FORM_PRIVILEGES_USERS_USER": "Privileges",
+    "FORM_PRIVILEGES_AVAILABLE_USERS_USER": "Available privileges",
+    "FORM_PRIVILEGES_USER_USERS_USER": "Privileges linked to the user",
+    "FORM_NEW_PASSWORD_USERS_USER": "New password",
+    "FORM_USER_PASSWORD_USERS_USER": "Password",
+    "FORM_USER_CONFIRM_PASSWORD_USERS_USER": "Password confirmation",
+    "FORM_GROUPS_USERS_USER": "Groups",
+    "FORM_ACCEPTNOTIFICATION_USERS_USER" : "Enable SMS notification for this user?",
+    "FORM_PHONE_USERS_USER" : "Telephone number (for SMS) in international E.164 format (+33 6 xx xx xx xx)",
+    "FORM_TITLE_USERS_USER": "User {{::login}}",
+    "FORM_IP_TOOLTIP_USERS_USER": "Allowed IP V4 address or regular expression.<br>Example: ^193.248.208<br>.Empty : all addresses are allowed.",
+    "FORM_RESTRICTION_USERS_USER": "Restriction",
+    "FORM_RESTRICTION_TOOLTIP_USERS_USER": "Ce champ peut être utilisé pour restreindre l'accès de l'utilisateur à certaines données.<br>Le mécanisme de filtre doit être implémenté dans un traitement GTF ou dans un module de vMap (cadastre par exemple).<br>La syntaxe à utiliser dépend de la nature du filtre.<br>Consulter la documentation ou le support technique pour avoir plus d'information sur les possibilités de filtre des données.",
+    "FORM_TIMEZONE_ID_USERS_USER" : "Time Zone",
+    "FORM_FORMATDATE_ID_USERS_USER" : "Date display format",
+    "": "",
+    "TITLE_SECTION_ACTIVE_DIRECTORY_USERS_GROUP": "AD server",
+    "FORM_GROUP_ACTIVE_DIRECTORY_USERS_GROUP": "Group",
+    "FORM_GROUP_INFO_ACTIVE_DIRECTORY_USERS_GROUP": "Seize the beginning of the group",
+    "FORM_SEARCH_BTN_ACTIVE_DIRECTORY_USERS_GROUP": "Search",
+    "BTN_IMPORT_SELECTION_ACTIVE_DIRECTORY_USERS_VITIS_GROUP": "Import",
+    "SUCCESFULL_IMPORTATION_ACTIVE_DIRECTORY_USERS_VITIS_GROUP": "Import successfully done",
+    "FORM_NAME_USERS_GROUP": "Name",
+    "FORM_ID_USERS_GROUP": "ID",
+    "FORM_USER_USERS_GROUP": "Users",
+    "FORM_AVAILABLE_USER_USERS_GROUP": "Available users",
+    "FORM_LINKED_USER_USERS_GROUP": "Users linked to group",
+    "FORM_ID_USERS_GROUP_GTF_GROUP": "ID",
+    "FORM_WORKSPACE_USERS_GROUP_GTF_GROUP": "Workspaces",
+    "FORM_AVAILABLE_WORKSPACE_USERS_GROUP_GTF_GROUP": "Available workspaces",
+    "FORM_LINKED_WORKSPACE_USERS_GROUP_GTF_GROUP": "Workspaces linked to group",
+    "FORM_INBOX_USERS_GROUP_GTF_GROUP": "In box",
+    "FORM_AVAILABLE_INBOX_USERS_GROUP_GTF_GROUP": "Available inboxes",
+    "FORM_LINKED_INBOX_USERS_GROUP_GTF_GROUP": "Inboxes linked to group",
+    "FORM_NAME_USERS_GROUP_GTF_GROUP": "Name",
+    "FORM_TITLE_USERS_GROUP": "Group {{::name}}",
+    "": "",
+    "FORM_ID_USERS_DOMAIN": "ID",
+    "FORM_ALIAS_USERS_DOMAIN": "Alias",
+    "FORM_NAME_USERS_DOMAIN": "Domain name",
+    "FORM_IP_SERVER_USERS_DOMAIN": "IP or Server name",
+    "FORM_TYPE_USERS_DOMAIN": "Domain type",
+    "FORM_PORT_USERS_DOMAIN": "Port",
+    "FORM_DN_USER_USERS_DOMAIN": "Search base DN (user)",
+    "FORM_FILTER_USER_USERS_DOMAIN": "Filter (user)",
+    "FORM_DN_GROUP_USERS_DOMAIN": "Search base DN (group)",
+    "FORM_FILTER_GROUP_USERS_DOMAIN": "Filter (group)",
+    "FORM_LOGIN_USERS_DOMAIN": "User",
+    "FORM_PASSWORD_USERS_DOMAIN": "Password",
+    "FORM_TITLE_USERS_DOMAIN": "Domain {{::domain}}",
+    "": "",
+    "FORM_USER_GROUP_USERS_PRIVILEGE": "User group",
+    "FORM_GROUP_DESCRIPTION_USERS_PRIVILEGE": "Description",
+    "FORM_GROUP_AVAILABLE_USER_USERS_PRIVILEGE": "Available users",
+    "FORM_GROUP_LINKED_USERS_USERS_PRIVILEGE": "Users linked to the privilege group",
+    "FORM_USERS_USERS_PRIVILEGE": "Users",
+    "FORM_TITLE_USERS_PRIVILEGE": "Privilege {{::rolname}}",
+    "": "",
+    "COMPONENT_MAP_FULLSCREEN": "Full screen",
+    "COMPONENT_MAP_LAYERSTREE": "Layers",
+    "COMPONENT_MAP_ZOOM_EXTENT": "Zoom to extent",
+    "COMPONENT_MAP_DELETE_FEATURE": "Delete feature",
+    "COMPONENT_MAP_DELETE_ALL": "Delete all features",
+    "COMPONENT_MAP_MODIFY_FEATURE": "Modify feature",
+    "COMPONENT_MAP_DRAW_POINT": "Draw point",
+    "COMPONENT_MAP_DRAW_LINE": "Draw line",
+    "COMPONENT_MAP_DRAW_POLYGON": "Draw polygon",
+    "COMPONENT_MAP_ZOOM_EXTENT": "Zoom to default extent",
+    "COMPONENT_MAP_DIVIDE_SEGMENT": "Diviser le segment",
+    "COMPONENT_MAP_OVERSIZED_EXTENT": "Map extent is oversized",
+    "COMPONENT_MAP_DIVIDE_SEGMENT_POINT_NOT_VALID": "Divite segment point not valid",
+    "LIST_MODE_INDEX_CONFIGURATION": "Index",
+    "LIST_MODE_ID_MODE_CONFIGURATION": "Mode",
+    "LIST_MODE_ICONE_MODE_CONFIGURATION": "Icon",
+    "LIST_TITLE_GRID_MODES": "List of modes",
+    "": "",
+    "WEBSOCKET_SERVER_TITLE_CONFIGURATION": "Websocket server",
+    "WEBSOCKET_SERVER_CONFIGURATION": "Server",
+    "WEBSOCKET_PORT_CONFIGURATION": "Port",
+    "WEBSOCKET_ALIAS_CONFIGURATION": "Alias",
+    "WEBSOCKET_URL_CONFIGURATION": "Client URL",
+    "WEBSOCKET_SERVER_STATE_CONFIGURATION": "Server state",
+    "WEBSOCKET_SERVER_MAX_CLIENTS_CONFIGURATION": "Max clients",
+    "WEBSOCKET_SERVER_MAX_CONNECTIONS_PER_IP_CONFIGURATION": "Max connections per IP",
+    "WEBSOCKET_SERVER_MAX_REQUESTS_PER_MINUTE_CONFIGURATION": "Max requets per user per minute",
+    "WEBSOCKET_USERS_TITLE_CONFIGURATION": "Users",
+    "WEBSOCKET_USERS_NUMBER_TITLE_CONFIGURATION": "Connected users (by services)",
+    "WEBSOCKET_USERS_APPLICATION_CONFIGURATION": "Application",
+    "WEBSOCKET_ACTIONS_TITLE_CONFIGURATION": "Actions",
+    "WEBSOCKET_ACTIONS_REFRESH_INFOS_CONFIGURATION": "Refresh infos",
+    "WEBSOCKET_ACTIONS_REFRESH_USERS_CONFIGURATION": "Refresh users",
+    "WEBSOCKET_ACTIONS_RESTART_SERVER_CONFIGURATION": "Restart server",
+    "WEBSOCKET_INFOS_REFRESHED_CONFIGURATION": "Infos refreshed",
+    "WEBSOCKET_NO_SERVER_RESPONSE_CONFIGURATION": "No server response",
+    "WEBSOCKET_USERS_RECONNECTED_CONFIGURATION": "Users refreshed",
+    "": "",
+    "FORM_THEME_NOTIFICATIONS_CONFIGURATION": "Notifications",
+    "FORM_SMS_NOTIFICATIONS_CONFIGURATION_CONFIG": "SMS notifications",
+    "FORM_SMS_NOTIFICATIONS_TRUE_CONFIGURATION": "Yes",
+    "FORM_SMS_NOTIFICATIONS_FALSE_CONFIGURATION": "No",
+    "": "",
+    "ERROR_DELETING_OWN_USER": "Vous ne pouvez pas supprimer votre compte utilisateur.",
+    "FORM_THEME_SMTP_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP",
+    "FORM_MAIL_SENDER_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Sender adress",
+    "FORM_NICKNAME_SENDER_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Sender name",
+    "FORM_SMTP_HOST_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP server",
+    "FORM_SMTP_PORT_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP server port",
+    "FORM_SMTP_AUTHENTIFICATION_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP authentication",
+    "FORM_SMTP_LOGIN_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP login",
+    "FORM_SMTP_PASSWORD_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP password",
+    "FORM_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Tester connection",
+    "MODAL_TITLE_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Connection check",
+    "MODAL_CONTENT_SUCCESS_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Successful connection",
+    "MODAL_CONTENT_ERROR_CHECK_SMTP_CONNECTION_CONFIGURATION" : "SMTP server connection error. Please check your settings.",
+    "FORM_THEME_ACCOUNT_CONFIGURATION_CONFIGURATION" : "Account creation",
+    "FORM_ACCOUNT_DEPS" : "This settings part need the SMTP settings part",
+    "FORM_ADVANCE_LOGIN_PAGE" : "Enable account creation and password fogotten features ?",
+    "FORM_AUTOMATED_SIGN_UP_CONFIGURATION" : "Do you want a validation by the application administrator ? (Administrator's mail is needed)",
+    "FORM_ADMIN_SIGN_UP_CONFIGURATION" : "Administrator's mail",
+    "FORM_ENABLE_ERROR_NOTIFICATION_CONFIGURATION" : "Send a mail to administrator when the server rise an error ?",
+    "FORM_GOOGLE_PRIVATE_CAPTCHA_CONFIGURATION" : "Google captcha private key",
+    "FORM_MAIL_TAG_SUBJECT_CONFIGURATION" : "Tag on mail's subjects",
+    "": "",
+    "ERROR_DELETING_OWN_USER": "Vous ne pouvez pas supprimer votre compte utilisateur.",
+    "FORM_TITLE_USERS_BILLINGGROUP": "Billing group {{::billinggroup}}",
+    "FORM_ID_USERS_BILLINGGROUP": "ID",
+    "FORM_BILLINGGROUP_USERS_BILLINGGROUP": "Name",
+    "FORM_DESCRIPTION_USERS_BILLINGGROUP": "Description",
+    "FORM_AVAILABLE_USER_USERS_BILLINGGROUP": "Available users",
+    "FORM_LINKED_USER_USERS_BILLINGGROUP": "Users linked to group"
+}
diff --git a/client/modules/vitis/lang/lang-fr.json b/client/modules/vitis/lang/lang-fr.json
new file mode 100755
index 00000000..a25cbd86
--- /dev/null
+++ b/client/modules/vitis/lang/lang-fr.json
@@ -0,0 +1,332 @@
+{
+    "TITLE_MODE_USER": "Utilisateur",
+    "TITLE_MODE_USERS": "Utilisateurs",
+    "TITLE_MODE_CONFIGURATION": "Configuration",
+    "TITLE_MODE_LOGS": "Journaux",
+    "TITLE_MODE_HELP": "Aide",
+    "TEXT_MODE_USER": "Profil de l'utilisateur connecté",
+    "TEXT_MODE_USERS": "Gestion des utilisateurs et des droits",
+    "TEXT_MODE_CONFIGURATION": "Paramètres de configuration avancée",
+    "TEXT_MODE_LOGS": "Historique des évènements d'exploitation",
+    "TEXT_MODE_HELP": "Documentation pour les administrateurs",
+    "": "",
+    "FILE_TOO_BIG_LOGS": "Le fichier est trop volumineux pour être visualisé.",
+    "DELETE_FILE_SUCCESS_LOGS": "Le fichier a été supprimé avec succès.",
+    "DELETE_FILES_SUCCESS_LOGS": "Les fichiers ont été supprimés avec succès.",
+    "DELETE_FILE_ERROR_LOGS": "Erreur pendant la suppression du fichier.",
+    "DELETE_FILES_ERROR_LOGS": "Erreur pendant la suppression des fichiers.",
+    "LOADING_FILE_ERROR_LOGS": "Erreur pendant le téléchargement du fichier.",
+    "DELETE_FILE_CONFIRM_LOGS": "Supprimer le fichier ?",
+    "DELETE_HISTORY_CONFIRM_LOGS": "Supprimer les fichiers qui ont plus de {{min_days_files}} jours ?",
+    "FILE_NOT_FOUND_LOGS": "Le fichier n'existe pas.",
+    "FORM_TITLE_LOGS": "Journaux",
+    "FORM_BTN_DELETE_HISTORY_LOGS": "Supprimer l'historique",
+    "FORM_BTN_REFRESH_LOGS": "Recharger les logs",
+    "FORM_BTN_DELETE_FILE_LOGS": "Supprimer le fichier",
+    "DELETE_FILE_ERROR_PERMISSION_DENIED_LOGS": "Suppression du fichier impossible (permission refusée).",
+    "": "",
+    "SECTION_UPDATE_TITLE_USERS_VITIS_GROUP": "Groupe n°{{sId}}",
+    "SECTION_DISPLAY_TITLE_USERS_VITIS_GROUP": "Groupe n°{{sId}}",
+    "SECTION_INSERT_TITLE_USERS_VITIS_GROUP": "Groupe",
+    "SECTION_UPDATE_TITLE_HELP_VITIS_HELP": "Aide",
+    "SECTION_UPDATE_TITLE_USERS_VITIS_USERS": "Utilisateur n°{{sId}}",
+    "SECTION_DISPLAY_TITLE_USERS_VITIS_USERS": "Utilisateur n°{{sId}}",
+    "SECTION_INSERT_TITLE_USERS_VITIS_USERS": "Utilisateur",
+    "": "",
+    "SECTION_UPDATE_TITLE_CONFIGURATION_VITIS_CONFIGURATION": "Configuration",
+    "FORM_GENERAL_SECTION_CONFIGURATION": "Général",
+    "FORM_APP_NAME_CONFIGURATION": "Nom de l'application",
+    "FORM_LANGUAGE_CONFIGURATION": "Langue",
+    "FORM_INSTANCE_IDENTIFIER_CONFIGURATION": "Identifiant de l'application (Utilisé pour les notifications envoyées à l'administrateur)",
+    "FORM_COOKIE_LIFETIME_CONFIGURATION": "Durée de vie des sessions en minutes",
+    "FORM_COOKIE_PATH_CONFIGURATION": "Portée des cookies",
+    "FORM_MAX_UPLOAD_FILE_SIZE_CONFIGURATION": "Taille maximale des fichiers envoyés sur le serveur en Mo",
+    "FORM_MAX_EXECUTION_TIME_CONFIGURATION": "Durée maximale d'exécution en secondes",
+    "FORM_MAX_REQUEST_TIME_CONFIGURATION": "Durée maximale des requêtes en secondes",
+    "FORM_REFRESH_PERIOD_CONFIGURATION": "Délai de rafraîchissement de l'interface graphique en secondes",
+    "FORM_MINIMUM_REFRESH_PERIOD_CONFIGURATION": "Délai minimum entre les rafraîchissements des listes en millisecondes",
+    "FORM_FORBIDDEN_EXTENSION_CONFIGURATION": "Extensions des fichiers interdits",
+    "FORM_ROWS_PER_PAGE_CONFIGURATION": "Nombre de lignes par page",
+    "FORM_WEB_SERVER_NAME_CONFIGURATION": "URL de base du serveur",
+    "FORM_VAS_HOME_CONFIGURATION": "Répertoire racine V.A.S",
+    "FORM_WEB_SERVER_UPLOAD_DIRECTORY_CONFIGURATION": "Chemin vers le dossier upload",
+    "FORM_DATE_FORMAT_CONFIGURATION": "Format des dates",
+    "FORM_SIGN_UP_CONFIGURATION" : "Afficher le bouton pour la création de compte ?",
+    "FORM_SIGN_UP_CONFIGURATION_YES" : "Oui",
+    "FORM_SIGN_UP_CONFIGURATION_NO" : "Non",
+    "FORM_FPWD_CONFIGURATION" : "Afficher le bouton pour la récupération de mot de passe ?",
+    "FORM_FPWD_CONFIGURATION_YES" : "Oui",
+    "FORM_FPWD_CONFIGURATION_NO" : "Non",
+    "FORM_REMEMBER_ME_CONFIGURATION" : "Autoriser \"Se souvenir de moi\" ? ",
+    "FORM_REMEMBER_ME_DEFAULT_CONFIGURATION" : "Valeur par défaut de \"Se souvenir de moi\"",
+    "FORM_LOG_SECTION_CONFIGURATION": "Journaux",
+    "FORM_LOG_MODE_CONFIGURATION": "Écriture des journaux",
+    "FORM_LOG_MODE_TRUE_CONFIGURATION": "Oui",
+    "FORM_LOG_MODE_FALSE_CONFIGURATION": "Non",
+    "FORM_DEBUG_MODE_CONFIGURATION": "Mode débogage",
+    "FORM_DEBUG_MODE_TRUE_CONFIGURATION": "Oui",
+    "FORM_DEBUG_MODE_FALSE_CONFIGURATION": "Non",
+    "FORM_LOG_PERIOD_CONFIGURATION": "Période de journalisation",
+    "FORM_LOG_SIZE_CONFIGURATION": "Taille max. des fichiers de log à afficher (en Ko)",
+    "FORM_HTTP_SERVER_SECTION_CONFIGURATION": "Serveur http",
+    "FORM_CLIENT_ALIAS_CONFIGURATION": "Alias du répertoire client (utilisé seulement par l'API Rest)",
+    "FORM_UPDATE_ALIAS_CONFIGURATION": "Alias du répertoire update",
+    "FORM_PUBLIC_ALIAS_CONFIGURATION": "Alias du répertoire public",
+    "FORM_SHARED_DIR_CONFIGURATION": "Répertoire partagé",
+    "FORM_UPDATE_SECTION_CONFIGURATION": "Mise à jour",
+    "FORM_WEB_SERVER_UPDATE_CONFIGURATION": "Adresse du serveur de mise à jour",
+    "FORM_SECURITY_SECTION_CONFIGURATION": "Sécurité",
+    "FORM_MIXED_RIGHTS_MANAGEMENT_CONFIGURATION": "Autoriser les utilisateurs du domaine à appartenir à des groupes locaux (gestion mixte)",
+    "FORM_ALLOW_PUBLIC_CONNECTION_CONFIGURATION": "Autoriser les connexions avec le compte public",
+    "FORM_PUBLIC_LOGIN_CONFIGURATION": "Compte public",
+    "FORM_PUBLIC_PASSWORD_CONFIGURATION": "Mot de passe du compte PUBLIC",
+    "FORM_TEST_CONNECTION_CONFIGURATION": "Tester la connexion",
+    "FORM_DATABASE_TITLE_CONFIGURATION": "Base de données",
+    "FORM_SGBD_CONFIGURATION": "SGBD",
+    "FORM_SERVER_CONFIGURATION": "Serveur",
+    "FORM_PORT_CONFIGURATION": "Port",
+    "FORM_SCHEMA_CONFIGURATION": "Schéma",
+    "FORM_MIXED_RIGHTS_MANAGEMENT_TRUE_CONFIGURATION": "Oui",
+    "FORM_MIXED_RIGHTS_MANAGEMENT_FALSE_CONFIGURATION": "Non",
+    "FORM_EXTRACT_DIR_CONFIGURATION": "Répertoire temporaire",
+    "FORM_PUBLIC_TOKEN_CONFIGURATION": "Jeton de connexion du compte PUBLIC",
+    "FORM_SERVICES_ALIAS_CONFIGURATION": "Alias du répertoire api_rest (utilisé seulement par l'API Rest)",
+    "FORM_DOC_ALIAS_CONFIGURATION": "Alias du répertoire doc",
+    "FORM_ERROR_FILE_WRITING_CONFIGURATION": "Erreur d'écriture du fichier properties.inc",
+    "PAGE_RELOAD_CONFIRM_CONFIGURATION": "Vous avez changé la langue de l'application.<br>La page doit être actualisée pour appliquer la mise à jour des propriétés.",
+    "FORM_APACHE_LOG_DIRECTORIE_CONFIGURATION": "Répertoire des logs d'apache",
+    "FORM_PRIVATE_CAPTCHA_KEY_CONFIGURATION": "Clef secrète du ReCaptcha (Google)",
+    "FORM_WS_DATA_ALIAS_CONFIGURATION": "Alias du répertoire data",
+    "PUBLIC_TOKEN_TOOLTIP_TITLE_CONFIGURATION": "Jeton de connexion du compte PUBLIC",
+    "PUBLIC_TOKEN_TOOLTIP_CONTENT_CONFIGURATION": "Les caractères acceptés sont les chiffres et les lettres<br>ainsi que les caractères '-' et ','.",
+    "FORM_PROXY_CHECK_SSL_CONFIGURATION": "Vérifier la validité du certificat SSL",
+    "FORM_PROXY_CHECK_SSL_TRUE_CONFIGURATION": "Oui",
+    "FORM_PROXY_CHECK_SSL_FALSE_CONFIGURATION": "Non",
+    "PROXY_CHECK_SSL_TOOLTIP_TITLE_CONFIGURATION": "Validité du certificat SSL",
+    "PROXY_CHECK_SSL_TOOLTIP_CONTENT_CONFIGURATION": "Vérification de la validité du certificat SSL pour les requêtes envoyées au serveur proxy.",
+	"FORM_TIMEZONE_ID_CONFIGURATION" : "Fuseau horaire",
+    "FORM_SMTP_AUTHENTIFICATION_TRUE_CONFIGURATION": "Oui",
+    "FORM_SMTP_AUTHENTIFICATION_FALSE_CONFIGURATION": "Non",
+    "": "",
+    "VERSION_SECTION_TITLE_VERSION_CONFIGURATION": "Version",
+    "CLIENT_VERSION_CONFIGURATION": "Client : ",
+    "NO_NEEDED_UPDATE_CONFIGURATION": "Votre application est à jour",
+    "NEEDED_UPDATE_CONFIGURATION": "Une mise à jour (version {{appVersion}}) est disponible sur le site de veremes",
+    "ERROR_RETRIEVE_UPDATE_CONFIGURATION": "Une erreur a été rencontrée lors de la vérification des mises à jour",
+    "BUILD_VERSION_CONFIGURATION": "Build : ",
+    "INSTALLATION_SECTION_TITLE_VERSION_CONFIGURATION": "État de l'installation",
+    "PHP_VERSION_CONFIGURATION": "PHP {{php_version}}",
+    "PDO_VERSION_CONFIGURATION": "PDO",
+    "POSTGRESQL_PDO_VERSION_CONFIGURATION": "PDO pour PostgreSQL",
+    "CURL_VERSION_CONFIGURATION": "cURL",
+    "POSTGRESQL_VERSION_CONFIGURATION": "PostgreSQL {{postgresql_version}}",
+    "LDAP_VERSION_CONFIGURATION": "LDAP (optionnel)",
+    "POSTGIS_VERSION_CONFIGURATION": "PostGIS {{postgis_version}} (optionnel)",
+    "SERVER_INFORMATIONS_SECTION_TITLE_VERSION_CONFIGURATION": "Informations sur le serveur",
+    "OS_VERSION_CONFIGURATION": "Système d'exploitation : ",
+    "DISK_VERSION_CONFIGURATION": "Informations sur le disque : ",
+    "DISK_VERSION_CONFIGURATION_VALUE": "{{::disk_free_space}} disponibles sur {{::disk_total_space}}",
+    "WEB_SERVER_SECTION_TITLE_VERSION_CONFIGURATION": "Serveur web",
+    "SERVER_ADDR_VERSION_CONFIGURATION": "IP : ",
+    "SERVER_NAME_VERSION_CONFIGURATION": "Nom : ",
+    "SERVER_PORT_VERSION_CONFIGURATION": "Port : ",
+    "": "",
+    "FORM_DELETE_LOGS_LOG": "Supprimer les fichiers de plus de",
+    "FORM_DAYS_LOGS_LOG": "Jours",
+    "": "",
+    "UPDATE_PASSWORD_USER_USER": "Vous êtes en train de modifier le mot de passe de votre utilisateur. <br>Cette action va entraîner votre déconnexion.<br>Souhaitez-vous continuer ?",
+    "ERROR_PASSWORD_CONFIRM_USER_USER": "Le mot de passe de confirmation est différent du mot de passe",
+    "WARNING_PASSWORD_CHANGE_USER_USER": "Changement de votre mot de passe",
+    "FORM_LOGIN_USER_USER": "Utilisateur",
+    "FORM_NAME_USER_USER": "Nom complet",
+    "FORM_EMAIL_USER_USER": "E-mail",
+    "FORM_AGENCY_USER_USER": "Société",
+    "FORM_DEPARTMENT_USER_USER": "Service",
+    "FORM_USER_PASSWORD_USER_USER": "Mot de passe",
+    "FORM_USER_CONFIRM_PASSWORD_USER_USER": "Confirmer le mot de passe",
+    "FORM_INFORMATIONS_USER_USER": "Informations",
+    "FORM_NEW_PASSWORD_USER_USER": "Nouveau mot de passe",
+    "ACCOUNT_UNSUBSCRIBE" : "Désactiver votre compte",
+    "FORM_DATAENCRYPT_USER_USER" : "Cryptage des données",
+    "FORM_SECRETKEY_USER_USER" : "Clé secrète",
+    "FORM_BILLINGGROUP_ID_USERS_USER" : "Groupe de facturation",
+    "FORM_ACCEPTNOTIFICATION_USER_USER" : "Acceptez-vous de recevoir des notifications par SMS ?",
+    "FORM_PHONE_USER_USER" : "N° de téléphone (pour SMS) au format international E.164 (+33 6 xx xx xx xx)",
+    "FORM_TIMEZONE_ID_USER_USER" : "Fuseau horaire",
+    "FORM_FORMATDATE_ID_USER_USER" : "Format d'affichage des dates",
+    "": "",
+    "USER_ROLE_TOOLTIP_TITLE_USERS_USER": "Description",
+    "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER": "Administrateur",
+    "USER_ROLE_USER_TOOLTIP_CONTENT_USERS_USER": "Utilisateur",
+    "FORM_LOGIN_ACTIVE_DIRECTORY_CONNECTION": "Utilisateur",
+    "FORM_PASSWORD_ACTIVE_DIRECTORY_CONNECTION": "Mot de passe",
+    "TITLE_ACTIVE_DIRECTORY_CONNECTION": "Connexion AD",
+    "FORM_CONNECTION_ACTIVE_DIRECTORY_CONNECTION": "Connexion",
+    "TITLE_SECTION_ACTIVE_DIRECTORY_USERS_VITIS_USERS": "Serveur AD",
+    "ERROR_BIND_ACTIVE_DIRECTORY_USERS_USER": "Erreur d'authentification",
+    "ERROR_INVALID_CREDENTIALS_ACTIVE_DIRECTORY_USERS_USER": "Identifiants incorrects",
+    "ERROR_CONTACT_DOMAIN_ACTIVE_DIRECTORY_USERS_USER": "Serveur LDAP injoignable",
+    "ERROR_ERROR_DOMAIN_ACTIVE_DIRECTORY_USERS_USER": "Erreur nom de domaine",
+    "TITLE_TAB_TREE_ACTIVE_DIRECTORY_USERS_USER": "Arborescence",
+    "TITLE_TAB_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Recherche",
+    "NAME_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Nom",
+    "ACCOUNT_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Compte",
+    "EMAIL_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "E-mail",
+    "AGENCY_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Société",
+    "DEPARTMENT_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Service",
+    "GROUP_SEARCH_ACTIVE_DIRECTORY_USERS_USER": "Nom du groupe",
+    "FORM_ACCOUNT_ACTIVE_DIRECTORY_USERS_USER": "Compte",
+    "FORM_GROUP_ACTIVE_DIRECTORY_USERS_USER": "Groupes",
+    "FORM_DEPARTMENT_ACTIVE_DIRECTORY_USERS_USER": "Service",
+    "FORM_SEARCH_BTN_ACTIVE_DIRECTORY_USERS_USER": "Rechercher",
+    "FORM_ACCOUNT_INFO_ACTIVE_DIRECTORY_USERS_USER": "Saisir le début du compte",
+    "FORM_GROUP_INFO_ACTIVE_DIRECTORY_USERS_USER": "Liste des groupes, séparés par des virgules",
+    "FORM_DEPARTMENT_INFO_ACTIVE_DIRECTORY_USERS_USER": "Saisir le début du nom du service",
+    "BTN_IMPORT_SELECTION_ACTIVE_DIRECTORY_USERS_VITIS_USERS": "Importer",
+    "SUCCESFULL_IMPORTATION_ACTIVE_DIRECTORY_USERS_VITIS_USERS": "Importation effectuée avec succès",
+    "FORM_ACTIVE_DIRECTORY_USER_GROUPS_USERS_USER": "Membre des groupes du domaine",
+    "FORM_ALL_USER_GROUPS_USERS_USER": "Synthèse des appartenances",
+    "FORM_DOMAIN_ACTIVE_DIRECTORY_CONNECTION": "Domaine",
+    "FORM_LOGIN_USERS_USER": "Utilisateur",
+    "FORM_NAME_USERS_USER": "Nom complet",
+    "FORM_EMAIL_USERS_USER": "E-mail",
+    "FORM_AGENCY_USERS_USER": "Société",
+    "FORM_DEPARTMENT_USERS_USER": "Service",
+    "FORM_DOMAIN_USERS_USER": "Domaine",
+    "FORM_IP_USERS_USER": "IP du poste",
+    "FORM_ID_USERS_USER": "ID",
+    "FORM_LAST_CONNECTION_USERS_USER": "Dernière connexion",
+    "FORM_LOCAL_GROUPS_USERS_USER": "Groupes locaux",
+    "FORM_GROUPS_AVAILABLE_USERS_USER": "Non membre des groupes",
+    "FORM_GROUPS_USER_USERS_USER": "Membre des groupes",
+    "FORM_PRIVILEGES_USERS_USER": "Privilèges",
+    "FORM_PRIVILEGES_AVAILABLE_USERS_USER": "Privilèges disponibles",
+    "FORM_PRIVILEGES_USER_USERS_USER": "Privilèges liés à l'utilisateur",
+    "FORM_NEW_PASSWORD_USERS_USER": "Nouveau mot de passe",
+    "FORM_USER_PASSWORD_USERS_USER": "Mot de passe",
+    "FORM_USER_CONFIRM_PASSWORD_USERS_USER": "Confirmer le mot de passe",
+    "FORM_ACCEPTNOTIFICATION_USERS_USER" : "Activer les notifications SMS pour cet utilisateur ?",
+    "FORM_PHONE_USERS_USER" : "N° de téléphone (pour SMS) au format international E.164 (+33 6 xx xx xx xx)",
+    "FORM_GROUPS_USERS_USER": "Groupes",
+    "FORM_TITLE_USERS_USER": "Utilisateur {{::login}}",
+    "FORM_IP_TOOLTIP_USERS_USER": "Adresse IP V4 autorisée à se connecter ou expression régulière.<br>Exemple : ^193.248.208.<br>Vide : toutes adresses acceptées.",
+    "FORM_RESTRICTION_USERS_USER": "Restriction",
+    "FORM_RESTRICTION_TOOLTIP_USERS_USER": "Ce champ peut être utilisé pour restreindre l'accès de l'utilisateur à certaines données.<br>Le mécanisme de filtre doit être implémenté dans un traitement GTF ou dans un module de vMap (cadastre par exemple).<br>La syntaxe à utiliser dépend de la nature du filtre.<br>Consulter la documentation ou le support technique pour avoir plus d'information sur les possibilités de filtre des données.",
+    "FORM_TIMEZONE_ID_USERS_USER" : "Fuseau horaire",
+    "FORM_FORMATDATE_ID_USERS_USER" : "Format d'affichage des dates",
+    "": "",
+    "TITLE_SECTION_ACTIVE_DIRECTORY_USERS_GROUP": "Serveur AD",
+    "FORM_GROUP_ACTIVE_DIRECTORY_USERS_GROUP": "Groupe",
+    "FORM_GROUP_INFO_ACTIVE_DIRECTORY_USERS_GROUP": "Saisir le début du groupe",
+    "FORM_SEARCH_BTN_ACTIVE_DIRECTORY_USERS_GROUP": "Rechercher",
+    "BTN_IMPORT_SELECTION_ACTIVE_DIRECTORY_USERS_VITIS_GROUP": "Importer",
+    "SUCCESFULL_IMPORTATION_ACTIVE_DIRECTORY_USERS_VITIS_GROUP": "Importation effectuée avec succès",
+    "FORM_NAME_USERS_GROUP": "Nom",
+    "FORM_ID_USERS_GROUP": "ID",
+    "FORM_USER_USERS_GROUP": "Utilisateurs",
+    "FORM_AVAILABLE_USER_USERS_GROUP": "Utilisateurs disponibles",
+    "FORM_LINKED_USER_USERS_GROUP": "Utilisateurs liés au groupe",
+    "FORM_ID_USERS_GROUP_GTF_GROUP": "ID",
+    "FORM_WORKSPACE_USERS_GROUP_GTF_GROUP": "Traitements",
+    "FORM_AVAILABLE_WORKSPACE_USERS_GROUP_GTF_GROUP": "Traitements disponibles",
+    "FORM_LINKED_WORKSPACE_USERS_GROUP_GTF_GROUP": "Traitements liés au groupe",
+    "FORM_INBOX_USERS_GROUP_GTF_GROUP": "Dépôts",
+    "FORM_AVAILABLE_INBOX_USERS_GROUP_GTF_GROUP": "Dépôts disponibles",
+    "FORM_LINKED_INBOX_USERS_GROUP_GTF_GROUP": "Dépôts liés au groupe",
+    "FORM_NAME_USERS_GROUP_GTF_GROUP": "Nom",
+    "FORM_TITLE_USERS_GROUP": "Groupe {{::name}}",
+    "": "",
+    "FORM_ID_USERS_DOMAIN": "ID",
+    "FORM_ALIAS_USERS_DOMAIN": "Alias",
+    "FORM_NAME_USERS_DOMAIN": "Nom du domaine",
+    "FORM_IP_SERVER_USERS_DOMAIN": "Nom ou IP du serveur",
+    "FORM_TYPE_USERS_DOMAIN": "Type du domaine",
+    "FORM_PORT_USERS_DOMAIN": "Port",
+    "FORM_DN_USER_USERS_DOMAIN": "Dn de base de recherche (utilisateur)",
+    "FORM_FILTER_USER_USERS_DOMAIN": "Filtre (utilisateur)",
+    "FORM_DN_GROUP_USERS_DOMAIN": "Dn de base de recherche (groupe)",
+    "FORM_FILTER_GROUP_USERS_DOMAIN": "Filtre (groupe)",
+    "FORM_LOGIN_USERS_DOMAIN": "Utilisateur",
+    "FORM_PASSWORD_USERS_DOMAIN": "Mot de passe",
+    "FORM_TITLE_USERS_DOMAIN": "Domaine {{::domain}}",
+    "": "",
+    "FORM_USER_GROUP_USERS_PRIVILEGE": "Groupe d'utilisateurs",
+    "FORM_GROUP_DESCRIPTION_USERS_PRIVILEGE": "Description",
+    "FORM_GROUP_AVAILABLE_USER_USERS_PRIVILEGE": "Utilisateurs disponibles",
+    "FORM_GROUP_LINKED_USERS_USERS_PRIVILEGE": "Utilisateurs liés au groupe",
+    "FORM_USERS_USERS_PRIVILEGE": "Utilisateurs",
+    "FORM_TITLE_USERS_PRIVILEGE": "Privilège {{::user_group}}",
+    "": "",
+    "COMPONENT_MAP_FULLSCREEN": "Plein écran",
+    "COMPONENT_MAP_LAYERSTREE": "Couches de la carte",
+    "COMPONENT_MAP_ZOOM_EXTENT": "Zoom étendue max",
+    "COMPONENT_MAP_DELETE_FEATURE": "Supprimer un dessin",
+    "COMPONENT_MAP_DELETE_ALL": "Supprimer tous les dessins",
+    "COMPONENT_MAP_MODIFY_FEATURE": "Modifier un dessin",
+    "COMPONENT_MAP_DRAW_POINT": "Dessiner point",
+    "COMPONENT_MAP_DRAW_LINE": "Dessiner ligne",
+    "COMPONENT_MAP_DRAW_POLYGON": "Dessiner polygone",
+    "COMPONENT_MAP_ZOOM_EXTENT": "Retour à l'étendue par défaut",
+    "COMPONENT_MAP_DIVIDE_SEGMENT": "Diviser le segment",
+    "COMPONENT_MAP_OVERSIZED_EXTENT": "L'étendue de la carte est en dehors de celle disponible",
+    "COMPONENT_MAP_DIVIDE_SEGMENT_POINT_NOT_VALID": "Le point de découpe n'est pas valide",
+    "LIST_MODE_INDEX_CONFIGURATION": "Index",
+    "LIST_MODE_ID_MODE_CONFIGURATION": "Mode",
+    "LIST_MODE_ICONE_MODE_CONFIGURATION": "Icone",
+    "LIST_TITLE_GRID_MODES": "Liste des modes",
+    "": "",
+    "WEBSOCKET_SERVER_TITLE_CONFIGURATION": "Serveur Websocket",
+    "WEBSOCKET_SERVER_CONFIGURATION": "Serveur",
+    "WEBSOCKET_PORT_CONFIGURATION": "Port",
+    "WEBSOCKET_ALIAS_CONFIGURATION": "Alias",
+    "WEBSOCKET_URL_CONFIGURATION": "URL client",
+    "WEBSOCKET_SERVER_STATE_CONFIGURATION": "État du serveur",
+    "WEBSOCKET_SERVER_MAX_CLIENTS_CONFIGURATION": "Clients max",
+    "WEBSOCKET_SERVER_MAX_CONNECTIONS_PER_IP_CONFIGURATION": "Connections max par IP",
+    "WEBSOCKET_SERVER_MAX_REQUESTS_PER_MINUTE_CONFIGURATION": "Requêtes max par utilisateur à la minute",
+    "WEBSOCKET_USERS_TITLE_CONFIGURATION": "Utilisateurs",
+    "WEBSOCKET_USERS_NUMBER_TITLE_CONFIGURATION": "Utilisateurs connectés (par service)",
+    "WEBSOCKET_USERS_APPLICATION_CONFIGURATION": "Application",
+    "WEBSOCKET_ACTIONS_TITLE_CONFIGURATION": "Actions",
+    "WEBSOCKET_ACTIONS_REFRESH_INFOS_CONFIGURATION": "Rafraichir les infos",
+    "WEBSOCKET_ACTIONS_REFRESH_USERS_CONFIGURATION": "Rafraichir la liste des utilisateurs",
+    "WEBSOCKET_ACTIONS_RESTART_SERVER_CONFIGURATION": "Redémarrer le serveur",
+    "WEBSOCKET_INFOS_REFRESHED_CONFIGURATION": "Infos rafraichies",
+    "WEBSOCKET_NO_SERVER_RESPONSE_CONFIGURATION": "Pas de réponse du serveur",
+    "WEBSOCKET_USERS_RECONNECTED_CONFIGURATION": "Utilisateurs rafraichis",
+    "": "",
+    "FORM_THEME_NOTIFICATIONS_CONFIGURATION": "Notifications",
+    "FORM_SMS_NOTIFICATIONS_CONFIGURATION_CONFIG": "Notifications téléphoniques par SMS",
+    "FORM_SMS_NOTIFICATIONS_TRUE_CONFIGURATION": "Oui",
+    "FORM_SMS_NOTIFICATIONS_FALSE_CONFIGURATION": "Non",
+    "": "",
+    "ERROR_DELETING_OWN_USER": "Vous ne pouvez pas supprimer votre compte utilisateur.",
+    "FORM_THEME_SMTP_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "SMTP",
+    "FORM_MAIL_SENDER_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Adresse expéditeur",
+    "FORM_NICKNAME_SENDER_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Nom expéditeur",
+    "FORM_SMTP_HOST_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Serveur SMTP",
+    "FORM_SMTP_PORT_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Port serveur SMTP",
+    "FORM_SMTP_AUTHENTIFICATION_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Authentification SMTP",
+    "FORM_SMTP_LOGIN_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Compte SMTP",
+    "FORM_SMTP_PASSWORD_CONFIGURATION_CONFIGURATION_GTF_CONFIG" : "Mot de passe SMTP",
+    "FORM_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Tester la connexion",
+    "MODAL_TITLE_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Test de connexion",
+    "MODAL_CONTENT_SUCCESS_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Connexion effectuée avec succés.",
+    "MODAL_CONTENT_ERROR_CHECK_SMTP_CONNECTION_CONFIGURATION" : "Erreur de connexion au serveur SMTP. Veuillez vérifier vos paramètres.",
+    "FORM_THEME_ACCOUNT_CONFIGURATION_CONFIGURATION" : "Création de Compte",
+    "FORM_ACCOUNT_DEPS" : "L'activation de ces options requiert les properties de la partie SMTP",
+    "FORM_ADVANCE_LOGIN_PAGE" : "Activer les fonctionnalités de création de compte et de récupération de mot de passe par l'API?",
+    "FORM_AUTOMATED_SIGN_UP_CONFIGURATION" : "Voulez-vous que l'administrateur valide les inscriptions ? (requiert le mail de l'administrateur)",
+    "FORM_ADMIN_SIGN_UP_CONFIGURATION" : "Mail de l'administrateur de l'application",
+    "FORM_ENABLE_ERROR_NOTIFICATION_CONFIGURATION" : "Recevoir des notifications lors de disfonctionnement du serveur ? (requiert le mail de l'administrateur)",
+    "FORM_GOOGLE_PRIVATE_CAPTCHA_CONFIGURATION" : "Clé privée pour le Captcha Google",
+    "FORM_MAIL_TAG_SUBJECT_CONFIGURATION" : "Prefixe sur les objets des mails",
+    "": "",
+    "ERROR_DELETING_OWN_USER": "Vous ne pouvez pas supprimer votre compte utilisateur.",
+    "FORM_TITLE_USERS_BILLINGGROUP": "Groupe de facturation {{::billinggroup}}",
+    "FORM_ID_USERS_BILLINGGROUP": "ID",
+    "FORM_BILLINGGROUP_USERS_BILLINGGROUP": "Nom",
+    "FORM_DESCRIPTION_USERS_BILLINGGROUP": "Description",
+    "FORM_AVAILABLE_USER_USERS_BILLINGGROUP": "Utilisateurs disponibles",
+    "FORM_LINKED_USER_USERS_BILLINGGROUP": "Utilisateurs liés au groupe"
+}
diff --git a/client/modules/vitis/less/activeDirectoryTree.less b/client/modules/vitis/less/activeDirectoryTree.less
new file mode 100755
index 00000000..d2552732
--- /dev/null
+++ b/client/modules/vitis/less/activeDirectoryTree.less
@@ -0,0 +1,78 @@
+/*
+form[name="logs"] .form-subtitle {
+        border-bottom: 1px solid silver;
+}
+*/
+.active-directory-tree-nav {
+        padding: 10px;
+        background-color: #ffffff;
+        border: 1px solid #838383;
+        border-radius: 10px;
+        font-size: 12px;
+}
+
+.active-directory-tree-nav-title {
+        font-size: 11px;
+        font-style: italic;
+        color: #535353;
+}
+// Trieeview
+.treeview {
+        font-size: 12px;
+        line-height: 25px;
+}
+
+// Fichier de log
+.active-directory-tree-content-log-path {
+        color: @font-color-purple;
+        font-family: arial;
+        font-size: 16px;
+        font-weight: bold;
+        padding-bottom: 6px;
+        margin-bottom: 20px;
+        border-bottom: 1px solid black;
+}
+.active-directory-tree-content {
+        width: 100%;
+        height: 100%;
+}
+.active-directory-tree-content-container {
+        display: none;
+        width: 100%;
+        height: 100%;
+        padding: 10px;
+}
+.active-directory-tree-content-textarea-container {
+        width: 100%;
+        height: 100%;
+}
+.active-directory-tree-content-textarea-container > textarea {
+        width: 100%;
+        height: 100%;
+        resize: none;
+        font-size: 11px;
+}
+.treeview .list-group-item {
+    border-radius: 0 !important;
+    height: 25px;
+    padding: 1px 0 2px 8px;
+    z-index: 0 !important;
+}
+
+.active-directory-tree-title {
+        font-weight: bold;
+        margin: 5px 0;
+}
+// Fenêtre de connexion.
+.dialog-modal-window-ad-connection .modal-dialog {
+    width: 400px;
+}
+.dialog-modal-window-login-domain {
+    display: block;
+    margin-top: 27px;
+}
+
+//
+.active-directory-tree-nav .treeview > .list-group > .list-group-item {
+    width: auto;
+}
\ No newline at end of file
diff --git a/client/modules/vitis/less/logs.less b/client/modules/vitis/less/logs.less
new file mode 100755
index 00000000..778bd240
--- /dev/null
+++ b/client/modules/vitis/less/logs.less
@@ -0,0 +1,78 @@
+form[name="logs"] .form-subtitle {
+        border-bottom: 1px solid silver;
+}
+
+.logs-form {
+        padding: 10px;
+        background-color: #ffffff;
+        border: 1px solid #838383;
+        border-radius: 10px;
+}
+
+.logs-form-title {
+        font-size: 11px;
+        font-style: italic;
+        color: #535353;
+}
+
+// Fichier de log
+.logs-content-log-path {
+        color: @font-color-purple;
+        font-family: arial;
+        font-size: 16px;
+        font-weight: bold;
+        padding-bottom: 6px;
+        margin-bottom: 20px;
+        border-bottom: 1px solid black;
+}
+.logs-content {
+        width: 100%;
+        height: 100%;
+}
+.logs-content-container {
+        display: none;
+        width: 100%;
+        height: 100%;
+        padding: 10px;
+}
+.logs-content-textarea-container {
+        width: 100%;
+        height: 100%;
+}
+.logs-content-textarea-container > textarea {
+        width: 100%;
+        height: 100%;
+        resize: none;
+        font-size: 11px;
+}
+
+.logs-delete-file {
+        margin: 0 0 2px 2px;
+}
+
+// Ligne "supprimer les fichiers de plus de...".
+.logs-min-days-row > div:nth-child(1) {
+    padding-right: 0;
+}
+.logs-min-days-row > div:nth-child(2) {
+    padding-left: 5px;
+}
+
+//
+.logs-form > .treeview > .list-group > .list-group-item {
+    width: auto;
+}
+
+// Fichiers et répertoires au même niveau.
+.logs-form li[class^='list-group-item node-logs_vitis_log_treeview'] > span[class='icon glyphicon'] {
+    display: initial;
+}
+.logs-form li[class^='list-group-item node-logs_vitis_log_treeview'] > span[class^='icon node-icon'] {
+    left: -5px;
+}
+
+// Pas de retour à la ligne dans les titres et noms de fichiers.
+.logs-form .node-logs_vitis_log_treeview {
+    white-space: nowrap;
+    overflow: hidden;
+}
\ No newline at end of file
diff --git a/client/modules/vitis/less/main.less b/client/modules/vitis/less/main.less
new file mode 100755
index 00000000..66adeeb6
--- /dev/null
+++ b/client/modules/vitis/less/main.less
@@ -0,0 +1,10 @@
+// LESS
+@ui-grid-bg-image: "../images/ui-grid/wbg.gif";
+@font-color-purple: #6d1a67;
+@import 'logs.less';
+@import 'versionConfiguration.less';
+@import 'phpInfoConfiguration.less';
+@import 'updateConfiguration.less';
+@import 'users.less';
+@import 'activeDirectoryTree.less';
+@import 'webServiceHelp.less';
\ No newline at end of file
diff --git a/client/modules/vitis/less/phpInfoConfiguration.less b/client/modules/vitis/less/phpInfoConfiguration.less
new file mode 100755
index 00000000..b0e2de77
--- /dev/null
+++ b/client/modules/vitis/less/phpInfoConfiguration.less
@@ -0,0 +1,88 @@
+// Php info
+.php-info-configuration {
+        position: relative;
+        width: 100%;
+        height: 100%;
+        margin: 0 0;
+        padding: 15px;
+        overflow-x: hidden;
+        overflow-y: scroll;
+        background-color: #f8f8f8;
+}
+
+/* phpinfo */
+//.php-info-configuration body {background-color: #ffffff; color: #000000;}
+.php-info-configuration body, .php-info-configuration td, .php-info-configuration th, .php-info-configuration h1, .php-info-configuration h2 {
+        font-family: sans-serif;
+}
+.php-info-configuration pre {
+        margin: 0px; 
+        font-family: monospace;
+}
+.php-info-configuration a:link {
+        color: #000099; 
+        text-decoration: none; 
+        background-color: #ffffff;
+}
+.php-info-configuration a:hover {
+        text-decoration: underline;
+}
+.php-info-configuration table {
+        border-collapse: collapse;
+}
+.php-info-configuration .center {
+        text-align: center;
+}
+.php-info-configuration .center table {
+        margin-left: auto; 
+        margin-right: auto; 
+        text-align: left;
+}
+.php-info-configuration .center th {
+        text-align: center !important;
+}
+.php-info-configuration td, .php-info-configuration th {
+        padding: 3px;
+        border: 1px solid #000000;
+        font-size: 75%;
+        vertical-align: baseline;
+}
+.php-info-configuration h1 {
+        font-size: 150%;
+}
+.php-info-configuration h2 {
+        font-size: 125%;
+}
+.php-info-configuration .p {
+        text-align: left;
+}
+.php-info-configuration .e {
+        background-color: #ccccff; 
+        font-weight: bold; 
+        color: #000000;
+}
+.php-info-configuration .h {
+        background-color: #9999cc; 
+        font-weight: bold; 
+        color: #000000;
+}
+.php-info-configuration .v {
+        background-color: #cccccc; 
+        color: #000000;
+}
+.php-info-configuration .vr {
+        background-color: #cccccc; 
+        text-align: right; 
+        color: #000000;
+}
+.php-info-configuration img {
+        float: right; 
+        border: 0px;
+}
+.php-info-configuration hr {
+        width: 600px; 
+        background-color: #cccccc; 
+        border: 0px; 
+        height: 1px; 
+        color: #000000;
+}
diff --git a/client/modules/vitis/less/updateConfiguration.less b/client/modules/vitis/less/updateConfiguration.less
new file mode 100755
index 00000000..2e2a555f
--- /dev/null
+++ b/client/modules/vitis/less/updateConfiguration.less
@@ -0,0 +1,11 @@
+// Version
+.update-configuration {
+        position: relative;
+        width: 100%;
+        height: 100%;
+        margin: 0;
+        padding: 0;
+        overflow-x: hidden;
+        overflow-y: hidden;
+        background-color: #f8f8f8;
+}
diff --git a/client/modules/vitis/less/users.less b/client/modules/vitis/less/users.less
new file mode 100755
index 00000000..0dd6cfe8
--- /dev/null
+++ b/client/modules/vitis/less/users.less
@@ -0,0 +1,15 @@
+// Users
+.user-role {
+	background: url(../images/user.png) center center no-repeat;
+}
+.admin-role {
+	background: url(../images/administrator.png) center center no-repeat;
+}
+
+// Bouton de connexion (import AD)
+.import-user-ad-connect-btn {
+        //width: 100%;
+}
+.import-user-ad-connect-btn > button {
+        float: right !important;
+}
diff --git a/client/modules/vitis/less/versionConfiguration.less b/client/modules/vitis/less/versionConfiguration.less
new file mode 100755
index 00000000..f3c030dd
--- /dev/null
+++ b/client/modules/vitis/less/versionConfiguration.less
@@ -0,0 +1,50 @@
+@import '../../../conf/less/variables.less';
+
+// Version
+.version-configuration {
+    position: relative;
+    width: 100%;
+    height: 100%;
+    margin: 0 0;
+    padding: 15px;
+    overflow-x: hidden;
+    overflow-y: scroll;
+    background-color: #f8f8f8;
+}
+//
+.version-configuration .list-group-item {
+    height: 32px;
+    padding: 7px 15px;
+    font-size: 12px;
+}
+
+.version-configuration .list-group-item > span:first-child {
+    font-weight: bold;
+}
+//
+.version-configuration .panel-title {
+    color: white;
+    font-weight: bold;
+}
+.panel-default>.panel-heading{
+    background-color: @application-lighen-color-theme;
+}
+//
+.install-state-ok {
+    background: url("../images/button_green.gif") 190px center no-repeat;
+}
+.install-state-error {
+    background: url("../images/button_red.gif") 190px center no-repeat;
+}
+
+.version-update {
+    height:20px;
+    padding-top:0;
+    font-weight:bold;
+}
+.version-needed-update {
+    color:#d94d0a !important; 
+}
+.version-no-needed-update {
+    color:white !important; 
+}
\ No newline at end of file
diff --git a/client/modules/vitis/less/webServiceHelp.less b/client/modules/vitis/less/webServiceHelp.less
new file mode 100755
index 00000000..b84da3a8
--- /dev/null
+++ b/client/modules/vitis/less/webServiceHelp.less
@@ -0,0 +1,8 @@
+// 
+.web-service-help {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        border: none;
+        border-left: 1px solid silver;
+}
diff --git a/client/modules/vitis/templates/activeDirectoryTreeLeftTpl.html b/client/modules/vitis/templates/activeDirectoryTreeLeftTpl.html
new file mode 100755
index 00000000..aeca66f1
--- /dev/null
+++ b/client/modules/vitis/templates/activeDirectoryTreeLeftTpl.html
@@ -0,0 +1,11 @@
+<div class="active-directory-tree-nav">
+        <ul class="nav nav-tabs" role="tablist">
+                <li role="presentation" class="active"><a href="#{{::sSelectedObjectName}}_treeview" aria-controls="{{::sSelectedObjectName}}_treeview" role="tab" data-toggle="tab" data-translate="TITLE_TAB_TREE_ACTIVE_DIRECTORY_USERS_USER"></a></li>
+                <li role="presentation"><a href="#{{::sSelectedObjectName}}_search_form" aria-controls="{{::sSelectedObjectName}}_search_form" role="tab" data-toggle="tab" data-translate="TITLE_TAB_SEARCH_ACTIVE_DIRECTORY_USERS_USER"></a></li>
+        </ul>
+        <div class="active-directory-tree-title">{{oLdap.sDn}}</div>
+        <div class="tab-content">
+                <div data-app-active-directory-tree-treeview-container="" role="tabpanel" class="tab-pane active"></div>
+                <div data-app-active-directory-tree-form="" role="tabpanel" class="tab-pane" id="{{::sSelectedObjectName}}_search_form">...</div>
+        </div>
+</div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/activeDirectoryTreeRightTpl.html b/client/modules/vitis/templates/activeDirectoryTreeRightTpl.html
new file mode 100755
index 00000000..8605ba70
--- /dev/null
+++ b/client/modules/vitis/templates/activeDirectoryTreeRightTpl.html
@@ -0,0 +1 @@
+<div data-app-active-directory-files="" class="row no-bs-row-margin active-directory-tree-content"></div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/logsLeftTpl.html b/client/modules/vitis/templates/logsLeftTpl.html
new file mode 100755
index 00000000..107fb3ae
--- /dev/null
+++ b/client/modules/vitis/templates/logsLeftTpl.html
@@ -0,0 +1,4 @@
+<div class="logs-form">
+        <div data-app-logs-treeview-container="logDrtv" id="{{::sSelectedObjectName}}_treeview"></div>
+        <div data-app-logs-form=""></div>
+</div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/logsRightTpl.html b/client/modules/vitis/templates/logsRightTpl.html
new file mode 100755
index 00000000..9d8b90e0
--- /dev/null
+++ b/client/modules/vitis/templates/logsRightTpl.html
@@ -0,0 +1,16 @@
+<div data-app-logs="" class="row no-bs-row-margin logs-content">
+        <div id="logs-content-container" class="col-xs-12 logs-content-container">
+                <div class="row no-bs-row-margin">
+                        <div class="col-xs-12 no-bs-col-padding logs-content-log-path">{{sLogPath}}
+                                <button type="button" id="btn_delete_log_file" class="btn btn-xs btn-primary logs-delete-file" aria-label="Left Align" ng-click="deleteLogFile(oSelectedLogFile)">
+                                        <span class="glyphicon glyphicon-trash"></span>
+                                </button>                        
+                        </div>
+                </div>
+                <div class="row no-bs-row-margin">
+                        <div class="col-xs-12 no-bs-col-padding logs-content-textarea-container">
+                                <textarea ng-bind="sLogContent"  readonly="readonly"></textarea>
+                        </div>
+                </div>
+        </div>
+</div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/phpInfoConfigurationTpl.html b/client/modules/vitis/templates/phpInfoConfigurationTpl.html
new file mode 100755
index 00000000..c88d1c6c
--- /dev/null
+++ b/client/modules/vitis/templates/phpInfoConfigurationTpl.html
@@ -0,0 +1,3 @@
+<div class="row php-info-configuration">
+        <div data-app-php-info="" class="col-xs-12 no_bs_padding">{{::phpinfo}}</div>
+</div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/updateConfigurationTpl.html b/client/modules/vitis/templates/updateConfigurationTpl.html
new file mode 100755
index 00000000..5f6e6129
--- /dev/null
+++ b/client/modules/vitis/templates/updateConfigurationTpl.html
@@ -0,0 +1 @@
+<div data-app-update-configuration="" class="row update-configuration"></div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/versionConfigurationTpl.html b/client/modules/vitis/templates/versionConfigurationTpl.html
new file mode 100755
index 00000000..ee06e37f
--- /dev/null
+++ b/client/modules/vitis/templates/versionConfigurationTpl.html
@@ -0,0 +1,70 @@
+<div data-app-version-configuration="" class="row version-configuration">
+    <div class="col-xs-12 no_bs_padding">
+        <!-- Version -->
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="VERSION_SECTION_TITLE_VERSION_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item"><span data-translate="CLIENT_VERSION_CONFIGURATION"></span>{{::oVersion.VM_VERSION}}</li>
+            </ul>
+            <div class="panel-heading version-update" ng-class="(oVersion.neededUpdate) ? 'version-needed-update' : 'version-no-needed-update'" >
+                <span data-translate="{{::oVersion.update}}" data-translate-values="oVersion"></span>
+            </div>  
+            <ul class="list-group">
+                <li class="list-group-item"><span data-translate="BUILD_VERSION_CONFIGURATION"></span>{{::oVersion.VM_BUILD}}</li>
+            </ul>
+        </div>
+        <!-- État de l'installation -->
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="INSTALLATION_SECTION_TITLE_VERSION_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.php_version)">
+                    <span data-translate="PHP_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.pdo_extension_loaded)">
+                    <span data-translate="PDO_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.pdo_pgsql_extension_loaded)">
+                    <span data-translate="POSTGRESQL_PDO_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.curl_extension_loaded)">
+                    <span data-translate="CURL_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.postgresql)">
+                    <span data-translate="POSTGRESQL_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.ldap_extension_loaded)">
+                    <span data-translate="LDAP_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+                <li class="list-group-item" ng-class="getStateCssClass(oVersion.postgis)">
+                    <span data-translate="POSTGIS_VERSION_CONFIGURATION" data-translate-values="oVersion"></span>
+                </li>
+            </ul>
+        </div>
+        <!-- Informations sur le serveur -->
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="SERVER_INFORMATIONS_SECTION_TITLE_VERSION_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item"><span data-translate="OS_VERSION_CONFIGURATION"></span>{{::oVersion.os_version}}</li>
+                <li class="list-group-item"><span data-translate="DISK_VERSION_CONFIGURATION"></span><span data-translate="DISK_VERSION_CONFIGURATION_VALUE" data-translate-values="oVersion"></span></li>
+            </ul>
+        </div>
+        <!-- Serveur web -->
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="WEB_SERVER_SECTION_TITLE_VERSION_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item"><span>{{::oVersion.server_software}}</span></li>
+                <li class="list-group-item"><span data-translate="SERVER_ADDR_VERSION_CONFIGURATION"></span>{{::oVersion.server_addr}}</li>
+                <li class="list-group-item"><span data-translate="SERVER_NAME_VERSION_CONFIGURATION"></span>{{::oVersion.server_name}}</li>
+                <li class="list-group-item"><span data-translate="SERVER_PORT_VERSION_CONFIGURATION"></span>{{::oVersion.server_port}}</li>
+            </ul>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/webServiceHelpTpl.html b/client/modules/vitis/templates/webServiceHelpTpl.html
new file mode 100755
index 00000000..ec5f3bc1
--- /dev/null
+++ b/client/modules/vitis/templates/webServiceHelpTpl.html
@@ -0,0 +1 @@
+<iframe data-app-web-service-help="" src="{{::sUrlWebServiceDoc}}" class="web-service-help"></iframe>
\ No newline at end of file
diff --git a/client/modules/vitis/templates/websocketConfigurationTpl.html b/client/modules/vitis/templates/websocketConfigurationTpl.html
new file mode 100755
index 00000000..e00de965
--- /dev/null
+++ b/client/modules/vitis/templates/websocketConfigurationTpl.html
@@ -0,0 +1,46 @@
+<div data-app-websocket-configuration="" class="row version-configuration">
+    <div class="col-xs-12 no_bs_padding">
+
+        <!--Serveur-->
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="WEBSOCKET_SERVER_TITLE_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item" ng-class="{'install-state-error': oServerInfos === null, 'install-state-ok': oServerInfos !== null}"><span data-translate="WEBSOCKET_SERVER_STATE_CONFIGURATION"></span> : </li>
+                <li ng-if="ctrl.propertiesSrvc.websocket_server" class="list-group-item"><span data-translate="WEBSOCKET_SERVER_CONFIGURATION"></span> : {{ctrl.propertiesSrvc.websocket_server}}</li>
+                <li ng-if="ctrl.propertiesSrvc.websocket_port" class="list-group-item"><span data-translate="WEBSOCKET_PORT_CONFIGURATION"></span> : {{ctrl.propertiesSrvc.websocket_port}}</li>
+                <li ng-if="ctrl.propertiesSrvc.websocket_alias" class="list-group-item"><span data-translate="WEBSOCKET_ALIAS_CONFIGURATION"></span> : {{ctrl.propertiesSrvc.websocket_alias}}</li>
+                <li ng-if="sWebSocketUrl" class="list-group-item"><span data-translate="WEBSOCKET_URL_CONFIGURATION"></span> : {{sWebSocketUrl}}</li>
+                <li ng-if="oServerInfos.maxClients" class="list-group-item"><span data-translate="WEBSOCKET_SERVER_MAX_CLIENTS_CONFIGURATION"></span> : {{oServerInfos.maxClients}}</li>
+                <li ng-if="oServerInfos.maxRequetsPerMinute" class="list-group-item"><span data-translate="WEBSOCKET_SERVER_MAX_REQUESTS_PER_MINUTE_CONFIGURATION"></span> : {{oServerInfos.maxRequetsPerMinute}}</li>
+            </ul> 
+        </div>
+
+        <!--Utilisateurs-->
+        <div ng-if="oServerInfos !== null" class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="WEBSOCKET_USERS_NUMBER_TITLE_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item"><span data-translate="WEBSOCKET_USERS_APPLICATION_CONFIGURATION"></span> : {{oServerInfos.clientCount}}</li>
+                <li ng-if="oService.clientCount" ng-repeat="(sServiceName, oService) in oServerInfos.activeServices" class="list-group-item"><span>{{sServiceName}}</span> : {{oService.clientCount}}</li>
+            </ul> 
+        </div>
+
+        <!--Actions-->
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title" data-translate="WEBSOCKET_ACTIONS_TITLE_CONFIGURATION"></h3>
+            </div>
+            <ul class="list-group">
+                <li class="list-group-item height-100">
+                    <button class="btn btn-primary" ng-click="ctrl.reloadWebsocketStatus()"><span data-translate="WEBSOCKET_ACTIONS_REFRESH_INFOS_CONFIGURATION"></span></button>
+                    <button class="btn btn-primary" ng-click="ctrl.refreshClients()"><span data-translate="WEBSOCKET_ACTIONS_REFRESH_USERS_CONFIGURATION"></span></button>
+                    <button class="btn btn-primary hidden"><span data-translate="WEBSOCKET_ACTIONS_RESTART_SERVER_CONFIGURATION"></span></button>
+                </li>
+            </ul> 
+        </div>
+
+    </div>
+</div>
\ No newline at end of file
diff --git a/vas/rest/conf/constants.inc b/vas/rest/conf/constants.inc
new file mode 100755
index 00000000..d4d3d5ab
--- /dev/null
+++ b/vas/rest/conf/constants.inc
@@ -0,0 +1,10 @@
+<?php
+// Définition des constantes
+if (!defined("CR")) {
+	define ("CR",chr(13));
+	define ("LF",chr(10));
+	define ("HT",chr(9));
+}
+define ("VM_FALSE",0);
+define ("VM_TRUE",1);
+?>
\ No newline at end of file
diff --git a/vas/rest/conf/php_conf.inc b/vas/rest/conf/php_conf.inc
new file mode 100755
index 00000000..01914190
--- /dev/null
+++ b/vas/rest/conf/php_conf.inc
@@ -0,0 +1,14 @@
+<?php
+//Définition de l'include path
+set_include_path(get_include_path() . PATH_SEPARATOR . $properties['vas_home']."/rest/class");
+//Définition de l'utilisation de cookies pour les variables de sessions
+ini_set("session.use_cookies", 0);
+ini_set("upload_tmp_dir", $properties["extract_dir"]);
+//Définition de la portée des cookies et de leur durée de vie
+if (isset($properties["cookie_path"]))
+    session_set_cookie_params($properties["cookie_lifetime"], $properties["cookie_path"]);
+// max_execution_time
+ini_set("max_execution_time", $properties["max_execution_time"]);
+// error_log
+ini_set("error_log", $properties['vas_home']."/server/php/log/php_".date('Y-m').".log");
+?>
diff --git a/vas/rest/conf/properties.inc b/vas/rest/conf/properties.inc
new file mode 100755
index 00000000..a0cce7d0
--- /dev/null
+++ b/vas/rest/conf/properties.inc
@@ -0,0 +1,78 @@
+<?php
+require "constants.inc";
+require "properties_server.inc";
+require "properties_domain.inc";
+require "selected_properties.inc";
+$properties['language'] = 'fr';
+$properties['cookie_lifetime'] = 525600;
+$properties['max_upload_file_size'] = 100 * 1024 * 1024;
+$properties['max_execution_time'] = 3600;
+$properties['max_request_time'] = 10;
+$properties['minimum_refresh_period'] = 100;
+$properties['forbidden_extension'] = '*.bat|*.com|*.exe|*.php|*.phtml|*.vhtml|*.js|*.vbe|*.wsf|*.dll';
+$properties['rows_per_page'] = 20;
+$properties['extract_dir'] = "{$properties['vas_home']}/tmp";
+$properties['date_format'] = 'd/m/Y';
+$properties['log_mode'] = true;
+$properties['debug_mode'] = false;
+$properties['log_period'] = 'Y-m';
+$properties['log_size'] = 2048;
+$properties['shared_dir'] = "{$properties['vas_home']}/shared";
+$properties['public_alias'] = 'public[ENV]';
+$properties['services_alias'] = 'rest[ENV]';
+$properties['doc_alias'] = 'doc[ENV]';
+$properties['ws_data_alias'] = 'ws_data[ENV]';
+$properties['proxy_check_ssl'] = true;
+$properties['mixed_rights_management'] = true;
+$properties['allow_public_connection'] = false;
+$properties['public_login'] = '';
+$properties['public_password'] = '';
+$properties['public_token'] = '';
+$properties["sign_up"] = "disabled";
+$properties["password_forgotten"] = "disabled";
+$properties["unsubscribe"] = false;
+$properties['geolocation_enabled'] = false;
+$properties['login_remember_me'] = 'enabled';
+$properties['login_remember_me_default'] = true;
+$properties['server_timezone'] = 'Europe/Paris';
+
+//inscription automatique
+$properties['advanced_login_page'] = false;
+$properties['automated_sign_up'] = false;
+$properties['enable_error_notification'] = false;
+$properties['mail_tag_subject'] = '[VITIS] ';
+//propriétés existentes dans GTF
+$properties['mail_sender'] = 'vitis@domaine.com';
+$properties['nickname_sender'] = 'Vitis';
+$properties['smtp_host'] = 'smtp.domaine.com';
+$properties['smtp_port'] = 26;
+$properties['smtp_authentification'] = true;
+$properties['smtp_login'] = 'login@domaine.com';
+$properties['smtp_password'] = 'password';
+//si automated_sign_up === false or error_notification === true
+$properties["admin_sign_up"] = "login@domaine.com";
+//pour l'inscription
+$properties["google_private_captcha"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+// pour identifier la machine
+$properties["instanceIdentifier"] = "";
+// Notifications par SMS
+$properties['sms_notifications'] = false;
+
+// Require tous les fichiers de tous les dossiers contenus sans properties
+$aDir = scandir(__DIR__);
+foreach ($aDir as $dir) {
+	if($dir != '.' && $dir != '..'){
+		if(is_dir(__DIR__.'/'.$dir)){
+			$aFiles = scandir(__DIR__.'/'.$dir);
+			foreach ($aFiles as $file) {
+				if((filetype(__DIR__.'/'.$dir.'/'.$file) == 'file') && (pathinfo(__DIR__.'/'.$dir.'/'.$file)['extension']) == 'inc' && $file != "version.inc"){
+					require_once __DIR__.'/'.$dir.'/'.$file;
+				}
+			}
+		}
+	}
+}
+
+require "properties_post.inc";
+include "php_conf.inc";
+?>
diff --git a/vas/rest/conf/properties_domain.inc b/vas/rest/conf/properties_domain.inc
new file mode 100755
index 00000000..e0ae3600
--- /dev/null
+++ b/vas/rest/conf/properties_domain.inc
@@ -0,0 +1,3 @@
+<?php
+$properties['domain'] [""] = "";
+?>
diff --git a/vas/rest/conf/properties_post.inc b/vas/rest/conf/properties_post.inc
new file mode 100755
index 00000000..cc6005fe
--- /dev/null
+++ b/vas/rest/conf/properties_post.inc
@@ -0,0 +1,18 @@
+<?php
+$properties['page_encoding'] = 'UTF-8';
+$properties["log_delim"] = HT;
+$properties['log_dir'] = $properties['vas_home'] . '/log/web';
+$properties['sql_log_file'] = $properties['log_dir'] . '/' . date($properties["log_period"]) . '/sql.log';
+$properties['sql_error_log_file'] = $properties['log_dir'] . '/' . date($properties["log_period"]) . '/sql_error.log';
+$properties['error_log_file'] = $properties['log_dir'] . '/error.log';
+$properties['connexion_log_file'] = $properties['log_dir'] . '/' . date($properties["log_period"]) . '/connexion.log';
+$properties['debug_log_file'] = $properties['log_dir'] . '/' . date($properties["log_period"]) . '/debug.log';
+$properties['proxy_log_file'] = $properties['log_dir'] . '/' . date($properties["log_period"]) . '/proxy.log';
+$properties['upload_dir'] = $properties['vas_home'] . '/upload';
+$properties['login'] = 'u_scheduler';
+$properties['convert_utf8'] = false;
+$properties['dir_export'] = $properties['vas_home'] . '/public';
+$properties['url_export'] = $properties['web_server_name'] . '/' . $properties['public_alias'];
+$properties['ws_data_dir'] = $properties['vas_home'] . '/ws_data';
+
+?>
\ No newline at end of file
diff --git a/vas/rest/conf/properties_server.inc b/vas/rest/conf/properties_server.inc
new file mode 100644
index 00000000..2d1208b5
--- /dev/null
+++ b/vas/rest/conf/properties_server.inc
@@ -0,0 +1,50 @@
+<?php
+$properties['vas_home'] = '[VAS_HOME]';
+$properties['sgbd'] = 'pgsql';
+$properties['database'] = '[DATABASE]';
+$properties['server'] = '[SERVER]';
+$properties['port'] = [PORT];
+$properties['schema_framework'] = 's_vitis';
+if (!empty($_SERVER["HTTP_HOST"]))
+    $properties['web_server_name'] = 'https://' . $_SERVER["HTTP_HOST"];
+else
+    $properties['web_server_name'] = 'https://' . strtolower(gethostname());
+$properties['log_directories'] ['Apache'] = "[APACHE]/logs";
+$properties['log_directories'] ['Php'] = $properties['vas_home']."/server/php/log";
+$properties['log_directories'] ['Application'] = $properties['vas_home']."/log";
+$properties['websocket_server'] = '127.0.0.1';
+$properties['websocket_port'] = [WEBSOCKET_PORT];
+$properties['websocket_alias'] = 'websocket[ENV]';
+$properties['environment_alias'] = '[ENV]';
+$properties["vitis_owner_login"] = 'u_vitis';
+$properties["vitis_owner_pass"] = '[U_VITIS_PASSWORD]';
+
+$properties['db_superuser_login'] = $properties["vitis_owner_login"];
+$properties['db_superuser_pass'] = $properties["vitis_owner_pass"];
+
+//inscription automatique
+$properties['applink_redirection'] = $properties['web_server_name'] . '/';
+
+$properties['SaveSentMail'] = false; 
+//si true remplir le bloc en dessous
+$properties['imapBotSender_host'] = "imap.domaine.com";
+$properties['imapBotSender_port'] = 993;
+$properties['imapBotSender_login'] = "login@domaine.com";
+$properties['imapBotSender_pwd'] = "password";
+$properties['imapBotSender_encrypt'] = "ssl";
+//privilèges à donner aux nouveaux inscrits
+$properties['sign_up_automated_roles'] = array();
+//liste des personne à mettre en copie du mail de notification si validation par administrateur (trois separateurs possibles ,| |;)
+$properties['sign_up_CC'] = "";
+$properties["application_title"] = '';
+$properties["use_favicon"] = true;
+$properties["favicon_path"] = "images/favicon.ico";
+$properties['pg_utils_root_path'] = "{$properties['vas_home']}/server/pgutils";
+$properties['sign_up_domain_forbidden'] = false; // array('yopmail.fr','yopmail.net','yopmail.com','cool.fr.nf','jetable.fr.nf','nospam.ze.tc','nomail.xl.cx','mega.zik.dj','speed.1s.fr','courriel.fr.nf','moncourrier.fr.nf','monemail.fr.nf','monmail.fr.nf','nwytg.com', 'vmani.com', 'emailna.co');
+// remplacer par un array de domaine comme forbidden pour n'autoriser que certain domaine à s'inscrire
+$properties['sign_up_domain_granted'] = false; // array('gmail.com');
+// properties d'accés au service de notification
+$properties["notifierDeploymentName"] = "test";
+$properties["notifierAccessKeyAccount"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+$properties["notifierSecretKeyAccount"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+?>
diff --git a/vas/rest/conf/selected_properties.inc b/vas/rest/conf/selected_properties.inc
new file mode 100755
index 00000000..6f49e8d8
--- /dev/null
+++ b/vas/rest/conf/selected_properties.inc
@@ -0,0 +1,143 @@
+<?php
+
+$properties['aAdminFields'] = Array();
+$properties['aUserFields'] = Array();
+$aAdminFields = Array(
+    'websocket_server',
+    'websocket_port',
+    'websocket_alias',
+    'vas_home',
+    'sgbd',
+    'database',
+    'server',
+    'port',
+    'schema_framework',
+    'web_server_name',
+    'log_directories.Apache',
+    'log_directories.Php',
+    'log_directories.Application',
+    'language',
+    'cookie_lifetime',
+    'max_upload_file_size',
+    'max_execution_time',
+    'max_request_time',
+    'minimum_refresh_period',
+    'refresh_period',
+    'forbidden_extension',
+    'rows_per_page',
+    'extract_dir',
+    'date_format',
+    'log_mode',
+    'debug_mode',
+    'log_period',
+    'log_size',
+    'shared_dir',
+    'public_alias',
+    'services_alias',
+    'doc_alias',
+    'ws_data_alias',
+    'proxy_check_ssl',
+    'mixed_rights_management',
+    'allow_public_connection',
+    'public_login',
+    'public_password',
+    'public_token',
+    'shared_dir',
+    'domain',
+    'domain.*',
+    'page_encoding',
+    'log_delim',
+    'log_dir',
+    'sql_log_file',
+    'error_log_file',
+    'connexion_log_file',
+    'debug_log_file',
+    'upload_dir',
+    'login',
+    'convert_utf8',
+    'dir_export',
+    'url_export',
+    'ws_data_dir',
+    'sevenzip_root_dir',
+    'sign_up',
+    'unsubscribe',
+    'password_forgotten',
+    'unsubscribe',
+    'geolocation_enabled',
+    'private_captcha_key',
+    'login_remember_me',
+    'login_remember_me_default',
+    'application_title',
+    'use_favicon',
+    'favicon_path',
+    'google_private_captcha',
+    'admin_sign_up',
+    'enable_error_notification',
+    'mail_tag_subject',
+    'advanced_login_page',
+    'automated_sign_up',
+    'mail_sender',
+    'nickname_sender',
+    'smtp_host',
+    'smtp_port',
+    'smtp_authentification',
+    'smtp_login',
+    'instanceIdentifier',
+    'smtp_password',
+    'sms_notifications',
+    'server_timezone'
+);
+$aUserFields = Array(
+    'websocket_alias',
+    'web_server_name',
+    'language',
+    'cookie_lifetime',
+    'max_upload_file_size',
+    'max_execution_time',
+    'max_request_time',
+    'minimum_refresh_period',
+    'refresh_period',
+    'forbidden_extension',
+    'rows_per_page',
+    'date_format',
+    'debug_mode',
+    'public_alias',
+    'services_alias',
+    'doc_alias',
+    'ws_data_alias',
+    'domain',
+    'domain.*',
+    'page_encoding',
+    'convert_utf8',
+    'url_export',
+    'sign_up',
+    'unsubscribe',
+    'password_forgotten',
+    'unsubscribe',
+    'geolocation_enabled',
+    'private_captcha_key',
+    'login_remember_me',
+    'login_remember_me_default',
+    'application_title',
+    'use_favicon',
+    'favicon_path',
+    'google_private_captcha',
+    'admin_sign_up',
+    'enable_error_notification',
+    'mail_tag_subject',
+    'advanced_login_page',
+    'automated_sign_up',
+    'mail_sender',
+    'nickname_sender',
+    'smtp_host',
+    'smtp_port',
+    'smtp_authentification',
+    'smtp_login',
+    'instanceIdentifier',
+    'smtp_password',
+    'sms_notifications',
+    'server_timezone'
+);
+$properties['aAdminFields'] = array_merge($properties['aAdminFields'], $aAdminFields);
+$properties['aUserFields'] = array_merge($properties['aUserFields'], $aUserFields);
+?>
diff --git a/vas/rest/conf/version.inc b/vas/rest/conf/version.inc
new file mode 100755
index 00000000..1e323190
--- /dev/null
+++ b/vas/rest/conf/version.inc
@@ -0,0 +1,7 @@
+<?php
+// Numéro de la version de Vitis
+define ("VM_VERSION", "[VERSION]");
+define ("VM_BUILD", "[BUILD]");
+define ("VM_MONTH_YEAR", "[MONTH_YEAR]");
+define ("VM_STATUS", "UNSTABLE");
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Accounts.class.inc b/vas/rest/ws/vitis/Accounts.class.inc
new file mode 100755
index 00000000..848ff49a
--- /dev/null
+++ b/vas/rest/ws/vitis/Accounts.class.inc
@@ -0,0 +1,662 @@
+<?php
+
+/**
+ * \file accounts.class.inc
+ * \class accounts
+ *
+ * \author Anthony Borghi <anthony.borghi@veremes.com>.
+ *
+ *  \brief This file contains the Accounts php class
+ *
+ * This class defines Rest Api to Vitis Accounts
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+require_once __DIR__ . '/../../class/vmlib/phpUtil.inc';
+/*
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\Exception;
+require_once 'PHPMailer/src/Exception.php';
+require_once 'PHPMailer/src/PHPMailer.php';
+require_once 'PHPMailer/src/SMTP.php';
+*/
+
+require_once __DIR__ . '/../../class/vmlib/Email.class.inc';
+
+class Accounts extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/accounts",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/accounts")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Accounts",
+     *   description="Operations about accounts"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+    }
+
+    /**
+     * @SWG\Get(path="/accounts/{operation_id}/{command}",
+     *   tags={"Accounts"},
+     *   summary="Send a mail to ask admin confirmation",
+     *   description="Send a mail to ask admin confirmation",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="group token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="operation_id",
+     *     in="path",
+     *     description="(fpwd, sign_up)",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="command",
+     *     in="path",
+     *     description="(confirm, update)",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="fullname",
+     *     in="formData",
+     *     description="name of user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="password",
+     *     in="formData",
+     *     description="password of user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/accounts")
+     *     )
+     *  )
+     */
+    function GET() {
+        require 'Accounts.class.mail.inc';
+        if ($this->aProperties["advanced_login_page"] === false) {
+            http_response_code(403);
+        } else {
+            if (isset($this->aPath[3])) {
+                if ($this->aPath[3] == "confirm") {
+                    if ($this->aPath[2] === "sign_up") {
+                        session_id($this->aValues["token"]);
+                        session_start();
+                        $sMessage = $this->addUser();
+                        if ($this->aProperties["automated_sign_up"]) {
+                            $sHtml = $this->bodyReplacer($aMail["signUpConfirmation"]);
+                        } else {
+                            $sRoleList = implode(", ", $this->aProperties["sign_up_automated_roles"]) . ", vitis_user";
+                            $sContent = str_replace("[ROLES]", $sRoleList, $aMail["SignUpOk"]);
+                            //$sHtml = str_replace("[CONTENT]", $sContent, $aMail["confirmationSignUp"]);
+                            $sHtml = $this->bodyReplacer($sContent);
+                            //$sContentMail = htmlentities($aMail["signUpConfirmation"]);
+                            //$sMail = str_replace("[CONTENT]", $sContentMail, $aMail["confirmationSignUp"]);
+                            $sMail = utf8_encode($this->bodyReplacer($aMail["signUpConfirmation"]));
+
+                            $sCC = "";
+                            if(isset($this->aProperties["sign_up_CC"])){
+                                $sCC = $this->aProperties["sign_up_CC"];
+                            }
+                                
+                            foreach($_SESSION[$this->aValues["datakey"]] as $sKey => $sValue){
+                                $sCC = str_replace("[".strtoupper($sKey)."]", $sValue, $sCC);
+                                $sMail = str_replace("[".strtoupper($sKey)."]", $sValue, $sMail);
+                            }
+                            $this->sendMail($_SESSION[$this->aValues["datakey"]]["email"], $sMail, $aMail["confirmationSignUpTitle"], $sCC);
+                        }
+                        $_SESSION[$this->aValues["datakey"]] = array();
+                        //session_destroy();
+                        return $sHtml;
+                    }
+                    if ($this->aPath[2] === "fpwd") {
+                        // check session
+                        session_id($this->aValues["token"]);
+                        session_start();
+
+                        if (isset($_SESSION[$this->aValues["datakey"]]["login"])) {
+                            // Login
+                            $sUrl = $this->aProperties["web_server_name"] . "/" . $this->aProperties["services_alias"] . "/vitis/accounts/fpwd/update?token=" . $this->aValues["token"] . "&output=text/html&datakey=" . $this->aValues["datakey"];
+                            $sContent = str_replace("[TOKEN]", $this->aValues["token"], $aMail["fpwdForm"]);
+                            $sContent = str_replace("[URL]", $sUrl, $sContent);
+                            $sHtml = $this->bodyReplacer($sContent, $aMail["passwordScript"]);
+                        } else {
+                            //$sContent = str_replace("[CONTENT]", $aMail["alreadyUpdate"], $aMail["confirmationSignUp"]);
+                            $sHtml = $this->bodyReplacer($aMail["alreadyUpdate"]);
+                        }
+
+                        return $sHtml;
+                    }
+                }
+                if ($this->aPath[3] == "update" || $this->aPath[3] == "error") {
+                    if ($this->aPath[2] === "fpwd") {
+                        $sContent = $this->bodyReplacer($aMail["fpwdUpdateOk"]);
+                            if ($this->aPath[3] == "error") {
+                                $sContent = $this->bodyReplacer($aMail["fpwdUpdateError"]);
+                            }
+                            return $sContent;
+                        /*require 'Accounts.class.sql.inc';
+                        // check session
+                        session_id($this->aValues["token"]);
+                        session_start();
+                        if (isset($_SESSION["login"])) {
+                            // update password if sent
+                            $oBd = new BD($this->aProperties["db_superuser_login"], $this->aProperties["db_superuser_pass"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"]);
+                            $oSgbdDataAccess = new PgsqlDataAccess($oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+                            $sErrorMessage = $oSgbdDataAccess->updateUserPassword(utf8_encode($_SESSION["login"]), $this->aValues["password"]);
+                            $sContent = $this->bodyReplacer($aMail["fpwdUpdateOk"]);
+                            if ($sErrorMessage != "") {
+                                $sContent = $this->bodyReplacer($aMail["fpwdUpdateError"]);
+                            }
+                            //return html page to confirm success or error
+                            $_SESSION = array();
+                            session_destroy();
+                        }
+                        return $sContent;*/
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @SWG\Post(path="/accounts/{operation_id}",
+     *   tags={"Accounts"},
+     *   summary="Send a mail to ask admin confirmation",
+     *   description="Send a mail to ask admin confirmation",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="group token",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="operation_id",
+     *     in="path",
+     *     description="(fpwd, sign_up)",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="username",
+     *     in="formData",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="fullname",
+     *     in="formData",
+     *     description="name of user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="password",
+     *     in="formData",
+     *     description="password of user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="mail",
+     *     in="formData",
+     *     description="mail of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="company",
+     *     in="formData",
+     *     description="organization of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/accounts")
+     *     )
+     *  )
+     */
+
+    /**
+     * request to add an account or get the password
+     * @return error message or confirmation
+     */
+    function POST() {
+        require 'Accounts.class.mail.inc';
+        if ($this->aProperties["advanced_login_page"] === false) {
+            http_response_code(403);
+        } else {
+            // Utilisateur en minuscule.
+            if (!empty($this->aValues["username"]))
+                $this->aValues["username"] = strtolower($this->aValues["username"]);
+            //
+            if (isset($this->aPath[2])) {
+                if ($this->aPath[2] == "sign_up") {
+                    //check Captcha
+                    $sUrl = "https://www.google.com/recaptcha/api/siteverify";
+                    $aData = array("secret"=>$this->aProperties["google_private_captcha"], "response"=>$this->aValues["captcha"]);
+                    //$sUrl = str_replace("[CAPTCHA]", $this->aValues["captcha"], $sUrl);
+                    //$sUrl = str_replace("[SECRET]", $this->aProperties["google_private_captcha"], $sUrl);
+                    //$verifyResponse = file_get_contents($sUrl, false, $context);
+                    $responseData = json_decode($this->postCurlRequest ($sUrl, $aData));
+                    if ($responseData->success) {
+                        // check login available and mail is on granted domain
+                        if (!$this->checkUserInfo()) {
+                            // the login is already used
+                            $sMessage = json_encode(array("status" => 5, "document_id" => $this->aValues["my_vitis_id"]));
+                        } else if(!$this->checkDomainMail()){
+                            //the mail is on a forbidden or ungranted domain
+                            $sMessage = json_encode(array("status" => 8, "document_id" => $this->aValues["my_vitis_id"]));
+                        } else {
+                            // en cas de compte public
+                            //$sToken = session_create_id ('signup'); // mieux vos utilisé le truc de vitis
+                            //session_id($sToken);
+                            $sToken = session_id();
+                            //if($sToken == "undefined"){
+                                //$sToken = session_create_id ();
+                                //session_id($sToken);
+                            //}
+
+                            session_start();
+                            $sDataKey = getUniqRandomId();
+
+                            $_SESSION[$sDataKey] = array();
+                            $_SESSION[$sDataKey]["login"] = $this->aValues["username"];
+                            $_SESSION[$sDataKey]["name"] = $this->aValues["fullname"];
+                            $_SESSION[$sDataKey]["email"] = $this->aValues["mail"];
+
+                            foreach($this->aValues as $sKey => $sValue){
+                                $_SESSION[$sDataKey][$sKey] = $sValue;
+                            }
+                            
+                            $sUrl = $this->aProperties["web_server_name"] . "/" . $this->aProperties["services_alias"] . "/vitis/accounts/sign_up/confirm?token=" . $sToken . "&output=text/html&datakey=" . $sDataKey;
+                            $sContent = str_replace("[HOSTNAME]", str_replace("https://", "", $this->aProperties["web_server_name"]), $aMail["newUserBody"]);
+
+                            //$sContent = str_replace("[LOGIN]", $_SESSION["login"], $sContent);
+                            //$sContent = str_replace("[MAIL]", $_SESSION["email"], $sContent);
+                            //$sContent = str_replace("[COMPANY]", $_SESSION["company"], $sContent);
+                            $sContent = str_replace("[URL]", $sUrl, $sContent);
+                            //$sBody = utf8_encode($this->bodyReplacer($sContent));
+                            if (!$this->aProperties["automated_sign_up"]) {
+                                $this->aValues["fullname"] = "";
+                            }
+                            // remplacement des valeurs envoyé
+                            foreach($this->aValues as $sKey => $sValue){
+                                $sContent = str_replace("[".strtoupper($sKey)."]", $sValue, $sContent);
+                            }
+                            if ($this->aProperties["automated_sign_up"]) {
+                                $sContent = str_replace("[TITLE]", $aMail["newUserTitleAutomated"], $sContent);
+                                //$sContent = str_replace("[FULLNAME]", $_SESSION["name"], $sContent);
+                                $sBody = utf8_encode($this->bodyReplacer($sContent));
+                                // send mail to admin
+                                $this->sendMail($this->aValues["mail"], $sBody, $aMail["newUserTitleAutomated"]);
+                            } else {
+                                $sContent = str_replace("[TITLE]", $aMail["newUserTitle"], $sContent);
+                                //$sContent = str_replace(" [FULLNAME]", "", $sContent);
+                                $sBody = utf8_encode($this->bodyReplacer($sContent));
+                                // send mail to admin
+                                $this->sendMail($this->aProperties["admin_sign_up"], $sBody, $aMail["newUserTitle"]);
+                            }
+                            $sMessage = json_encode(array("status" => 1, "document_id" => $this->aValues["my_vitis_id"]));
+                        }
+                    } else {
+                        $sMessage = json_encode(array("status" => 6, "document_id" => $this->aValues["my_vitis_id"]));
+                    }
+                } elseif ($this->aPath[2] == "fpwd") {
+                    // forgot password
+                    // check data with database
+                    if ($this->checkUserInfos()) {
+                        // en cas de compte public
+                        //$sToken = session_create_id ('fpwd');
+                        //session_id($sToken);
+                        //create Token and insert it in url
+                        $sToken = session_id();
+                        if($sToken == "undefined"){
+                            $sToken = session_create_id ();
+                            session_id($sToken);
+                        }
+
+                        session_start();
+                        
+                        $sDataKey = getUniqRandomId();
+
+                        $_SESSION[$sDataKey] = array();
+                        $_SESSION[$sDataKey]["login"] = $this->aValues["username"];
+                        $_SESSION[$sDataKey]["mail"] = $this->aValues["mail"];
+                        $sUrl = $this->aProperties["web_server_name"] . "/" . $this->aProperties["services_alias"] . "/vitis/accounts/fpwd/confirm?token=" . $sToken . "&output=text/html&datakey=" . $sDataKey;
+                        $sContent = str_replace("[LOGIN]", $this->aValues["username"], $aMail["fpwdBody"]);
+                        $sContent = str_replace("[HOSTNAME]", str_replace("https://", "", $this->aProperties["web_server_name"]), $sContent);
+                        $sContent = str_replace("[URL]", $sUrl, $sContent);
+                        $sBody = utf8_encode($this->bodyReplacer($sContent));
+                        // send mail to user
+                        $this->sendMail($this->aValues["mail"], $sBody, $aMail["fpwdTitle"]);
+                        $sMessage = json_encode(array("status" => 1, "document_id" => $this->aValues["my_vitis_id"]));
+                    } else {
+                        $sMessage = json_encode(array("status" => 7, "document_id" => $this->aValues["my_vitis_id"]));
+                    }
+                }
+            }
+        }
+        return $sMessage;
+    }
+
+    function postCurlRequest ($sUrl, $postfields) {
+        $ch = curl_init($sUrl);
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json"));
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_POST, 1);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+        return curl_exec($ch);
+    }
+
+    function checkUserInfo() {
+        require 'Accounts.class.sql.inc';
+        // new objet bd
+        $oBd = new BD($this->aProperties["db_superuser_login"], $this->aProperties["db_superuser_pass"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"]);
+        // check if login exist
+        $aParams['SCHEMA'] = array('value' => $this->aProperties["schema_framework"], 'type' => 'schema_name');
+        $aParams['USERNAME'] = array('value' => $this->aValues["username"], 'type' => 'string');
+        $oPDOresult = $oBd->executeWithParams($aSql['UserExists'], $aParams);
+        if ($oBd->nombreLigne($oPDOresult) > 0) {
+            return false;
+        }
+        return true;
+    }
+
+    function checkUserInfos() {
+        require 'Accounts.class.sql.inc';
+        // new objet bd
+        $oBd = new BD($this->aProperties["db_superuser_login"], $this->aProperties["db_superuser_pass"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"]);
+        // check if login exist
+        $aParams['SCHEMA'] = array('value' => $this->aProperties["schema_framework"], 'type' => 'schema_name');
+        $aParams['USERNAME'] = array('value' => $this->aValues["username"], 'type' => 'string');
+        $aParams['MAIL'] = array('value' => $this->aValues["mail"], 'type' => 'string');
+        $oPDOresult = $oBd->executeWithParams($aSql['checkUser'], $aParams);
+        if ($oBd->nombreLigne($oPDOresult) > 0) {
+            return true;
+        }
+        return false;
+    }
+    
+    function checkDomainMail(){
+        $sMail = $this->aValues["mail"];
+        $sDomain = end(explode('@', $sMail));
+        // check if granted
+        if(!empty($this->aProperties["sign_up_domain_granted"])){
+            for($i = 0;$i < count($this->aProperties["sign_up_domain_granted"]);$i++){
+                if($this->aProperties["sign_up_domain_granted"][$i]=== $sDomain){
+                    return true;
+                }
+            }
+            return false;
+        }
+        // check if forbidden
+        if(!empty($this->aProperties["sign_up_domain_forbidden"])){
+            for($i = 0;$i < count($this->aProperties["sign_up_domain_forbidden"]);$i++){
+                if($this->aProperties["sign_up_domain_forbidden"][$i]=== $sDomain){
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    function sendMail($sMailAdress, $sBody, $sTitle, $sCC = "") {
+        $sMailStruct = array(
+            "to" => $sMailAdress,
+            "cc" => $sCC,
+            "cci"=> "",
+            "subject" => $this->aProperties['mail_tag_subject'] . $sTitle,
+            "body" => utf8_decode($sBody),
+            "aAttachments" => array()
+        );
+        $mail = new Email(null, null, $this->aProperties, null);
+        $mail->loadFromExernalDataStruct($sMailStruct);
+        //error_log("between load and send");
+        $mail->send();
+        //error_log("after send");
+        
+        /*
+        $mail = new PHPMailer;
+
+        $mail->isSMTP();                                                // Set mailer to use SMTP
+        $mail->SMTPDebug = 0;                                           // 3 pour voir les infos de connexion 
+        $mail->Debugoutput = function($str, $level) {
+            error_log("debug level $level; message: $str");
+        };
+        //$mail->AuthType = 'LOGIN';
+        $mail->Host = $this->aProperties["smtp_host"];                  // Specify main and backup SMTP servers
+        $mail->Port = $this->aProperties["smtp_port"];                  // TCP port to connect to
+        $mail->SMTPAuth = $this->aProperties["smtp_authentification"];  // Enable SMTP authentication
+        //$mail->Username = $this->aProperties["smtp_login"];             // SMTP username
+        //$mail->Password = $this->aProperties["smtp_password"];          // SMTP password
+        //$mail->SMTPSecure = 'tls';                                      // Enable TLS encryption, `ssl` also accepted (deprecated)
+
+        $mail->SMTPOptions = array(
+            'ssl' => array(
+                'verify_peer' => false,
+                'verify_peer_name' => false,
+                'allow_self_signed' => true
+            )
+        );
+
+        if ($this->aProperties["smtp_authentification"] === true) {
+            $mail->AuthType = 'LOGIN';
+            $mail->Username = $this->aProperties["smtp_login"];             // SMTP username
+            $mail->Password = $this->aProperties["smtp_password"];          // SMTP password
+            $mail->SMTPSecure = 'tls';                                      // Enable TLS encryption, `ssl` also accepted (deprecated)
+        }
+
+        $mail->setFrom($this->aProperties["mail_sender"], $this->aProperties["mail_sender"]);
+        $mail->addAddress($sMailAdress);                                // Add a recipient
+        $mail->addReplyTo($this->aProperties["mail_sender"], $this->aProperties["mail_sender"]);
+
+        $mail->isHTML(true);                                            // Set email format to HTML
+        $mail->CharSet = 'UTF-8';
+
+        $mail->Subject = $this->aProperties['mail_tag_subject'] . $sTitle;
+        $mail->Body = utf8_decode($sBody);
+
+        if (!$mail->send()) {
+            error_log('Mailer Error: ' . $mail->ErrorInfo);
+        }*/
+    }
+
+    function bodyReplacer($sContent, $sScript = "") {
+        require 'Accounts.class.mail.inc';
+        $sBody = str_replace('[CONTENT]', $sContent, $aMail["mainBody"]);
+        $sBody = str_replace('[REDIRECTION]', $this->aProperties['applink_redirection'] , $sBody);
+        $sBody = str_replace('[SCRIPT]', $sScript, $sBody);
+        return $sBody;
+    }
+
+    function addUser() {
+        require 'Accounts.class.sql.inc';
+        // new objet bd
+        $oBd = new BD($this->aProperties["db_superuser_login"], $this->aProperties["db_superuser_pass"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"]);
+        // check if login exist
+        $aParams['SCHEMA'] = array('value' => $this->aProperties["schema_framework"], 'type' => 'schema_name');
+        $aParams['USERNAME'] = array('value' => utf8_encode($_SESSION[$this->aValues["datakey"]]["login"]), 'type' => 'string');
+        $oPDOresult = $oBd->executeWithParams($aSql['UserExists'], $aParams);
+        if ($oBd->nombreLigne($oPDOresult) > 0) {
+            $oError = new VitisError(1, "user already exists");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            // create postgres user if not exists
+            $oSgbdDataAccess = new PgsqlDataAccess($oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+            $sErrorMessage = $oSgbdDataAccess->createSgbdUser($_SESSION[$this->aValues["datakey"]]["login"], $_SESSION[$this->aValues["datakey"]]["password"]);
+            if ($sErrorMessage != "") {
+                $oError = new VitisError(1, $sErrorMessage);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            } else {
+                // insertion s_vitis.user
+                //error_log(print_r(mb_detect_encoding($_SESSION[$this->aValues["datakey"]]["name"]), true));
+                $_SESSION[$this->aValues["datakey"]]["name"] = utf8_decode($_SESSION[$this->aValues["datakey"]]["name"]);
+                $_SESSION[$this->aValues["datakey"]]["company"] = utf8_decode($_SESSION[$this->aValues["datakey"]]["company"]);
+                $iId = $oBd->insert($this->aProperties['schema_framework'], 'v_user', $_SESSION[$this->aValues["datakey"]], $this->aProperties['schema_framework'] . '.seq_common', 'user_id');
+                if ($oBd->enErreur()) {
+                    $oError = new VitisError(1, $oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                }
+                //ajout des privileges
+                for ($i = 0; $i < count($this->aProperties["sign_up_automated_roles"]); $i++) {
+                    $aParams['ROLE'] = array('value' => $this->aProperties["sign_up_automated_roles"][$i], 'type' => 'column_name');
+                    $aParams['USERNAME'] = array('value' => utf8_encode($_SESSION[$this->aValues["datakey"]]["login"]), 'type' => 'column_name');
+                    $oPDOresult = $oBd->executeWithParams($aSql['setPrivilege'], $aParams);
+                    if ($oBd->enErreur()) {
+                        $oError = new VitisError(1, $oBd->getBDMessage());
+                        $aXmlRacineAttribute['status'] = 0;
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    }
+                }
+            }
+        }
+
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Put(path="/accounts/{user_id}/unsubscribe",
+     *   tags={"Accounts"},
+     *   summary="Disable an account",
+     *   description="Request to disable an account",
+     *   operationId="PUT",
+     *   produces={"application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="user_id",
+     *     in="path",
+     *     description="user_id account to disable",
+     *     required=true,
+     *     type="integer"
+     *   ),
+     * @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="user login to verify",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="confirmation Response",
+     *         @SWG\Schema(ref="#/definitions/accounts")
+     *     ),
+     * 
+     *  )
+     */
+    function PUT() {
+        $iStatus = 0;
+        $sMessage = "";
+
+        if($this->aPath[2] === "fpwd"){
+            require 'Accounts.class.sql.inc';
+            // check session
+            session_id($this->aValues["token"]);
+            session_start();
+            if (isset($_SESSION[$this->aValues["datakey"]]["login"])) {
+                // update password if sent
+                $oBd = new BD($this->aProperties["db_superuser_login"], $this->aProperties["db_superuser_pass"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"]);
+                $oSgbdDataAccess = new PgsqlDataAccess($oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+                $sErrorMessage = $oSgbdDataAccess->updateUserPassword(utf8_encode($_SESSION[$this->aValues["datakey"]]["login"]), $this->aValues["password"]);
+                $sContent = json_encode(array("sUrl" => $this->aProperties["web_server_name"] . "/" . $this->aProperties["services_alias"] . "/vitis/accounts/fpwd/update?output=text/html"));
+                if ($sErrorMessage != "") {
+                    $sContent = json_encode(array("sUrl" => $this->aProperties["web_server_name"] . "/" . $this->aProperties["services_alias"] . "/vitis/accounts/fpwd/error?output=text/html"));
+                }
+                //return html page to confirm success or error
+                $_SESSION[$this->aValues["datakey"]] = array();
+                //session_destroy();
+            }
+            return $sContent;
+        } else if ($this->aProperties["unsubscribe"] === true) {
+            if (in_array("vitis_admin", $this->oConnection->aPrivileges)||$_SESSION["ses_Login"] == $this->aValues["login"]) {
+                require 'Accounts.class.sql.inc';
+                $oBd = new BD($this->aProperties["db_superuser_login"], $this->aProperties["db_superuser_pass"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"]);
+
+                $aParams = array(
+                    "SCHEMA" => array("value" => $this->aProperties["schema_framework"], "type" => "column_name"),
+                    "USER_ID" => array("value" => $this->aValues["my_vitis_id"], "type" => "integer")
+                );
+                $oPDOresult = $oBd->executeWithParams($aSql['getUserToUnsubscribe'], $aParams);
+
+                if ($oBd->nombreLigne($oPDOresult) === 1) {
+                    $oUser = $oBd->ligneSuivante($oPDOresult);
+                    if ($this->aValues["login"] === $oUser["login"]) {
+                        if ($oUser["role"] !== "admin") {
+                            $aParams = array(
+                                "SCHEMA" => array("value" => $this->aProperties["schema_framework"], "type" => "column_name"),
+                                "LOGIN" => array("value" => $this->aValues["login"], "type" => "column_name"),
+                                "LOGIN2" => array("value" => $this->aValues["login"], "type" => "string")
+                            );
+
+                            $oBd->executeWithParams($aSql['disableAccount'], $aParams);
+                            $oBd->executeWithParams($aSql['emptyAccount'], $aParams);
+                            $iStatus = 1;
+                            $sMessage = "Compte désactivé";
+                        } else {
+                            $sMessage = "Le compte d'un administrateur ne peut pas être désactivé";
+                        }
+                    } else {
+                        $sMessage = "API incassable, oui monsieur !!!";
+                    }
+                } else {
+                    $sMessage = "L'id d'utilisateur que vous avez envoyé n'existe pas ou ne retourne pas qu'une seule ligne";
+                }
+            } else {
+                $sMessage = "Vous ne pouvez pas désactiver ce compte";
+            }
+        } else {
+            $sMessage = "La fonctionnalité de désinscription n'est pas activée sur ce serveur";
+        }
+        return json_encode(array("status" => $iStatus, "message" => $sMessage));
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Accounts.class.mail.inc b/vas/rest/ws/vitis/Accounts.class.mail.inc
new file mode 100755
index 00000000..ff03a074
--- /dev/null
+++ b/vas/rest/ws/vitis/Accounts.class.mail.inc
@@ -0,0 +1,617 @@
+<?php
+
+$aMail["newUserTitle"] = "Un nouvel utilisateur vient juste de s'inscrire";
+$aMail["newUserTitleAutomated"] = "Vérification de votre adresse mail";
+$aMail["newUserBody"] = '<!-- 1 Column Text + Button : BEGIN -->
+    <tr>
+        <td bgcolor="#ffffff" style="padding: 0px; text-align: center;background-color:#8c8c8c; height:50px; margin-bottom:10px;">
+            <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #FFFFFF; font-weight: normal;">[TITLE]</h1>
+        </td>
+    </tr>
+    <tr>
+        <td bgcolor="#ffffff" style="padding: 10px 20px; font-family: sans-serif; font-size: 15px; line-height: 20px; color: #000000; text-align: center;">
+            <p style="width:100%; font-weight:bold; text-align: justify; font-size: 20px;">Bonjour [FULLNAME],</p>
+            <p style="width:100%; text-align: left;font-size: 18px;">Nous vous remercions d\'avoir créé votre compte sur <b>[HOSTNAME]</b>.</p>
+            <p style="width:100%; text-align: left;font-size: 18px;"><b>Informations sur votre compte :</b></p>
+            <p style="width:100%; text-align: left;font-size: 18px;">Identifiant : [USERNAME]</p>
+            <p style="width:100%; text-align: left;font-size: 18px;">Mail : [MAIL]</p>
+            <p style="width:100%; text-align: left;font-size: 18px;">Organisme : [COMPANY] </p>
+            <p style="width:100%; text-align: left;font-size: 18px;margin-top: 20px;">Cliquez sur le bouton ci-dessous pour finaliser votre inscription :</p>
+        </td>
+    </tr>
+    <tr>
+        <td bgcolor="#ffffff" style="padding: 10px 20px; font-family: sans-serif; font-size: 20px; line-height: 20px; color: #555555;">
+            <table role="presentation" aria-hidden="true" cellspacing="0" cellpadding="0" border="0" align="center" style="margin: auto">
+                <tr>
+                    <td style="border-radius: 3px; background: #5cb85c; text-align: center;" class="button-td">
+                        <a href="[URL]" style="background: #5cb85c; border: 15px solid #5cb85c; font-family: sans-serif; font-size: 18px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 0px; font-weight: bold;" class="button-a">
+                            &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#ffffff;">Je confirme mon adresse mail</span>&nbsp;&nbsp;&nbsp;&nbsp;
+                        </a>
+                    </td>
+                </tr>
+            </table>
+            <!-- Button : END -->
+        </td>
+    </tr>
+    <tr>
+        <td bgcolor="#ffffff" style="padding: 10px 20px; font-family: sans-serif; line-height: 20px; color: #000000; text-align: center;">
+            <p style="width:100%; text-align: justify;font-size: 18px;">Si vous ne vous êtes pas inscrit(e) sur notre application <b>[HOSTNAME]</b>, ignorez simplement ce message.</p>
+        </td>
+    </tr>
+    <!-- 1 Column Text + Button : END -->';
+
+$aMail["confirmationSignUpTitle"] = "Confirmation d'inscription";
+$aMail["genericBody"] = '
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal;">[MESSAGE]</h1>
+                </td>
+            </tr>';
+
+$aMail["SignUpOk"] = '<tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal;">L\'utilisateur a été ajouté, connectez vous sur la base de données pour lui donner des droits (Defaut: [ROLES])</h1>
+                </td>
+            </tr>';
+$aMail["SignUpError"] = '<tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal;">L\'utilisateur n\'a pas pu être ajouté consultez les fichiers de log pour plus d\'informations</h1>
+                </td>
+            </tr>';
+
+$aMail["signUpConfirmation"] = '<tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal; margin-bottom: 15px;">Votre compte est maintenant activé, vous pouvez vous connecter. Pour avoir accès à plus de fonctionnalités contactez l\'administrateur</h1>
+                    <a style="margin: 0; font-family: sans-serif; font-size: 22px; font-weight: normal;" href="[REDIRECTION]"> Retourner vers l\'application </a>
+                </td>
+            </tr>';
+$aMail["fpwdTitle"] = "Changez votre mot de passe";
+$aMail["fpwdUpdateOk"] = '<tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal;">Le mot de passe a été mis à jour</h1>
+                </td>
+            </tr>';
+$aMail["fpwdUpdateError"] = '<tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal;">Le mot de passe n\'a pas pu être mis à jour</h1>
+                </td>
+            </tr>';
+$aMail["alreadyUpdate"] = '<tr>
+                <td bgcolor="#ffffff" style="padding: 40px 40px 20px; text-align: center;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #333333; font-weight: normal;">Le mot de passe à déjà été changé</h1>
+                </td>
+            </tr>';
+
+$aMail["fpwdBody"] = '<!-- 1 Column Text + Button : BEGIN -->
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 0px; text-align: center;background-color:#8c8c8c; height:50px; margin-bottom:10px;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #FFFFFF; font-weight: normal;">Changez votre mot de passe</h1>
+                </td>
+            </tr>
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 10px 20px; font-family: sans-serif; font-size: 15px; line-height: 20px; color: #000000; text-align: center;">
+                    <p style="width:100%; font-weight:bold; text-align: left; font-size: 20px;">Bonjour [LOGIN],</p>
+                    <p style="width:100%; text-align: left;font-size: 18px;">Une tentative de récupération de votre compte à été effectué sur le site <b>[HOSTNAME]</b>.</p>
+                    <p style="width:100%; text-align: left;font-size: 18px;margin-top: 10px;">Cliquez sur le bouton ci-dessous pour changer votre mot de passe :</p>
+                </td>
+            </tr>
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 10px 20px; font-family: sans-serif; font-size: 15px; line-height: 20px; color: #555555;">
+                    <table role="presentation" aria-hidden="true" cellspacing="0" cellpadding="0" border="0" align="center" style="margin: auto">
+                        <tr>
+                            <td style="border-radius: 3px; background: #5cb85c; text-align: center;" class="button-td">
+                                <a href="[URL]" style="background: #5cb85c; border: 15px solid #5cb85c; font-family: sans-serif; font-size: 18px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 0px; font-weight: bold;" class="button-a">
+                                    &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#ffffff;">Changer mon mot de passe</span>&nbsp;&nbsp;&nbsp;&nbsp;
+                                </a>
+                            </td>
+                        </tr>
+                    </table>
+                    <!-- Button : END -->
+                </td>
+            </tr>
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 10px 20px; font-family: sans-serif; line-height: 20px; color: #000000; text-align: center;">
+                    <p style="width:100%; text-align: justify;font-size: 18px;">Si vous n\'avez pas perdu votre mot de passe pour vous connecter à notre application <b>[HOSTNAME]</b>, ignorez simplement ce message.</p>
+                </td>
+            </tr>
+            <!-- 1 Column Text + Button : END -->';
+
+$aMail["fpwdForm"] = '<!-- 1 Column Text + Button : BEGIN -->
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 0px; text-align: center;background-color:#8c8c8c; height:50px; margin-bottom:10px;">
+                    <h1 style="margin: 0; font-family: sans-serif; font-size: 24px; line-height: 27px; color: #FFFFFF; font-weight: normal;">Saisissez votre nouveau mot de passe</h1>
+                </td>
+            </tr>
+            <tr>
+                <td bgcolor="#ffffff" style="padding: 20px 40px 40px; font-family: sans-serif; font-size: 15px; line-height: 20px; color: #555555; text-align: center;">
+                    <form style="text-align:-webkit-right;">
+                        <div style="text-align:left;">
+                            <label for="password" style="font-weight: bold;">Nouveau mot de passe</label>
+                            <input type="password" id="password" name="password" class="input-text-control" required/>
+                        </div>
+                        <div style="text-align:left;margin-top:10px;">
+                            <label for="password_confirm" style="font-weight: bold;">Confirmer votre nouveau mot de passe</label>
+                            <input type="password" id="password_confirm" name="password_confirm" class="input-text-control" required/>
+                        </div>
+                        <div style="margin-top:20px;">
+                            <input type="hidden" name="token" value="[TOKEN]"/>
+                            <input type="hidden" name="output" value="text/html"/>
+                            <button style="background: #5cb85c; border: 15px solid #5cb85c; font-family: sans-serif; font-size: 15px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 0px; font-weight: bold;" class="button-a" type="button" onclick="sendRequest(\'[URL]\')"><span style="color:#ffffff;">Envoi</span></button>
+                        </div>
+                    </form>
+                </td>
+            </tr>';
+
+$aMail["passwordScript"] = '<script>
+    var password = document.getElementById("password"), confirm_password = document.getElementById("password_confirm");
+
+        function validatePassword(){
+          if(password.value != confirm_password.value) {
+            confirm_password.setCustomValidity("Les deux mots de passe doivent être identique");
+          } else {
+            confirm_password.setCustomValidity(\'\');
+          }
+        }
+
+        password.onchange = validatePassword;
+        confirm_password.onkeyup = validatePassword;
+
+        function sendRequest (sUrl){
+            if(typeof(password.value)!== "undefined"){
+                if(password.value != ""){
+                    var xhr = new XMLHttpRequest();
+                    xhr.open("PUT", sUrl);
+                    sParams = JSON.stringify({"password": password.value});
+                    xhr.onreadystatechange = function (aEvt) {
+                        if (xhr.readyState == 4) {
+                            if (xhr.status == 200) {
+                                    var oJson = JSON.parse(xhr.responseText);
+                                    window.location.replace(oJson.sUrl);
+                            } else {
+                                    //xhr.responseText;
+                            }
+                        }
+                    }
+                    xhr.send(sParams);
+                }else{console.log("saisissez un mot de passe2")}
+            }else{console.log("saisissez un mot de passe")}
+        }
+    </script>';
+
+$aMail["mainBody"] = '<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8"> <!-- utf-8 works for most cases -->
+    <meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn\'t be necessary -->
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
+    <meta name="x-apple-disable-message-reformatting">  <!-- Disable auto-scale in iOS 10 Mail entirely -->
+    <title>VAM</title> <!-- The title tag shows in email notifications, like Android 4.4. -->
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+    <!-- Web Font / @font-face : BEGIN -->
+    <!-- NOTE: If web fonts are not required, lines 10 - 27 can be safely removed. -->
+
+    <!-- Desktop Outlook chokes on web font references and defaults to Times New Roman, so we force a safe fallback font. -->
+    <!--[if mso]>
+        <style>
+            * {
+                font-family: sans-serif !important;
+            }
+        </style>
+    <![endif]-->
+
+    <!-- All other clients get the webfont reference; some will render the font and others will silently fail to the fallbacks. More on that here: http://stylecampaign.com/blog/2015/02/webfont-support-in-email/ -->
+    <!--[if !mso]><!-->
+  <!-- insert web font reference, eg: <link href="https://fonts.googleapis.com/css?family=Roboto:400,700" rel="stylesheet" type="text/css"> -->
+  <!--<![endif]-->
+
+  <!-- Web Font / @font-face : END -->
+
+  <!-- CSS Reset -->
+  <style>
+
+  /* What it does: Remove spaces around the email design added by some email clients. */
+  /* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
+  html,
+  body {
+     margin: 0 auto !important;
+     padding: 0 !important;
+     height: 100% !important;
+     width: 100% !important;
+     /*min-width: 600px;*/
+ }
+
+ /* What it does: Stops email clients resizing small text. */
+ * {
+    -ms-text-size-adjust: 100%;
+    -webkit-text-size-adjust: 100%;
+}
+
+/* What it does: Centers email on Android 4.4 */
+div[style*="margin: 16px 0"] {
+    margin:0 !important;
+}
+
+/* What it does: Stops Outlook from adding extra spacing to tables. */
+table,
+td {
+    mso-table-lspace: 0pt !important;
+    mso-table-rspace: 0pt !important;
+}
+
+/* What it does: Fixes webkit padding issue. Fix for Yahoo mail table alignment bug. Applies table-layout to the first 2 tables then removes for anything nested deeper. */
+table {
+    border-spacing: 0 !important;
+    border-collapse: collapse !important;
+    table-layout: fixed !important;
+    margin: 0 auto !important;
+}
+table table table {
+    table-layout: auto;
+}
+
+/* What it does: Uses a better rendering method when resizing images in IE. */
+img {
+    -ms-interpolation-mode:bicubic;
+}
+
+/* What it does: A work-around for iOS meddling in triggered links. */
+*[x-apple-data-detectors] {
+    color: inherit !important;
+    text-decoration: none !important;
+}
+
+/* What it does: A work-around for Gmail meddling in triggered links. */
+.x-gmail-data-detectors,
+.x-gmail-data-detectors *,
+.aBn {
+    border-bottom: 0 !important;
+    //cursor: default !important;
+}
+
+/* What it does: Prevents Gmail from displaying an download button on large, non-linked images. */
+.a6S {
+ display: none !important;
+ opacity: 0.01 !important;
+}
+/* If the above doesn\'t work, add a .g-img class to any image in question. */
+img.g-img + div {
+ display:none !important;
+}
+
+/* What it does: Prevents underlining the button text in Windows 10 */
+.button-link {
+    text-decoration: none !important;
+}
+
+blockquote {
+  font-style:normal;
+  text-align:left;
+  //margin-left: 32px!important;
+  margin: 5px 5px 0px 32px!important;
+  //padding-top:10px;
+  //font-family:"Segoe Print","Times New Roman", Verdana;
+  padding-left: 7px;
+  min-height: 30px;
+  //background-color: #EFEFEF;
+  border-left: 2px solid #8c8c8c;  
+}
+
+blockquote > p {
+   margin:4.5px;
+}
+
+.input-text-control{
+    display: block;
+    width: 100%;
+    height: 14px;
+    padding: 4px 5px;
+    font-size: 12px;
+    line-height: 1.5;
+    border-radius: 3px;
+    color: #555;
+    background-color: #fff;
+    background-image: none;
+    border: 1px solid #ccc;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
+    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
+    -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
+    -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
+    transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
+}
+
+/* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89  */
+/* Create one of these media queries for each additional viewport size you\'d like to fix */
+/* Thanks to Eric Lepetit (@ericlepetitsf) for help troubleshooting */
+@media only screen and (min-device-width: 375px) and (max-device-width: 413px) { /* iPhone 6 and 6+ */
+    .email-container {
+        min-width: 375px !important;
+    }
+}
+
+</style>
+
+<!-- What it does: Makes background images in 72ppi Outlook render at correct size. -->
+    <!--[if gte mso 9]>
+    <xml>
+        <o:OfficeDocumentSettings>
+            <o:AllowPNG/>
+            <o:PixelsPerInch>96</o:PixelsPerInch>
+        </o:OfficeDocumentSettings>
+    </xml>
+<![endif]-->
+
+<!-- Progressive Enhancements -->
+<style>
+
+/* What it does: Hover styles for buttons */
+.button-td,
+.button-a {
+    transition: all 100ms ease-in;
+}
+.button-td:hover,
+.button-a:hover {
+    background: #449D44 !important;
+    border-color: #449D44 !important;
+}
+
+.bottom-strip{
+    width: 120px !important;
+    height: 10px !important;
+    float: left !important;
+}
+
+.square-logo-layout{
+    width: 40px;
+    float: left !important;
+    background-color: #FFF;//#24292E;
+    border-radius: 50%;
+    font-size: 30px;
+    padding: 7.5px;
+    margin-right: 0px;
+    //color: #FFF;
+    cursor:pointer !important;
+}
+
+.square-logo-layout > svg{
+    cursor:pointer!important;
+}
+
+
+/* Media Queries */
+@media screen and (max-width: 600px) {
+
+    .email-container {
+        width: 100% !important;
+        margin: auto !important;
+    }
+
+    /* What it does: Forces elements to resize to the full width of their container. Useful for resizing images beyond their max-width. */
+    .fluid {
+        max-width: 100% !important;
+        height: auto !important;
+        margin-left: auto !important;
+        margin-right: auto !important;
+    }
+
+    /* What it does: Forces table cells into full-width rows. */
+    .stack-column,
+    .stack-column-center {
+        display: block !important;
+        width: 100% !important;
+        max-width: 100% !important;
+        direction: ltr !important;
+    }
+    /* And center justify these ones. */
+    .stack-column-center {
+        text-align: center !important;
+    }
+
+    /* What it does: Generic utility class for centering. Useful for images, buttons, and nested tables. */
+    .center-on-narrow {
+        text-align: center !important;
+        display: block !important;
+        margin-left: auto !important;
+        margin-right: auto !important;
+        float: none !important;
+    }
+    table.center-on-narrow {
+        display: inline-block !important;
+    }
+
+    .input-text-control{
+        display: block;
+        width: 100%;
+        height: 14px;
+        padding: 4px 5px;
+        font-size: 12px;
+        line-height: 1.5;
+        border-radius: 3px;
+        color: #555;
+        background-color: #fff;
+        background-image: none;
+        border: 1px solid #ccc;
+        -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
+        box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
+        -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
+        -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
+        transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
+    }
+
+    /* What it does: Adjust typography on small screens to improve readability */
+    .email-container p {
+        font-size: 17px !important;
+        line-height: 22px !important;
+    }
+
+}
+
+</style>
+
+</head>
+<body width="100%" bgcolor="#E5E5E5" style="margin: 0px; mso-line-height-rule: exactly;">
+    <center style="width: 600px; margin: auto; background: #FFFFFF; text-align: left;">
+        <!-- Email Header : BEGIN -->
+        <table role="presentation" aria-hidden="true" aria-hidden="true" cellspacing="0" cellpadding="0" border="0" align="center" width="600" style="margin: auto;" class="email-container">
+           <tr>
+            <td style="padding: 20px 0px; text-align: center">
+             <a href="http://www.veremes.com/" target="_blank">
+                <svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="335px" height="100px" viewBox="0 0 335 100" enable-background="new 0 0 335 100" xml:space="preserve">
+                    <g>
+                        <rect fill="#FFFFFF" width="335" height="100"/>
+                        <g>
+                            <path fill="#1A171B" d="M308.774,60.788c-0.99-1.493-2.537-2.688-4.64-3.589c-0.533-0.224-1.577-0.57-3.142-1.042
+                                        c-1.563-0.47-2.75-0.959-3.567-1.472c-0.893-0.547-1.532-1.161-1.916-1.841c-0.386-0.682-0.577-1.517-0.577-2.511
+                                        c0-1.4,0.466-2.572,1.398-3.516c0.933-0.944,2.098-1.417,3.498-1.417c1.561,0,2.793,0.437,3.695,1.308
+                                        c0.901,0.873,1.402,2.1,1.505,3.681h4.622c-0.12-2.909-1.026-5.178-2.72-6.806c-1.69-1.626-3.972-2.439-6.845-2.439
+                                        c-2.71,0-5.016,0.916-6.921,2.744c-1.904,1.831-2.856,4.057-2.856,6.678c0,2.319,0.569,4.168,1.714,5.551
+                                        c1.143,1.383,3.582,2.734,7.318,4.056c2.334,0.858,3.947,1.775,4.838,2.754c0.891,0.98,1.336,2.274,1.336,3.884
+                                        c0,1.612-0.561,2.947-1.682,4.007c-1.121,1.063-2.526,1.592-4.219,1.592c-1.772,0-3.262-0.69-4.463-2.071
+                                        c-1.202-1.379-1.802-3.12-1.802-5.228v-0.122h-4.502c0.103,3.535,1.114,6.344,3.039,8.431c1.922,2.085,4.466,3.127,7.637,3.127
+                                        c3.108,0,5.674-0.952,7.698-2.853c2.025-1.899,3.038-4.301,3.038-7.205C310.261,64.182,309.764,62.279,308.774,60.788z
+                                         M118.462,41.021c-5.17,0-9.417,1.679-12.739,5.035c-3.32,3.357-4.979,7.607-4.979,12.742c0,4.912,1.693,9.118,5.084,12.617
+                                        c3.389,3.502,7.535,5.252,12.438,5.252c3.694,0,6.947-0.998,9.756-2.988c2.808-1.994,4.988-4.849,6.542-8.569h-4.866
+                                        c-1.103,2.332-2.666,4.151-4.688,5.459c-2.023,1.308-4.302,1.962-6.834,1.962c-3.575,0-6.558-1.131-8.947-3.394
+                                        c-2.391-2.263-3.718-5.226-3.983-8.894h30.413v-0.318c0-5.604-1.601-10.154-4.797-13.655
+                                        C127.662,42.771,123.529,41.021,118.462,41.021z M105.366,56.472c0.509-3.468,1.901-6.219,4.17-8.258
+                                        c2.27-2.037,5.04-3.056,8.313-3.056c3.517,0,6.368,0.948,8.556,2.844c2.188,1.897,3.692,4.719,4.509,8.47H105.366z M99.054,31.046
+                                        L84.898,69.101L72.402,35.38l0.007-0.047l-0.079-0.217c-0.401-1.095-0.841-2.3-1.34-3.546l-0.194-0.523h-0.021
+                                        c-2.108-5.143-5.249-10.879-10.817-12.957c-5.541-2.069-12.762-0.675-17.169,3.314c-3.422,3.096-5.471,7.843-6.089,14.111
+                                        c0-0.002-0.117,1.154-0.117,1.154c-0.239,2.31-0.481,4.665-0.354,7.034l0.047,0.874l0.875-0.048l2.31-0.124l0.876-0.046
+                                        l-0.049-0.876c-0.113-2.069,0.115-4.268,0.335-6.396c0-0.001,0.12-1.172,0.12-1.172c0.517-5.235,2.121-9.103,4.771-11.499
+                                        c3.349-3.03,8.825-4.09,13.024-2.522c4.294,1.604,6.994,6.964,8.88,11.717l1.387,3.688l0.208,0.57l0.005-0.004L83.24,75.692h3.407
+                                        l16.788-44.646H99.054z M268.755,41.021c-5.171,0-9.418,1.679-12.738,5.035c-3.32,3.357-4.979,7.607-4.979,12.742
+                                        c0,4.912,1.692,9.118,5.084,12.617c3.389,3.502,7.535,5.252,12.438,5.252c3.695,0,6.947-0.998,9.758-2.988
+                                        c2.807-1.994,4.986-4.849,6.54-8.569h-4.866c-1.102,2.332-2.666,4.151-4.688,5.459c-2.022,1.308-4.302,1.962-6.835,1.962
+                                        c-3.574,0-6.557-1.131-8.945-3.394c-2.392-2.263-3.72-5.226-3.984-8.894h30.415v-0.318c0-5.604-1.603-10.154-4.8-13.655
+                                        C277.955,42.771,273.821,41.021,268.755,41.021z M255.658,56.472c0.51-3.468,1.901-6.219,4.171-8.258
+                                        c2.27-2.037,5.039-3.056,8.314-3.056c3.516,0,6.367,0.948,8.555,2.844c2.187,1.897,3.692,4.719,4.509,8.47H255.658z
+                                         M148.164,42.625c-1.253,0.705-2.409,1.808-3.465,3.315v-3.946h-4.074v33.698h4.379V55.395c0-3.099,0.583-5.334,1.754-6.711
+                                        c1.17-1.376,3.11-2.187,5.821-2.431l-0.032-4.744C150.878,41.549,149.417,41.922,148.164,42.625z M172.22,41.021
+                                        c-5.171,0-9.418,1.679-12.738,5.035c-3.321,3.357-4.981,7.607-4.981,12.742c0,4.912,1.694,9.118,5.085,12.617
+                                        c3.389,3.502,7.535,5.252,12.438,5.252c3.695,0,6.947-0.998,9.757-2.988c2.808-1.994,4.988-4.849,6.541-8.569h-4.866
+                                        c-1.102,2.332-2.665,4.151-4.688,5.459c-2.023,1.308-4.303,1.962-6.834,1.962c-3.574,0-6.557-1.131-8.947-3.394
+                                        c-2.391-2.263-3.718-5.226-3.984-8.894h30.414v-0.318c0-5.604-1.6-10.154-4.799-13.655
+                                        C181.419,42.771,177.286,41.021,172.22,41.021z M159.124,56.472c0.51-3.468,1.901-6.219,4.17-8.258
+                                        c2.271-2.037,5.04-3.056,8.313-3.056c3.517,0,6.369,0.948,8.556,2.844c2.188,1.897,3.692,4.719,4.51,8.47H159.124z
+                                         M232.864,41.264c-2.51,0-4.779,0.509-6.809,1.518c-2.03,1.012-3.73,2.49-5.097,4.43c-1.106-1.818-2.712-3.264-4.82-4.338
+                                        c-2.108-1.072-4.441-1.61-7-1.61c-2.212,0-4.191,0.379-5.941,1.134c-1.748,0.756-3.27,1.88-4.558,3.372v-3.776h-4.258v33.698
+                                        h4.258V59.274c0-2.927,0.105-4.978,0.321-6.154c0.215-1.177,0.586-2.227,1.119-3.147c0.856-1.473,2.026-2.604,3.509-3.391
+                                        c1.481-0.787,3.203-1.182,5.165-1.182c3.248,0,5.66,0.926,7.233,2.777c1.573,1.852,2.36,4.722,2.36,8.61v18.905h4.136V59.274
+                                        c0-2.927,0.112-4.978,0.338-6.154c0.223-1.177,0.59-2.227,1.1-3.147c0.854-1.473,2.012-2.604,3.467-3.391
+                                        c1.457-0.787,3.143-1.182,5.06-1.182c3.318,0,5.711,0.947,7.178,2.84c1.469,1.894,2.202,5.07,2.202,9.529v17.923h4.137V58.658
+                                        c0-6.093-1.043-10.516-3.122-13.268C240.76,42.64,237.436,41.264,232.864,41.264z"/>
+                            <g>
+                            <path fill="#1A171B" d="M36.791,43.727c4.5,3.508,3.856-8.518,5.095-10.445c-0.251,0.39,1.045-0.227,1.359-0.68
+                                                c0.714-1.033,0.78-1.304,1.783-0.467c0.685,0.57,4.073-2.156,5.011-2.76c-0.206-0.223,0.68,1.338,0.68,0.764
+                                                c0,4.354-0.253,0.671,2.42,1.401c1.206,0.329,2.179-0.847,3.269,0.893c-0.283,0.31-0.566,0.621-0.849,0.933
+                                                c4.111,1.071,3.139,4.072,7.134,6.029c-1.239,0.545-2.304,1.363-2.463,2.803c1.169,0.267,2.366,0.422,3.566,0.424
+                                                c-0.34,0.311-0.679,0.622-1.02,0.934c2.158,0.346,2.307,2.235,4.671,1.699c-0.891,1.669-4.83,4.51-1.274,5.094
+                                                c-0.198,0.085-0.396,0.171-0.594,0.255c0.745,0.477,1.172,1.362,1.868,1.868c-0.946,0.11-1.794,0.679-2.802,0.68
+                                                c0.04,1.611,1.581,1.87,2.717,2.124c-2.577,1.72,0.311,0.894,0.722,2.122c-0.165-0.493,1.154,1.254,0.807,0.977
+                                                c-0.173-0.139-1.318,0.596-0.807,1.062c0.174,0.158,4.875,0.583,1.98,1.482c-1.714,0.534-4.447,0.456-3.679,2.763
+                                                c-1.174-0.126-1.886,0.235-2.845-0.083c0.154,0.687-0.067,0.846,0.213,1.442c-1.335,0.382-2.595-0.269-3.695-1.061
+                                                c-0.042,0.268-0.084,0.537-0.127,0.806c-0.368-0.325-0.736-0.649-1.104-0.976c0.016,0.536-0.255,1.096-0.212,1.656
+                                                c-0.877-0.677-5.258-4.209-2.972-1.189c0.905,1.195,1.842,1.439,2.93,2.463c-1.363,0.366-0.2,5.027,1.91,4.627
+                                                c-1.045,1.709-3.151-0.414-4.289,1.828c1.419,0.304,0.683,0.515,1.826,1.146c-0.596-0.139-1.35,0.109-1.996-0.043
+                                                c0.058,0.606,1.302,2.911,1.104,3.185c-0.761,1.05-2.778-1.146-3.949-1.146c-0.209,0.18-0.252,0.392-0.126,0.636
+                                                c1.264,0.254,0.742,0.52,0.976,1.698c-2.448-0.878-0.467,0.231-0.467,1.104c0,3.686-2.677-0.092-2.548,2.505
+                                                c-0.269-0.014-0.537-0.027-0.806-0.041c0.263,2.893-2.243-0.257-2.845,3.056c0.048,0.018-3.298-0.522-3.333-0.488
+                                                c-1.136,1.135-1.402-0.027-2.174,0.598c-1.87,1.514-1.024-1.807-1.552-1.998c-0.694-0.253-2.246,1.984-2.455,0.573
+                                                c-0.207-1.396-0.55-3.131-1.463-1.656c-0.954-0.37-3.546,0.314-3.842-0.572c-0.223-0.67-2.252-3.619-0.871-4.078
+                                                c-0.407,0.137-1.347,0.543-1.719,0.765c0.857-2.833-1.515-2.188-3.185-1.146c0.104-1.69,0.899-3.521-1.083-3.247
+                                                c0.293-0.662,0.337-1.645,0.828-2.356c-0.382,0.084-0.764,0.17-1.146,0.254c0.059-0.477,4.984-10.382,5.223-10.382
+                                                c-0.199-0.062-0.369-0.169-0.51-0.318c-1.236,3.129-3.048,5.804-5.095,8.534c0.046-0.52-0.061-1.008-0.318-1.464
+                                                c-0.23,0-1.983,2.339-2.548,2.61c0-0.253,0-0.509,0-0.763c-0.231,0.366-1.444,2.675-1.783,2.675c-0.329,0,0.481-1.796-0.51-1.467
+                                                c-0.944,0.315-1.458,0.54-2.292,0.701c0.99-1.181,1.719-2.432-0.446-1.783c0.204-0.955-0.191-1.231-0.191-1.974
+                                                c-0.159,0.41-0.393,0.771-0.7,1.084c-0.23-1.254-0.242-6.138-0.383-6.138c-1.46,0,0.123-2.937,0.341-3.312
+                                                c-0.17-0.142-0.341-0.282-0.51-0.425c0.05,1.16-0.433,1.305-0.764,2.293c-1.08-1.767,1.521-3.314-0.764-3.99
+                                                c0.311-0.256,0.623-0.51,0.934-0.765c-0.199-0.198-0.396-0.396-0.595-0.595c-0.269,0.61-0.729,1.216-1.02,1.783
+                                                c-0.154-0.479,0.034-2.888,0.51-2.888c-0.313-0.017-0.624-0.044-0.935-0.084c0.723-0.973,0.495-1.264,1.444-1.699
+                                                c-0.17-0.51-0.339-1.019-0.509-1.529c0.17,0.058,0.339,0.114,0.509,0.171c0.149,0.083-0.41-0.829-0.68-0.424
+                                                c0.503-0.754,1.123-1.223,1.868-1.614c-0.283-0.17-0.566-0.34-0.849-0.51c0.664-0.432,1.176-1.357,2.038-1.698
+                                                c-0.566-1.104-0.674-1.464-1.868-1.784c-0.033-2.104,1.163-9.234,2.717-8.407c-0.049-0.578-0.062-0.699,0.509-0.765
+                                                c-0.087-1.145-0.637-0.797,0.595-1.104c-0.979-4.102,1.847-2.083,3.651-1.104c0-0.341,0-0.68,0-1.02
+                                                c0.534,0.116,1.853,0.641,2.177,0.085c0.109-0.188-0.92-0.513-1.073-0.594c1.126-0.569,0.975-1.844,0.17-3.143
+                                                c1.503,0.075,3.008,0.738,3.482-0.594c0.613,0.591,1.188,0.584,1.697,1.358c0.284-0.481,0.566-0.963,0.85-1.443
+                                                c0.53,0.646,1.549,2.504,2.59,1.983c0.223-0.111,1.486,0.661,1.486,0.394c0-1.159,0.588-2.121,1.529-2.717
+                                                C35.584,34.716,35.005,38.027,36.791,43.727"/>
+                            </g>
+                        </g>
+                    </g>
+                </svg>
+            </a>
+        </td>
+    </tr>
+</table>
+<!-- Email Header : END -->
+
+<!-- Email Body : BEGIN -->
+<table role="presentation" aria-hidden="true" cellspacing="0" cellpadding="0" border="0" align="center" width="600" style="margin: auto;" class="email-container">
+
+    [CONTENT]
+
+</table>
+<!-- Email Body : END -->
+
+<!-- Email Footer : BEGIN -->
+<table role="presentation" aria-hidden="true" cellspacing="0" cellpadding="0" border="0" align="center" width="600" style="margin: auto;" class="email-container">
+    <tr>
+        <td style="padding: 0px;width: 100%;" class="x-gmail-data-detectors">
+            <div class="bottom-strip" style="background-color: #39468A;"></div>
+            <div class="bottom-strip" style="background-color: #E74F23;"></div>
+            <div class="bottom-strip" style="background-color: #923288;"></div>
+            <div class="bottom-strip" style="background-color: #1C9DB2;"></div>
+            <div class="bottom-strip" style="background-color: #E10759;"></div>
+        </td>
+    </tr>
+</table>
+<table role="presentation" aria-hidden="true" cellspacing="0" cellpadding="0" border="0" align="center" width="600" style="margin: auto;" class="email-container">
+    <tr>
+        <td style="padding: 10px;width: 50%;font-size: 12px; font-family: sans-serif; line-height:18px; text-align: center; color: #888888; cursor:pointer;" class="x-gmail-data-detectors">
+            <a class="square-logo-layout" href="https://twitter.com/Veremes_Info" target="_blank" style="color: #24292E; cursor:pointer;">
+                <!--<i class="fa fa-twitter" style=""></i>-->
+                <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill: currentColor; cursor:pointer;">
+                        <title>Twitter</title>
+                        <path d="M50,0a50,50,0,1,0,50,50A50,50,0,0,0,50,0ZM75.28,37c0,.56,0,1.12,0,1.68C75.32,56,62.2,75.83,38.21,75.83h0a37,37,0,0,1-20-5.86,24.62,24.62,0,0,0,3.11.18,26.13,26.13,0,0,0,16.2-5.58,13,13,0,0,1-12.18-9.06,12.34,12.34,0,0,0,2.45.24,13,13,0,0,0,3.44-.46A13,13,0,0,1,20.77,42.5v-.16A13.11,13.11,0,0,0,26.68,44a13.05,13.05,0,0,1-4-17.42A37,37,0,0,0,49.52,40.18a13.19,13.19,0,0,1-.34-3,13.05,13.05,0,0,1,22.57-8.92A26.11,26.11,0,0,0,80,25.12a13.08,13.08,0,0,1-5.73,7.22,26.23,26.23,0,0,0,7.49-2.06A26.49,26.49,0,0,1,75.28,37Z"/>
+                </svg>
+            </a>
+            <a class="square-logo-layout" href="https://www.linkedin.com/company/veremes/" target="_blank" style="color: #24292E; cursor:pointer;">
+                <!--<i class="fa fa-linkedin" style=""></i>-->
+                <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill: currentColor; cursor:pointer;">
+                        <title>LinkedIn</title>
+                        <path d="M50,0a50,50,0,1,0,50,50A50,50,0,0,0,50,0ZM60.71,51a6.48,6.48,0,0,0-6.33,6.32V79.68H41.74V41.74H54.38v5a13.63,13.63,0,0,1,10.54-5.9A15,15,0,0,1,79.68,55.65v24H67V57.33A6.48,6.48,0,0,0,60.71,51ZM27,34.57A7.59,7.59,0,1,1,34.57,27,7.55,7.55,0,0,1,27,34.57Zm6.32,7.17V79.68H20.66V41.74Z"/>
+                </svg>
+            </a>
+            <a class="square-logo-layout" href="http://vm09.veremes.net/" target="_blank" style="color: #24292E; cursor:pointer;">
+                <!--<i class="fa fa-github" style=""></i>-->
+                <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill: currentColor; cursor:pointer;">
+                    <title>GitLab</title>
+                    <path d="M50,0a50,50,0,1,0,50,50A50,50,0,0,0,50,0ZM75.18,15.1a1,1,0,0,1,2,0l9,27.81h-20Zm-52.34,0a1,1,0,0,1,2,0l9,27.81h-20ZM9.85,61A2.63,2.63,0,0,1,8.9,58l4.35-13.4L47.16,88.07Zm4.33-17h20l14.3,44Zm21.19,0H64.63L50,89Zm30.42,0h20L51.49,88ZM90.15,61,52.84,88.07,86.75,44.62,91.1,58A2.63,2.63,0,0,1,90.15,61Z"/>
+                </svg>
+            </a>
+            <a class="square-logo-layout" href="http://www.veremes.com/" target="_blank" style="color: #24292E; cursor:pointer;">
+                <!--<i class="fa fa-globe" style=""></i>-->
+                <svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill: currentColor; cursor:pointer;">
+                        <defs>
+                                <style>.cls-1{fill:none;}</style>
+                        </defs>
+                        <title>Veremes</title>
+                        <path class="cls-1" d="M60.17,18.09h0S60.15,18.05,60.17,18.09Z"/>
+                        <path class="cls-1" d="M48.39,26.38c.66-6.65,2.7-11.56,6.06-14.6a11.45,11.45,0,0,1,1.82-1.29A40.5,40.5,0,0,0,50,10l-1,0c-3.18,3.87-5.13,9.17-5.79,15.85l-.15,1.47c-.21,2.06-.42,4.16-.47,6.28-1.35-5.7-.83-9.69-1.1-15.87A4,4,0,0,0,39.6,21.2c0,.34-1.6-.64-1.88-.5-1.33.67-2.62-1.69-3.29-2.51L33.35,20c-.65-1-1.38-1-2.16-1.73-.6,1.69-2.51.85-4.42.76,1,1.65,1.21,3.26-.21,4,.19.1,1.5.51,1.36.75-.41.71-2.09,0-2.77-.11V25c-2.29-1.25-5.88-3.81-4.63,1.4-1.57.39-.87-.05-.76,1.4-.72.09-.71.24-.64,1-2-1.05-3.5,8-3.45,10.68,1.51.4,1.65.86,2.37,2.26-1.1.43-1.75,1.61-2.59,2.16l1.08.64a6,6,0,0,0-2.37,2c.34-.51,1.05.65.86.54l-.65-.22c.22.65.43,1.3.65,2-1.21.55-.92.92-1.83,2.15.39,0,.78.09,1.18.11-.6,0-.84,3.06-.65,3.67.37-.72,1-1.49,1.3-2.27l.75.76-1.18,1c2.9.86-.4,2.82,1,5.06.42-1.25,1-1.43,1-2.91l.65.54c-.28.48-2.29,4.21-.44,4.21.18,0,.2,6.2.49,7.79a4,4,0,0,0,.89-1.38c0,.95.5,1.3.24,2.51,2.75-.82,1.82.76.57,2.26a20.92,20.92,0,0,0,2.91-.89c1.26-.41.23,1.86.64,1.86s2-2.93,2.27-3.39v1c.72-.35,2.94-3.32,3.23-3.32a3.11,3.11,0,0,1,.41,1.86,46.51,46.51,0,0,0,6.47-10.83,1.46,1.46,0,0,0,.65.4c-.31,0-6.56,12.58-6.64,13.18l1.46-.32c-.63.9-.68,2.15-1,3,2.51-.35,1.5,2,1.37,4.13,2.12-1.33,5.14-2.15,4.05,1.45a15.73,15.73,0,0,1,2.18-1c-1.76.58.82,4.33,1.11,5.17.37,1.13,3.66.26,4.87.73,1.16-1.87,1.6.33,1.86,2.11s2.24-1,3.12-.73c.67.24-.4,4.46,2,2.53,1-.79,1.32.68,2.76-.75,0,0,4.29.64,4.23.62.77-4.21,3.94-.21,3.61-3.88l1,0c-.16-3.3,3.24,1.5,3.24-3.18,0-1.11-2.52-2.52.59-1.4-.29-1.5.37-1.84-1.24-2.16a.62.62,0,0,1,.16-.81c1.49,0,4,2.79,5,1.46.25-.35-1.33-3.28-1.4-4,.82.2,1.77-.12,2.53.06-1.45-.8-.52-1.07-2.32-1.46,1.45-2.84,4.12-.15,5.45-2.32C70.78,71.9,69.3,66,71,65.52c-1.38-1.3-2.57-1.61-3.72-3.13-2.9-3.83,2.66.65,3.78,1.51-.06-.71.28-1.42.27-2.1L72.76,63c0-.34.11-.69.16-1,1.4,1,3,1.83,4.69,1.35-.35-.76-.08-1-.27-1.83,1.22.4,2.12-.06,3.61.11-1-2.93,2.5-2.84,4.67-3.51,3.68-1.15-2.29-1.68-2.51-1.88-.65-.6.8-1.53,1-1.35.44.35-1.23-1.87-1-1.24-.52-1.56-4.19-.51-.92-2.7-1.44-.32-3.4-.65-3.45-2.69,1.28,0,2.36-.73,3.56-.87-.89-.64-1.43-1.76-2.37-2.37l.75-.32c-4.51-.74.49-4.35,1.62-6.47-3,.68-3.19-1.72-5.93-2.16l1.29-1.18a20.84,20.84,0,0,1-4.52-.54c.19-1.83,1.55-2.87,3.12-3.56-5.07-2.49-3.84-6.3-9.06-7.66L68.28,22c-1.38-2.21-2.62-.72-4.15-1.13-3.39-.93-3.07,3.75-3.07-1.78,0,.62-.81-.72-.89-1-1.22.8-5.47,4.21-6.34,3.49-1.27-1.06-1.35-.72-2.26.59-.4.58-2,1.36-1.73.87-.9,1.41-1,7.1-2.05,10.79,0-2,.25-4,.45-6Z"/>
+                        <path d="M99.94,47.71l0-.64c0-.61-.08-1.23-.14-1.84,0-.16,0-.31,0-.46-.08-.74-.17-1.47-.28-2.2,0-.19-.06-.38-.1-.57q-.13-.86-.3-1.68l-.12-.64c-.15-.7-.31-1.39-.48-2.08,0-.15-.09-.3-.13-.45-.14-.56-.3-1.11-.46-1.65-.08-.24-.15-.49-.23-.73-.16-.51-.34-1-.52-1.54-.06-.17-.12-.35-.19-.53-.23-.62-.47-1.24-.73-1.85-.11-.27-.22-.53-.34-.8s-.35-.78-.53-1.17l-.38-.81c-.27-.56-.56-1.11-.85-1.66-.16-.3-.33-.59-.49-.88s-.35-.61-.53-.92-.37-.63-.57-.94L92,22.86q-.55-.86-1.14-1.68l-.45-.62c-.25-.35-.51-.69-.77-1-.13-.18-.27-.35-.41-.52q-1.36-1.74-2.9-3.35L86,15.35q-1.66-1.72-3.48-3.29L82.46,12a51.79,51.79,0,0,0-5.4-4h0a49.56,49.56,0,0,0-4.42-2.54h0A49.59,49.59,0,0,0,63.94,2h0c-1.56-.45-3.16-.83-4.78-1.13L58.49.73,57.21.52C56.59.43,56,.35,55.33.29L54.54.21,53,.1l-.73,0C51.51,0,50.76,0,50,0a50,50,0,1,0,50,50C100,49.23,100,48.47,99.94,47.71ZM49.84,23c-.31.49,1.33-.29,1.73-.87.91-1.31,1-1.65,2.26-.59.87.72,5.12-2.69,6.34-3.49,0,0,0-.06,0,0h0c.08.24.89,1.58.89,1,0,5.53-.32.85,3.07,1.78,1.53.41,2.77-1.08,4.15,1.13L67.2,23.14c5.22,1.36,4,5.17,9.06,7.66-1.57.69-2.93,1.73-3.12,3.56a20.84,20.84,0,0,0,4.52.54l-1.29,1.18c2.74.44,2.92,2.84,5.93,2.16-1.13,2.12-6.13,5.73-1.62,6.47l-.75.32c.94.61,1.48,1.73,2.37,2.37-1.2.14-2.28.86-3.56.87.05,2,2,2.37,3.45,2.69-3.27,2.19.4,1.14.92,2.7-.21-.63,1.46,1.59,1,1.24-.22-.18-1.67.75-1,1.35.22.2,6.19.73,2.51,1.88-2.17.67-5.64.58-4.67,3.51-1.49-.17-2.39.29-3.61-.11.19.87-.08,1.07.27,1.83-1.7.48-3.29-.34-4.69-1.35,0,.34-.11.69-.16,1l-1.4-1.24c0,.68-.33,1.39-.27,2.1C70,63,64.41,58.56,67.31,62.39c1.15,1.52,2.34,1.83,3.72,3.13-1.73.46-.25,6.38,2.43,5.87-1.33,2.17-4-.52-5.45,2.32,1.8.39.87.66,2.32,1.46-.76-.18-1.71.14-2.53-.06.07.77,1.65,3.7,1.4,4-1,1.33-3.53-1.46-5-1.46a.62.62,0,0,0-.16.81c1.61.32,1,.66,1.24,2.16-3.11-1.12-.59.29-.59,1.4,0,4.68-3.4-.12-3.24,3.18l-1,0c.33,3.67-2.84-.33-3.61,3.88.06,0-4.19-.67-4.23-.62-1.44,1.43-1.78,0-2.76.75-2.37,1.93-1.3-2.29-2-2.53-.88-.32-2.86,2.52-3.12.73s-.7-4-1.86-2.11c-1.21-.47-4.5.4-4.87-.73-.29-.84-2.87-4.59-1.11-5.17a15.73,15.73,0,0,0-2.18,1c1.09-3.6-1.93-2.78-4.05-1.45.13-2.15,1.14-4.48-1.37-4.13.37-.84.42-2.09,1-3l-1.46.32c.08-.6,6.33-13.18,6.64-13.18a1.46,1.46,0,0,1-.65-.4,46.51,46.51,0,0,1-6.47,10.83A3.11,3.11,0,0,0,28,67.51c-.29,0-2.51,3-3.23,3.32v-1c-.3.46-1.83,3.39-2.27,3.39s.62-2.27-.64-1.86a20.92,20.92,0,0,1-2.91.89c1.25-1.5,2.18-3.08-.57-2.26.26-1.21-.24-1.56-.24-2.51a4,4,0,0,1-.89,1.38c-.29-1.59-.31-7.79-.49-7.79-1.85,0,.16-3.73.44-4.21l-.65-.54c.06,1.48-.55,1.66-1,2.91-1.37-2.24,1.93-4.2-1-5.06l1.18-1L15,52.47c-.34.78-.93,1.55-1.3,2.27-.19-.61,0-3.67.65-3.67-.4,0-.79-.06-1.18-.11.91-1.23.62-1.6,1.83-2.15-.22-.65-.43-1.3-.65-2l.65.22c.19.11-.52-1-.86-.54a6,6,0,0,1,2.37-2l-1.08-.64c.84-.55,1.49-1.73,2.59-2.16-.72-1.4-.86-1.86-2.37-2.26-.05-2.68,1.47-11.73,3.45-10.68-.07-.73-.08-.88.64-1-.11-1.45-.81-1,.76-1.4-1.25-5.21,2.34-2.65,4.63-1.4v-1.3c.68.15,2.36.82,2.77.11.14-.24-1.17-.65-1.36-.75,1.42-.73,1.23-2.34.21-4,1.91.09,3.82.93,4.42-.76C32,19,32.7,19,33.35,20l1.08-1.83c.67.82,2,3.18,3.29,2.51.28-.14,1.88.84,1.88.5a4,4,0,0,1,1.94-3.45c.27,6.18-.25,10.17,1.1,15.87,0-2.12.26-4.22.47-6.28l.15-1.47c.66-6.68,2.61-12,5.79-15.85l1,0a40.5,40.5,0,0,1,6.27.49,11.45,11.45,0,0,0-1.82,1.29c-3.36,3-5.4,8-6.06,14.6l-.15,1.49c-.2,2-.41,4-.45,6C48.82,30.14,48.94,24.45,49.84,23Z"/>
+                </svg>
+            </a>
+        </td>
+        <td style="padding: 10px;width: 50%;font-size: 20px; font-family: sans-serif; line-height:18px; text-align: center; color: #000000;" class="x-gmail-data-detectors">
+            <div style="margin-bottom:10px;">Pour toute question :</div>
+            <div>support@veremes.com</div>
+        </td>
+    </tr>
+</table>
+<!-- Email Footer : END -->
+
+</center>
+[SCRIPT]
+</body>
+</html>';
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Accounts.class.sql.inc b/vas/rest/ws/vitis/Accounts.class.sql.inc
new file mode 100755
index 00000000..69f2806c
--- /dev/null
+++ b/vas/rest/ws/vitis/Accounts.class.sql.inc
@@ -0,0 +1,9 @@
+<?php
+
+$aSql["UserExists"] = "SELECT \"user\".login FROM [SCHEMA].\"user\" WHERE \"user\".login=[USERNAME];";
+$aSql["checkUser"] = "SELECT * FROM [SCHEMA].\"user\" WHERE \"user\".login=[USERNAME] AND \"user\".email=[MAIL];";
+$aSql["setPrivilege"] = "GRANT [ROLE] TO [USERNAME];";
+$aSql["getUserToUnsubscribe"] = "SELECT login, role FROM [SCHEMA].v_user WHERE v_user.user_id = [USER_ID];";
+$aSql["disableAccount"] = "REVOKE vitis_user FROM [LOGIN]";
+$aSql["emptyAccount"] = "UPDATE [SCHEMA].\"user\" SET email = '', company = '', name = '' WHERE login = [LOGIN2]";
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Action.class.inc b/vas/rest/ws/vitis/Action.class.inc
new file mode 100755
index 00000000..480aea50
--- /dev/null
+++ b/vas/rest/ws/vitis/Action.class.inc
@@ -0,0 +1,35 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Action.class.inc
+ * \class Action
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Action php class
+ *
+ * This class defines operation for one Action
+ * 
+ */
+class Action extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aAction) {
+        $this->aFields = $aAction;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Actions.class.inc b/vas/rest/ws/vitis/Actions.class.inc
new file mode 100755
index 00000000..97faef7d
--- /dev/null
+++ b/vas/rest/ws/vitis/Actions.class.inc
@@ -0,0 +1,62 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Actions.class.inc
+ * \class Actions
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Actions php class
+ *
+ * This class defines operation for one Column
+ * 
+ */
+class Actions extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("table_name", "index", "application_name", "module_name");
+    }
+
+    /**
+     * get informations about table columns
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        require_once "Action.class.inc";
+        $aFields = null;
+        // 
+        if (empty($this->aValues['language']))
+            $this->aValues['language'] = 'en';
+        //
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['sRessource'] = array('value' => $this->aValues['ressource_id'], 'type' => 'string');
+        $aParams['language'] = array('value' => $this->aProperties['language'], 'type' => 'string');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getTableActions'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            while ($aAction = $this->oConnection->oBd->ligneSuivante($oPDOresult))
+                array_push($this->aObjects, new Action($aAction));
+        }
+        return $aFields;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/ActiveDirectory.class.inc b/vas/rest/ws/vitis/ActiveDirectory.class.inc
new file mode 100755
index 00000000..6cf9ac22
--- /dev/null
+++ b/vas/rest/ws/vitis/ActiveDirectory.class.inc
@@ -0,0 +1,744 @@
+<?php
+
+/**
+ * \file ActiveDirectory.class.inc
+ * \class ActiveDirectory
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the ActiveDirectory php class
+ *
+ * This class defines Rest Api to Gtf workspaces
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Domain.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+require_once(__DIR__ . '/../../class/treeview/Tree.php');
+require_once(__DIR__ . '/../../class/treeview/LdapTree.php');
+require_once(__DIR__ . '/../../class/Ldap.class.inc');
+require_once 'User.class.inc';
+
+class ActiveDirectory extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/activedirectory",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/activedirectory")
+     *   }
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array('workspace_id', 'name');
+    }
+
+    /**
+     * @SWG\Get(path="/ActiveDirectory/Test",
+     *   tags={"Domains"},
+     *   summary="Test connection to active directory",
+     *   description="Request to test connection to active directory",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="query",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Encrypted password of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="object",
+     *     in="query",
+     *     type="string",
+     *         @SWG\Items(type="string"),
+     *         default="person",
+     *         enum={"person", "group"},
+     *     description="object of test",
+     *     required=true,
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/ActiveDirectory/Tree",
+     *   tags={"Domains"},
+     *   summary="Get Active Directory tree of domain",
+     *   description="Request to get active Directory tree of domain by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="query",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Encrypted password of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="object",
+     *     in="query",
+     *     type="string",
+     *         @SWG\Items(type="string"),
+     *         default="person",
+     *         enum={"person", "group"},
+     *     description="object of test",
+     *     required=true,
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/ActiveDirectory/Users",
+     *   tags={"Domains"},
+     *   summary="Search Active Directory users",
+     *   description="Request to search active Directory users",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="query",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Encrypted password of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="search_account",
+     *     in="query",
+     *     description="account to search",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="search_groups",
+     *     in="query",
+     *     description="groups to search",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="search_department",
+     *     in="query",
+     *     description="department to search",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/ActiveDirectory/Users/{branch}",
+     *   tags={"Domains"},
+     *   summary="Get Active Directory users of branch",
+     *   description="Request to get active Directory users of branch by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="branch",
+     *     in="path",
+     *     description="branch of tree",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="query",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Encrypted password of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/ActiveDirectory/Groups",
+     *   tags={"Domains"},
+     *   summary="Search Active Directory groups",
+     *   description="Request to search active Directory groups",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="query",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Encrypted password of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="search_group",
+     *     in="query",
+     *     description="group to search",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/ActiveDirectory/Groups/{branch}",
+     *   tags={"Domains"},
+     *   summary="Get Active Directory groups of branch",
+     *   description="Request to get active Directory groups of branch by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="branch",
+     *     in="path",
+     *     description="branch of tree",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="query",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Encrypted password of user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/ActiveDirectory/UserGroups/{user_id}",
+     *   tags={"Domains"},
+     *   summary="Get groups of Active Directory user",
+     *   description="Request to get the groupd of an active Directory user",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="user_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="mixed_rights_management",
+     *     in="query",
+     *     description="mixed rights management",
+     *     required=true,
+     *     type="boolean",
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/ActiveDirectory")
+     *     )
+     *  )
+     */
+
+    /**
+     * get active directory users
+     * @return active directory users
+     */
+    function GET() {
+        if (isset($this->oConnection->oError) && !empty($this->oConnection->oError)) {
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $this->oConnection->oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        if (!empty($this->aPath[2])) {
+            // Test de connexion au serveur AD ?
+            if ($this->aPath[2] == 'Test') {
+                $aReturn = $this->testDomain();
+                if ($aReturn['sStatus'] == 1) {
+                    $oError = new VitisError(1, $aReturn['sMessage']);
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+            // Arborescence du serveur AD ?
+            else if ($this->aPath[2] == 'Tree') {
+                $aReturn = $this->getDomainADTree();
+                if ($aReturn['sStatus'] == 1) {
+                    $oError = new VitisError(1, $aReturn['sMessage']);
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+            // Utilisateurs d'une branche ou recherche sur tout l'arbre ?
+            else if ($this->aPath[2] == 'Users') {
+                if (!empty($this->aPath[3])) {
+                    $this->aValues['branch'] = $this->aPath[3];
+                    $aReturn = $this->getADTreeUsers();
+                } else
+                    $aReturn = $this->searchADTreeUsers();
+                if ($aReturn['sStatus'] == 1) {
+                    $oError = new VitisError(1, $aReturn['sMessage']);
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+            // Groupes d'une branche ou recherche sur tout l'arbre ?
+            else if ($this->aPath[2] == 'Groups') {
+                if (!empty($this->aPath[3])) {
+                    $this->aValues['branch'] = $this->aPath[3];
+                    $aReturn = $this->getADTreeGroups();
+                } else
+                    $aReturn = $this->searchADTreeGroups();
+                if ($aReturn['sStatus'] == 1) {
+                    $oError = new VitisError(1, $aReturn['sMessage']);
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+            // Groupes d'un utilisateur ?
+            else if ($this->aPath[2] == 'UserGroups') {
+                $aReturn = $this->getADUserGroups();
+                if ($aReturn['sStatus'] == 1) {
+                    $oError = new VitisError(1, $aReturn['sMessage']);
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+
+    /**
+     * Test domain
+     */
+    Public function testDomain() {
+        $bIsError = false;
+        $aValues = $this->aValues;
+        if (empty($this->aValues['domain_id'])) {
+            require $this->sRessourcesFile;
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['domain'] = array('value' => $this->aValues['domain'], 'type' => 'string');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getAdId'], $aParams);
+            if ($this->oConnection->oBd->enErreur()) {
+                $aReturn = array('sStatus' => 1, 'sMessage' => $this->oConnection->oBd->getBDMessage());
+                $bIsError = true;
+            } else {
+                $oResult = $this->oConnection->oBd->objetSuivant($oPDOresult);
+                $aValues['my_vitis_id'] = $oResult->domain_id;
+            }
+        } else {
+            $aValues['my_vitis_id'] = $this->aValues['domain_id'];
+        }
+
+        if ($bIsError == false) {
+
+            // Infos du domaine
+            $oDomain = new Domain($this->aPath, $aValues, $this->aProperties, $this->oConnection);
+            $oDomain->GET();
+            $this->aValues = array_merge($oDomain->aFields, $this->aValues);
+            $this->aValues['my_vitis_id'] = $oDomain->aFields['domain_id'];
+            //
+            $aResult = array();
+            // Informations de l'AD stocké dans un tableau
+            $sLoginLdap = $this->aValues['login'] . '@' . $this->aValues['domain'];
+
+            $aLdap = array('sIdLdap' => $this->aValues['my_vitis_id'], 'sType' => $this->aValues['type'], 'sLdapName' => $this->aValues['domain'], 'sLoginLdap' => $sLoginLdap, 'sPwdLdap' => $this->aValues['password'], 'sServer' => $this->aValues['server'], 'sPort' => $this->aValues['port']);
+
+            $aLdap['sObject'] = $this->aValues['object'];
+
+            // Utilisateur ou groupe ?
+            if ($this->aValues['object'] == "person")
+                $aLdap['sDnResearch'] = $this->aValues['dn_search_user'];
+            else
+                $aLdap['sDnResearch'] = $this->aValues['dn_search_group'];
+            // Connexion au serveur AD.
+            $oLdap = new Ldap(serialize($aLdap));
+            $sLdapConn = $oLdap->connectLdap();
+            $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            if (ldap_error($sLdapConn) == "Success") {
+                if (empty($this->aObjects)) {
+                    $this->aObjects = array();
+                    $this->aObjects[0] = new stdClass();
+                }
+                $this->aObjects[0]->aFields = $aLdap;
+                $aReturn['oLdap'] = $oLdap;
+            } else {
+                if (ldap_error($sLdapConn) == "Invalid credentials")
+                    $sError = 'ERROR_INVALID_CREDENTIALS_ACTIVE_DIRECTORY_USERS_USER';
+                else if (ldap_error($sLdapConn) == "Can't contact LDAP server")
+                    $sError = 'ERROR_CONTACT_DOMAIN_ACTIVE_DIRECTORY_USERS_USER';
+                else
+                    $sError = ldap_error($sLdapConn);
+                $aReturn = array('sStatus' => 1, 'sMessage' => $sError);
+            }
+        }
+        return $aReturn;
+    }
+
+    /**
+     * getDomainADTree
+     */
+    Public function getDomainADTree() {
+        $aReturn = $this->testDomain();
+        if ($aReturn['sStatus'] == 1)
+            return $aReturn;
+        else {
+            $oLdap = $aReturn['oLdap'];
+            // Important!
+            if ($oLdap->aLdap['sDnResearch'] == '')
+                $oLdap->aLdap['sDnResearch'] = 'null';
+            $oLdapTree = new LdapTree($oLdap);
+            $branch = null;
+            $aTree = $oLdapTree->json($branch, true);
+            $this->aObjects[0]->aFields = array('tree' => $aTree);
+            $aReturn = array('sStatus' => 0, 'sMessage' => '');
+        }
+        return $aReturn;
+    }
+
+    /**
+     * getADTreeUsers
+     */
+    Public function getADTreeUsers() {
+        $this->aValues['object'] = 'person';
+        $aReturn = $this->testDomain();
+        if ($aReturn['sStatus'] == 1)
+            return $aReturn;
+        else {
+            $oLdap = $aReturn['oLdap'];
+            $sLdapConn = $oLdap->connectLdap();
+            $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            if (ldap_error($sLdapConn) == "Success") {
+                $aUserList = $oLdap->getUsers($sLdapConn, $this->aValues['branch']);
+                $this->aObjects[0]->aFields = array('users' => $aUserList);
+                $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            } else
+                $aReturn = array('sStatus' => 1, 'sMessage' => ldap_error($sLdapConn));
+        }
+        return $aReturn;
+    }
+
+    /**
+     * getADTreeUsers
+     */
+    Public function searchADTreeUsers() {
+        $this->aValues['object'] = 'person';
+        $aReturn = $this->testDomain();
+        if ($aReturn['sStatus'] == 1)
+            return $aReturn;
+        else {
+            $aUserListdouble = array();
+            $oLdap = $aReturn['oLdap'];
+            $sDn = $oLdap->getDcLdap();
+            $sLdapConn = $oLdap->connectLdap();
+            $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            if (ldap_error($sLdapConn) == "Success") {
+                $sFilter = "(&(objectclass=person)";
+                if (!empty($_REQUEST["search_account"]) && $_REQUEST["search_account"] != "") {
+                    $sFilter .= "(" . $oLdap->userprincipalname . "=" . $_REQUEST["search_account"] . "*)";
+                }
+                if (!empty($_REQUEST["search_department"])) {
+                    $sFilter .= "(department=" . $_REQUEST["search_department"] . "*)";
+                }
+
+                if (!empty($_REQUEST["search_groups"])) {
+                    $sFilter .= "(|";
+                    $aGroup = explode(',', str_replace(", ", ",", $_REQUEST["search_groups"]));
+
+                    foreach ($aGroup as $sGroup) {
+                        $aUserListdouble = array_merge($aUserListdouble, $oLdap->get_members($sLdapConn, $sDn, $sGroup, $_REQUEST["search_account"], $_REQUEST["search_department"]));
+                        $sPrimaryGroup = $oLdap->getGroupInfo($sLdapConn, $sDn, $sGroup);
+                        $sFilter .= "(primaryGroupID=" . $sPrimaryGroup . ")";
+                    }
+                    $sFilter .= ")";
+                }
+                $sFilter .= ")";
+                $aUserListdouble = array_merge($aUserListdouble, $oLdap->getCriteria($sLdapConn, $sDn, $sFilter, $oLdap->aLdap["sObject"]));
+                $known_users = array();
+                $aUserList = array();
+                foreach ($aUserListdouble as $user) {
+                    if (!in_array($user["userprincipalname"], $known_users)) {
+                        $aUserList[] = $user;
+                        $known_users[] = $user["userprincipalname"];
+                    }
+                }
+                $this->aObjects[0]->aFields = array('users' => $aUserList);
+            } else
+                $aReturn = array('sStatus' => 1, 'sMessage' => ldap_error($sLdapConn));
+        }
+        return $aReturn;
+    }
+
+    /**
+     * getADTreeGroups
+     */
+    Public function getADTreeGroups() {
+        $this->aValues['object'] = 'group';
+        $aReturn = $this->testDomain();
+        if ($aReturn['sStatus'] == 1)
+            return $aReturn;
+        else {
+            $oLdap = $aReturn['oLdap'];
+            $sLdapConn = $oLdap->connectLdap();
+            $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            if (ldap_error($sLdapConn) == "Success") {
+                $aGroupList = $oLdap->getGroups($sLdapConn, $this->aValues['branch']);
+                $this->aObjects[0]->aFields = array('groups' => $aGroupList);
+                $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            } else
+                $aReturn = array('sStatus' => 1, 'sMessage' => ldap_error($sLdapConn));
+        }
+        return $aReturn;
+    }
+
+    /**
+     * getADTreeGroups
+     */
+    Public function searchADTreeGroups() {
+        $this->aValues['object'] = 'group';
+        $aReturn = $this->testDomain();
+        if ($aReturn['sStatus'] == 1)
+            return $aReturn;
+        else {
+            $aGroupListdouble = array();
+            $oLdap = $aReturn['oLdap'];
+            $sDn = $oLdap->getDcLdap();
+            $sLdapConn = $oLdap->connectLdap();
+            $aReturn = array('sStatus' => 0, 'sMessage' => '');
+            if (ldap_error($sLdapConn) == "Success") {
+                $sFilter = "(&(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)(objectclass=group))(!(objectClass=person))";
+                if (!empty($_REQUEST["search_group"]) && $this->aValues['search_group'] != "") {
+                    $sFilter .= "(cn=" . $this->aValues['search_group'] . "*)"; // $sFilter .="(cn=".$_REQUEST["name_ad"]."*)";
+                }
+                $sFilter .= ")";
+                $aGroupList = $oLdap->getCriteria($sLdapConn, $sDn, $sFilter, $oLdap->aLdap["sObject"]);
+                $this->aObjects[0]->aFields = array('groups' => $aGroupList);
+            } else
+                $aReturn = array('sStatus' => 1, 'sMessage' => ldap_error($sLdapConn));
+        }
+        return $aReturn;
+    }
+
+    /**
+     * getADUserGroups
+     */
+    Public function getADUserGroups() {
+        require $this->sRessourcesFile;
+        $aReturn = array('sStatus' => 0, 'sMessage' => '');
+        $aUserGroup = Array();
+        // Login de l'utilisateur.
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['iUserId'] = array('value' => $this->aPath[3], 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getUserLogin'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $aReturn = array('sStatus' => 1, 'sMessage' => $this->oConnection->oBd->getBDMessage());
+        } else {
+            // Groupes du domaine dont l'utilisateur est membre.
+            $oResult = $this->oConnection->oBd->objetSuivant($oPDOresult);
+            $aGroupListId = getUserGroups2($oResult->login, $this->oConnection->oBd, $this->aProperties["mixed_rights_management"], $this->aProperties["schema_framework"]);
+            // Liste des groupes de l'utilisateur.
+            $aParams = array();
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['iUserId'] = array('value' => $this->aPath[3], 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getUserGroups'], $aParams);
+            if ($this->oConnection->oBd->enErreur()) {
+                $aReturn = array('sStatus' => 1, 'sMessage' => $this->oConnection->oBd->getBDMessage());
+            } else {
+                $sGroup = "";
+                $sIdGroup = "";
+                while ($oGroup = $this->oConnection->oBd->objetSuivant($oPDOresult)) {
+                    $aUserGroup[$oGroup->group_id] = $oGroup->name;
+                    if ($sGroup == "") {
+                        $sGroup = $oGroup->name;
+                    } else {
+                        $sGroup .= ", " . $oGroup->name;
+                    }
+                    if ($sIdGroup == "") {
+                        $sIdGroup = $oGroup->group_id;
+                    } else {
+                        $sIdGroup .= "@@" . $oGroup->group_id;
+                    }
+                }
+                if ($aGroupListId['ad'] != "") {
+                    if ($sGroup == "") {
+                        $sGroup = $aGroupListId['ad'];
+                    } else {
+                        $sGroup .= ", " . $aGroupListId['ad'];
+                    }
+                }
+                $this->aObjects[0]->aFields = array('allGroups' => $sGroup, 'adGroups' => $aGroupListId['ad']);
+            }
+        }
+        return $aReturn;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/BillingGroup.class.inc b/vas/rest/ws/vitis/BillingGroup.class.inc
new file mode 100755
index 00000000..cb9c5b3e
--- /dev/null
+++ b/vas/rest/ws/vitis/BillingGroup.class.inc
@@ -0,0 +1,120 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file BillingBillingGroup.class.inc
+ * \class BillingGroup
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the BillingGroup php class
+ *
+ * This class defines operation for one BillingGroup
+ * 
+ */
+class BillingGroup extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("billinggroup_id", "billinggroup", "description");
+    }
+
+    /**
+     * @SWG\Get(path="/billinggroups/{billinggroup_id}", 
+     *   tags={"BillingGroups"},
+     *   summary="Get BillingGroup",
+     *   description="Request to get BillingGroup by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="billinggroup_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *   format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/billinggroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "v_billinggroup", "billinggroup_id");
+        //$this->getUsers();
+    }
+
+    /**
+     *  get users of billinggroup
+     */
+    /*
+    function getUsers() {
+        require $this->sRessourcesFile;
+        if (in_array("users", $this->aSelectedFields)) {
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['billinggroup_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGroupUsers'], $aParams);
+            $sListUserId = "";
+            $aListUserLogin = array();
+            while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                if ($sListUserId == "") {
+                    $sListUserId = $aLigne["user_id"];
+                } else {
+                    $sListUserId .= "|" . $aLigne["user_id"];
+                }
+                $aListUserLogin[] = $aLigne["login"];
+            }
+            $oPDOresult = $this->oConnection->oBd->fermeResultat();
+            $this->aFields['users'] = $sListUserId;
+            $this->aFields['users_label'] = implode(',', $aListUserLogin);
+        }
+    }
+    */
+    /**
+     * delete an user
+     */
+    function DELETE() {
+        $this->oConnection->oBd->delete($this->aProperties['schema_framework'], 'v_billinggroup', 'billinggroup_id', $this->aValues['my_vitis_id'], 'integer');
+        if ($this->oConnection->oBd->enErreur()) {
+            $this->oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+        } else {
+            $this->aFields['billinggroup_id'] = $this->aValues['my_vitis_id'];
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/BillingGroups.class.inc b/vas/rest/ws/vitis/BillingGroups.class.inc
new file mode 100755
index 00000000..dffff1e6
--- /dev/null
+++ b/vas/rest/ws/vitis/BillingGroups.class.inc
@@ -0,0 +1,293 @@
+<?php
+
+/**
+ * \file BillingGroups.class.inc
+ * \class BillingGroups
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis BillingGroups
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'BillingGroup.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class BillingGroups extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/billinggroups",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/billinggroups")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="BillingGroups",
+     *   description="Operations about BillingGroups"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("billinggroup_id", "billinggroup", "description");
+    }
+
+    /**
+     * @SWG\Get(path="/billinggroups",
+     *   tags={"BillingGroups"},
+     *   summary="Get BillingGroups",
+     *   description="Request to get BillingGroups",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/billinggroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * get BillingGroups
+     * @return  BillingGroups
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_billinggroup", "billinggroup_id");
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * @SWG\Post(path="/billinggroups",
+     *   tags={"BillingGroups"},
+     *   summary="Add BillingGroup",
+     *   description="Request to add billinggroup",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="name",
+     *     in="formData",
+     *     description="Name of the billinggroup",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="users",
+     *     in="formData",
+     *     description="Users of the billinggroup",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/billinggroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * insert billinggroup
+     * @return id of the billinggroup created
+     */
+    function POST() {
+        $aReturn = $this->genericPost($this->aProperties['schema_framework'], 'v_billinggroup', $this->aProperties['schema_framework'] . '.seq_common', 'billinggroup_id');
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * @SWG\Put(path="/billinggroups/{billinggroup_id}",
+     *   tags={"BillingGroups"},
+     *   summary="Update BillingGroup",
+     *   description="Request to update BillingGroup",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="billinggroup_id",
+     *     in="path",
+     *     description="id of the billinggroup",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="name",
+     *     in="query",
+     *     description="Name of the billinggroup",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="users",
+     *     in="query",
+     *     description="Users of the billinggroup",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/billinggroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * update billinggroup
+     * @return id of the billinggroup if ok error object if ko
+     */
+    function PUT() {
+        $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'v_billinggroup', 'billinggroup_id');
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * @SWG\Delete(path="/billinggroups/",
+     *   tags={"BillingGroups"},
+     *   summary="delete BillingGroup",
+     *   description="Request to delete BillingGroup",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="idList",
+     *     in="query",
+     *     description="id of the billinggroups",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/billinggroups")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Delete(path="/billinggroups/{billinggroup_id}",
+     *   tags={"BillingGroups"},
+     *   summary="delete BillingGroup",
+     *   description="Request to delete BillingGroup",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="billinggroup_id",
+     *     in="path",
+     *     description="id of the billinggroup",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/billinggroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * delete billinggroup
+     * @return id of billinggroup deleted or error object if a billinggroup is not deleted
+     */
+    function DELETE() {
+        $aReturn = $this->genericDelete($this->aProperties['schema_framework'], 'v_billinggroup', 'billinggroup_id');
+        return $aReturn['sMessage'];
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Column.class.inc b/vas/rest/ws/vitis/Column.class.inc
new file mode 100755
index 00000000..5fa5536b
--- /dev/null
+++ b/vas/rest/ws/vitis/Column.class.inc
@@ -0,0 +1,35 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Column.class.inc
+ * \class Column
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Column php class
+ *
+ * This class defines operation for one Column
+ * 
+ */
+class Column extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aColumn) {
+        $this->aFields = $aColumn;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Columns.class.inc b/vas/rest/ws/vitis/Columns.class.inc
new file mode 100755
index 00000000..332abe1c
--- /dev/null
+++ b/vas/rest/ws/vitis/Columns.class.inc
@@ -0,0 +1,59 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Columns.class.inc
+ * \class Columns
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Columns php class
+ *
+ * This class defines operation for one Column
+ * 
+ */
+class Columns extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("table_name", "index", "application_name", "module_name");
+    }
+
+    /**
+     * get informations about table columns
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        require_once "Column.class.inc";
+        $aFields = null;
+        //
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['sRessource'] = array('value' => $this->aValues['ressource_id'], 'type' => 'string');
+        $aParams['language'] = array('value' => $this->aProperties['language'], 'type' => 'string');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getTableColumns'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            while ($aColumn = $this->oConnection->oBd->ligneSuivante($oPDOresult))
+                array_push($this->aObjects, new Column($aColumn));
+        }
+        return $aFields;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Database.class.inc b/vas/rest/ws/vitis/Database.class.inc
new file mode 100755
index 00000000..7c2c8ddc
--- /dev/null
+++ b/vas/rest/ws/vitis/Database.class.inc
@@ -0,0 +1,34 @@
+<?php
+
+require_once 'Vitis.class.inc';
+
+/**
+ * \file Action.class.inc
+ * \class Action
+ *
+ * \author Benoit Picavet
+ *
+ * 	\brief This file contains the Action php class
+ *
+ * This class defines operation for one Action
+ * 
+ */
+class Database extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aDatabase) {
+        $this->aFields = $aDatabase;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Domain.class.inc b/vas/rest/ws/vitis/Domain.class.inc
new file mode 100755
index 00000000..91cc0e3b
--- /dev/null
+++ b/vas/rest/ws/vitis/Domain.class.inc
@@ -0,0 +1,93 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Domain.class.inc
+ * \class Domain
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Domain php class
+ *
+ * This class defines operation for one Domain
+ * 
+ */
+class Domain extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("domain_id", "domain", "alias", "server", "port", "dn_search_user", "filter_user", "dn_search_group", "filter_group", "login", "password", "verify_rights", "type");
+    }
+
+    /**
+     * @SWG\Get(path="/domains/{domain_id}", 
+     *   tags={"Domains"},
+     *   summary="Get Domain",
+     *   description="Request to get Domain by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="domain_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *   format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/domains")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "domain", "domain_id");
+    }
+
+    /**
+     * delete a domain
+     */
+    function DELETE() {
+        $this->oConnection->oBd->delete($this->aProperties['schema_framework'], 'domain', 'domain_id', $this->aValues['my_vitis_id'], 'integer');
+        if ($this->oConnection->oBd->enErreur()) {
+            $this->oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+        } else {
+            $this->aFields['domain_id'] = $this->aValues['my_vitis_id'];
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Domains.class.inc b/vas/rest/ws/vitis/Domains.class.inc
new file mode 100755
index 00000000..e7e2b620
--- /dev/null
+++ b/vas/rest/ws/vitis/Domains.class.inc
@@ -0,0 +1,530 @@
+<?php
+
+/**
+ * \file Domains.class.inc
+ * \class Domains
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis Domains
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Domain.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Domains extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/domains",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/domains")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Domains",
+     *   description="Operations about Domains"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("domain_id", "domain", "alias", "server", "port", "dn_search_user", "filter_user", "dn_search_group", "filter_group", "login", "password", "verify_rights", "type");
+    }
+
+    /**
+     * @SWG\Get(path="/domains",
+     *   tags={"Domains"},
+     *   summary="Get Domains",
+     *   description="Request to get Domains",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Domains
+     * @return  Domains
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "domain", "domain_id");
+        $sMessage = $aReturn['sMessage'];
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Post(path="/domains",
+     *   tags={"Domains"},
+     *   summary="Add Domain",
+     *   description="Request to add domain",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="domain",
+     *     in="formData",
+     *     description="domain name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="alias",
+     *     in="formData",
+     *     description="Domain alias",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="server",
+     *     in="formData",
+     *     description="Ad server",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="port",
+     *     in="formData",
+     *     description="Ad server port",
+     *     required=true,
+     *     type="integer",
+     *    format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="dn_search_user",
+     *     in="formData",
+     *     description="Search DN base for users",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="filter_user",
+     *     in="formData",
+     *     description="Filter to search users",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="dn_search_group",
+     *     in="formData",
+     *     description="Search DN base for groups",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="filter_group",
+     *     in="formData",
+     *     description="Filter to search groups",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="login",
+     *     in="formData",
+     *     description="login to connect to ldap",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="formData",
+     *     description="password to connect to ldap",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="type",
+     *     in="formData",
+     *     description="type of ldap server (AD or openldap supported)",
+     *     required=false,
+     *     type="array",
+     *         @SWG\Items(type="string"),
+     *         collectionFormat="multi",
+     *         default="AD",
+     *         enum={"AD", "OpenLdap"}
+     *   ),
+     *  @SWG\Parameter(
+     *     name="verify_rights",
+     *     in="formData",
+     *     description="verify rights",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/domains")
+     *     ),
+     * 
+     *  )
+     */
+
+    /**
+     * insert user
+     * @return id of the user created
+     */
+    function POST() {
+        $aReturn = $this->genericPost($this->aProperties['schema_framework'], 'domain', $this->aProperties['schema_framework'] . '.seq_common', 'domain_id');
+        if ($aReturn['sStatus'] == 1) {
+            $oDomain = new Domain($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+            $oDomain->GET();
+            $error = $this->writeDomainInProperties($oDomain->aFields, "insert");
+            if ($error['sStatus'] == 1) {
+                $sMessage = $aReturn['sMessage'];
+            } else {
+                $oError = new VitisError(1, $error['sMessage']);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        } else {
+            $sMessage = $aReturn['sMessage'];
+        }
+        return $sMessage;
+    }
+
+    /**
+     * 
+     * @param type $aExternalValues
+     * @param type $sAction
+     * @return type
+     */
+    Function writeDomainInProperties($aValues, $sAction) {
+        require $this->sRessourcesFile;
+        $sSql2 = $aSql['listDomain'];
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql2, $aParams);
+        $fPropertiesDomain = fopen('conf/properties_domain.inc', 'w');
+        fputs($fPropertiesDomain, "<?php" . PHP_EOL);
+        fputs($fPropertiesDomain, '$properties[\'domain\'] [""] = "";' . PHP_EOL);
+        while ($oDomain = $this->oConnection->oBd->objetSuivant($oPDOresult)) {
+            fputs($fPropertiesDomain, '$properties[\'domain\'] ["' . $oDomain->alias . '"] = "' . $oDomain->domain . '";' . PHP_EOL);
+        }
+        fputs($fPropertiesDomain, "?>" . PHP_EOL);
+        fclose($fPropertiesDomain);
+        if ($sAction == "insert") {
+            $aParams = array();
+            $aParams['sDomain'] = array('value' => 'vitis_' . $aValues["domain"], 'type' => 'string');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getInfoRolname'], $aParams);
+            if ($this->oConnection->oBd->nombreLigne($oPDOresult) == 0) {
+                $aParams = array();
+                $aParams['sDomain'] = array('value' => 'vitis_' . $aValues["domain"], 'type' => 'double_quote');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['createRolname'], $aParams);
+                if ($this->oConnection->oBd->enErreur()) {
+                    $aReturn = array(sStatus => 0, sMessage => $this->oBd->getBDMessage());
+                    return array(aReturn => $aReturn);
+                }
+            }
+        }
+
+        $aReturn = array('sStatus' => 1, 'sMessage' => "");
+        return $aReturn;
+    }
+
+    /**
+     * @SWG\Put(path="/domains/{domain_id}",
+     *   tags={"Domains"},
+     *   summary="Update Domain",
+     *   description="Request to update domain",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain_id",
+     *     in="path",
+     *     description="domain id",
+     *     required=true,
+     *     type="integer",
+     *   format="int32"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="domain",
+     *     in="query",
+     *     description="domain name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="alias",
+     *     in="query",
+     *     description="Domain alias",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="server",
+     *     in="query",
+     *     description="Ad server",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="port",
+     *     in="query",
+     *     description="Ad server port",
+     *     required=true,
+     *     type="integer",
+     *    format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="dn_search_user",
+     *     in="query",
+     *     description="Search DN base for users",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="filter_user",
+     *     in="query",
+     *     description="Filter to search users",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="dn_search_group",
+     *     in="query",
+     *     description="Search DN base for groups",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="filter_group",
+     *     in="query",
+     *     description="Filter to search groups",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login to connect to ldap",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="password to connect to ldap",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="type",
+     *     in="query",
+     *     description="type of ldap server (AD or openldap supported)",
+     *     required=false,
+     *     type="array",
+     *         @SWG\Items(type="string"),
+     *         collectionFormat="multi",
+     *         default="AD",
+     *         enum={"AD", "OpenLdap"}
+     *   ),
+     *  @SWG\Parameter(
+     *     name="verify_rights",
+     *     in="query",
+     *     description="verify rights",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/domains")
+     *     ),
+     * 
+     *  )
+     */
+
+    /**
+     * insert user
+     * @return id of the user created
+     */
+    function PUT() {
+        $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'domain', 'domain_id');
+        if ($aReturn['sStatus'] == 1) {
+
+            $oDomain = new Domain($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+            $oDomain->GET();
+            $error = $this->writeDomainInProperties($oDomain->aFields, "update");
+            if ($error['sStatus'] == 1) {
+                $sMessage = $aReturn['sMessage'];
+            } else {
+
+                $oError = new VitisError(1, $error['sMessage']);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        } else {
+            $sMessage = $aReturn['sMessage'];
+        }
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Delete(path="/domains/",
+     *   tags={"Domains"},
+     *   summary="delete Domain",
+     *   description="Request to delete Domain",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="domain token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="idList",
+     *     in="query",
+     *     description="id of the domains",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/domains")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Delete(path="/domains/{domain_id}",
+     *   tags={"Domains"},
+     *   summary="delete Domain",
+     *   description="Request to delete Domain",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="domain token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="domain_id",
+     *     in="path",
+     *     description="id of the domain",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/domains")
+     *     )
+     *  )
+     */
+
+    /**
+     * delete domain
+     * @return id of domain deleted or error object if a domain is not deleted
+     */
+    function DELETE() {
+        $aReturn = $this->genericDelete($this->aProperties['schema_framework'], 'domain', 'domain_id');
+        if ($aReturn['sStatus'] == 1) {
+            $oDomain = new Domain($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+            $oDomain->GET();
+            $error = $this->writeDomainInProperties($oDomain->aFields, 'delete');
+            if ($error['sStatus'] == 1) {
+                $sMessage = $aReturn['sMessage'];
+            } else {
+                $oError = new VitisError(1, $error['sMessage']);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        } else {
+            $sMessage = $aReturn['sMessage'];
+        }
+        return $sMessage;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/FormatDate.class.inc b/vas/rest/ws/vitis/FormatDate.class.inc
new file mode 100755
index 00000000..86400273
--- /dev/null
+++ b/vas/rest/ws/vitis/FormatDate.class.inc
@@ -0,0 +1,78 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file FormatDate.class.inc
+ * \class FormatDate
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the FormatDate php class
+ *
+ * This class defines operation for one FormatDate
+ * 
+ */
+class FormatDate extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("formatdate_id", "formatdate", "CONCAT(formatdate, to_char(NOW(), ' (' || formatdate_id || ' HH24:MI:SS'), ')') as label");
+    }
+
+    /**
+     * @SWG\Get(path="/formatdates/{formatdate_id}", 
+     *   tags={"FormatDates"},
+     *   summary="Get FormatDate",
+     *   description="Request to get FormatDate by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="formatdate_id",
+     *     in="path",
+     *     description="formatdate id",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/formatdates")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "rt_formatdate", "formatdate_id");
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/FormatDates.class.inc b/vas/rest/ws/vitis/FormatDates.class.inc
new file mode 100755
index 00000000..e66f8710
--- /dev/null
+++ b/vas/rest/ws/vitis/FormatDates.class.inc
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * \file FormatDates.class.inc
+ * \class FormatDates
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis FormatDates
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'FormatDate.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class FormatDates extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/formatdates",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/formatdates")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="FormatDates",
+     *   description="Operations about FormatDates"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("formatdate_id", "formatdate", "CONCAT(formatdate, to_char(NOW(), ' (' || formatdate_id || ' HH24:MI:SS'), ')') as label");
+    }
+
+    /**
+     * @SWG\Get(path="/formatdates",
+     *   tags={"FormatDates"},
+     *   summary="Get FormatDates",
+     *   description="Request to get FormatDates",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/formatdates")
+     *     )
+     *  )
+     */
+
+    /**
+     * get FormatDates
+     * @return  FormatDates
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "rt_formatdate", "formatdate_id");
+        return $aReturn['sMessage'];
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/GenericQuery.class.inc b/vas/rest/ws/vitis/GenericQuery.class.inc
new file mode 100755
index 00000000..cbd3217c
--- /dev/null
+++ b/vas/rest/ws/vitis/GenericQuery.class.inc
@@ -0,0 +1,42 @@
+<?php
+
+require_once 'Vitis.class.inc';
+
+/**
+ * \file Query.class.inc
+ * \class Query
+ *
+ * \author Armand Bahi <armand.bahi@veremes.com>.
+ *
+ * 	\brief This file contains the Query php class
+ *
+ * This class defines operation for one Query
+ * 
+ */
+class GenericQuery extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array();
+    }
+
+    /**
+     * get informations about query
+     */
+    function GET() {
+        
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/GenericQuerys.class.inc b/vas/rest/ws/vitis/GenericQuerys.class.inc
new file mode 100755
index 00000000..ae3ade89
--- /dev/null
+++ b/vas/rest/ws/vitis/GenericQuerys.class.inc
@@ -0,0 +1,888 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once 'GenericQuery.class.inc';
+require_once __DIR__ . '/../../class/vmlib/BD.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file PrivateToken.class.inc
+ * \class PrivateToken
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the PrivateToken php class
+ *
+ * This class defines Rest Api to private token
+ */
+class GenericQuerys extends Vitis {
+
+    public $aSql = array();
+    public $oBd;
+
+    /**
+     * @SWG\Definition(
+     *   definition="/genericquerys",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/genericquerys")
+     *   },
+     * )
+     *  @SWG\Tag(
+     *   name="GenericQuerys",
+     *   description="Operations about GenericQuerys"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        require 'GenericQuerys.class.sql.inc';
+        $this->aSql = $aSql;
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+    }
+
+    /**
+     * @SWG\Get(path="/genericquerys",
+     *   tags={"GenericQuerys"},
+     *   summary="Get Querys",
+     *   description="Request to query a schema. There is two ways to use this service: with the token witch will use the current server/port/sgbd, with login/password witch can query distant servers",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="user login",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="user password",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="server",
+     *     in="query",
+     *     description="database server",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="port",
+     *     in="query",
+     *     description="database server port",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sgbd",
+     *     in="query",
+     *     description="database server sgbd(pgsql/oci)",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="database",
+     *     in="query",
+     *     description="database to query",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="schema",
+     *     in="query",
+     *     description="schema to query",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="table",
+     *     in="query",
+     *     description="table to query",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/genericquerys/{table_name}",
+     *   tags={"GenericQuerys"},
+     *   summary="Get Querys",
+     *   description="Request to query a table. There is two ways to use this service: with the token witch will use the current server/port/sgbd, with login/password witch can query distant servers",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="user login",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="user password",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="server",
+     *     in="query",
+     *     description="database server",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="port",
+     *     in="query",
+     *     description="database server port",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sgbd",
+     *     in="query",
+     *     description="database server sgbd (pgsql/oci)",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="database",
+     *     in="query",
+     *     description="database to query",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="schema",
+     *     in="query",
+     *     description="schema to query",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="table_name",
+     *     in="path",
+     *     description="table to query",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="encoding",
+     *     in="query",
+     *     description="table to query",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/genericquerys/{table_name}/columns",
+     *   tags={"GenericQuerys"},
+     *   summary="Get Querys",
+     *   description="Request to query. There is two ways to use this service: with the token witch will use the current server/port/sgbd, with login/password witch can query distant servers",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="user login",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="user password",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="server",
+     *     in="query",
+     *     description="database server",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="port",
+     *     in="query",
+     *     description="database server port",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sgbd",
+     *     in="query",
+     *     description="database server sgbd (pgsql/oci)",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="database",
+     *     in="query",
+     *     description="database to query",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="schema",
+     *     in="query",
+     *     description="schema to query",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="table_name",
+     *     in="path",
+     *     description="table to query",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="encoding",
+     *     in="query",
+     *     description="table to query",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/genericquerys/databases",
+     *   tags={"GenericQuerys"},
+     *   summary="Get Querys",
+     *   description="Get the dtabases list",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *   )
+     * )
+     */
+    /**
+     * @SWG\Get(path="/genericquerys/{database}/schemas",
+     *   tags={"GenericQuerys"},
+     *   summary="Get Querys",
+     *   description="Get the database schemas",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="database",
+     *     in="path",
+     *     description="database",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *   )
+     * )
+     */
+
+    /**
+     * get Querys
+     * @return  Querys
+     */
+    function GET() {
+        $aDataReturn = array('sStatus' => 0);
+        if (empty($this->aValues['encoding'])) {
+            $this->aValues['encoding'] = "UTF-8";
+        }
+
+        if (!empty($this->aValues['token'])) {
+
+            // Connexion par token
+            $this->oConnection = new Connection($this->aValues, $this->aProperties);
+
+            if (!empty($this->aValues['table']))
+                $this->aPath[2] = $this->aValues['table'];
+
+            $sLogin = '';
+            if (!empty($this->aValues['login']))
+                $sLogin = $this->aValues['login'];
+            if (empty($this->aValues['login']) || $this->aValues['login'] == 'u_vitis')
+                $this->aValues['login'] = $this->oConnection->oBd->login;
+
+            if (empty($this->aValues['password']) || $sLogin == 'u_vitis')
+                $this->aValues['password'] = $this->oConnection->oBd->mdp;
+
+            if (empty($this->aValues['server']))
+                $this->aValues['server'] = $this->oConnection->oBd->serveur;
+
+            if (empty($this->aValues['port']))
+                $this->aValues['port'] = $this->oConnection->oBd->port;
+
+            if (empty($this->aValues['database']))
+                $this->aValues['database'] = $this->oConnection->oBd->base;
+
+            if (empty($this->aValues['sgbd']))
+                $this->aValues['sgbd'] = $this->oConnection->oBd->sgbd;
+
+            if (empty($this->aValues['encoding']))
+                $this->aValues['encoding'] = $this->oConnection->oBd->sPageEncoding;
+        }
+        else {
+            if ($this->aValues['login'] == 'u_vitis') {
+                $this->aValues['login'] = '';
+                $this->aValues['password'] = '';
+            }
+        }
+
+        $this->oBd = new BD($this->aValues['login'], $this->aValues['password'], $this->aValues['database'], $this->aValues['server'], $this->aValues['port'], $this->aValues['sgbd'], $this->aValues['encoding']);
+        if ($this->oBd->erreurRencontree) {
+            writeToErrorLog(ERROR_CONNECTION_PROBLEM);
+            writeToErrorLog($this->oBd->getBDMessage());
+            $oError = new VitisError(1, $this->oBd->sMessage);
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            $bXMLError = true;
+        } else {
+            if (isset($this->aPath[2])) {
+                if ($this->aPath[2] == "databases") {
+                    $this->getDatabases();
+                    $aDataReturn = array('sStatus' => 1);
+                } else {
+                    if (!empty($this->aPath[3]) && $this->aPath[3] == "schemas") {
+                        $this->getSchemas($this->aPath[2]);
+                        $aDataReturn = array('sStatus' => 1);
+                    } else if (!empty($this->aPath[3]) && $this->aPath[3] == "columns") {
+                        $this->getTableColumns($this->aValues['schema'], $this->aPath[2]);
+                        $aDataReturn = array('sStatus' => 1);
+                    } else {
+                        $aDataReturn = $this->getData();
+                    }
+                }
+            } else {
+                $this->getTables($this->aValues['schema']);
+                $aDataReturn = array('sStatus' => 1);
+            }
+            $aXmlRacineAttribute['status'] = $aDataReturn['sStatus'];
+            if (!empty($aDataReturn['sMessage']))
+                return $aDataReturn['sMessage'];
+            else
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+
+    /**
+     * Display the databases
+     * @param type $sdatabases
+     */
+    function getDatabases() {
+        require_once 'Database.class.inc';
+        $sSql = $this->aSql[$this->aValues['sgbd']]['getDatabases'];
+        $aSQLParams = array();
+        $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+        if ($this->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oBd->getBDMessage());
+            writeToErrorLog($this->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            while ($aDatabase = $this->oBd->ligneSuivante($oPDOresult)) {
+                array_push($this->aObjects, new Database($aDatabase));
+            }
+        }
+    }
+
+    /**
+     * Get the schemas list
+     * @param String $sDatabase
+     */
+    function getSchemas($sDatabase) {
+        require_once 'Schema.class.inc';
+        $this->oBd = new BD($this->aValues['login'], $this->aValues['password'], $sDatabase, $this->aValues['server'], $this->aValues['port'], $this->aValues['sgbd'], $this->aValues['encoding']);
+        $sSql = $this->aSql[$this->aValues['sgbd']]['getSchemas'];
+        $aSQLParams = array();
+        $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+        if ($this->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oBd->getBDMessage());
+            writeToErrorLog($this->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            while ($aSchema = $this->oBd->ligneSuivante($oPDOresult)) {
+                array_push($this->aObjects, new Schema($aSchema));
+            }
+        }
+    }
+
+    /**
+     * Display the tables contained in the $sSchema param
+     * @param type $sSchema
+     */
+    function getTables($sSchema) {
+        require_once "Table.class.inc";
+
+        $sSql = $this->aSql[$this->aValues['sgbd']]['getTables'];
+        $aSQLParams = array('sSchema' => array('value' => $sSchema, 'type' => 'column_name'));
+
+        if (!empty($this->aValues['order_by'])) {
+            $aSQLParams['order_by'] = array('value' => $this->aValues['order_by'], 'type' => 'column_name');
+            $sSql .= ' ORDER BY "[order_by]"';
+        }
+
+        $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+        if ($this->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oBd->getBDMessage());
+            writeToErrorLog($this->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            while ($aTable = $this->oBd->ligneSuivante($oPDOresult)) {
+                array_push($this->aObjects, new Table($aTable));
+            }
+        }
+
+        if ($this->aValues['sgbd'] === 'pgsql') {
+
+            $sSql = $this->aSql['pgsql']['getViews'];
+            $aSQLParams = array('sSchema' => array('value' => $sSchema, 'type' => 'column_name'));
+
+            if (!empty($this->aValues['order_by'])) {
+                $aSQLParams['order_by'] = array('value' => $this->aValues['order_by'], 'type' => 'column_name');
+                $sSql .= ' ORDER BY "[order_by]"';
+            }
+
+            $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+            if ($this->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oBd->getBDMessage());
+                writeToErrorLog($this->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            } else {
+                while ($aTable = $this->oBd->ligneSuivante($oPDOresult)) {
+                    array_push($this->aObjects, new Table($aTable));
+                }
+            }
+
+            $sSql = $this->aSql['pgsql']['getMatviews'];
+            $aSQLParams = array('sSchema' => array('value' => $sSchema, 'type' => 'column_name'));
+
+            if (!empty($this->aValues['order_by'])) {
+                $aSQLParams['order_by'] = array('value' => $this->aValues['order_by'], 'type' => 'column_name');
+                $sSql .= ' ORDER BY "[order_by]"';
+            }
+
+            $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+            if ($this->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oBd->getBDMessage());
+                writeToErrorLog($this->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            } else {
+                while ($aTable = $this->oBd->ligneSuivante($oPDOresult)) {
+                    array_push($this->aObjects, new Table($aTable));
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Display the columns contained in the $sSchema, $sTable param
+     * @param type $sSchema
+     * @param type $sTable
+     */
+    function getTableColumns($sSchema, $sTable) {
+        require_once "Column.class.inc";
+
+        $sSql = $this->aSql[$this->aValues['sgbd']]['getTableColumns'];
+        $aSQLParams = array(
+            'sSchema' => array('value' => $sSchema, 'type' => 'column_name'),
+            'sTable' => array('value' => $sTable, 'type' => 'column_name')
+        );
+
+        $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+        if ($this->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            while ($aColumn = $this->oBd->ligneSuivante($oPDOresult))
+                array_push($this->aObjects, new Column($aColumn));
+        }
+    }
+
+    /**
+     * Get the table columns with $this->aSelectedFields  and returns an array
+     * @param type $sSchema
+     * @param type $sTable
+     * @return array
+     */
+    function tableColumns($sSchema, $sTable) {
+        require_once "Column.class.inc";
+        $aColumn = [];
+
+        $sSql = $this->aSql[$this->aValues['sgbd']]['getTableColumns'];
+        $aSQLParams = array(
+            'sSchema' => array('value' => $sSchema, 'type' => 'column_name'),
+            'sTable' => array('value' => $sTable, 'type' => 'column_name')
+        );
+
+        $oResult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+        if (!empty($oResult)) {
+            while ($aObject = $this->oBd->ligneSuivante($oResult)) {
+                if ($aObject['data_type'] != 'SDO_GEOMETRY' && $aObject['data_type'] != 'geometry') {
+                    array_push($aColumn, $aObject['column_name']);
+                }
+            }
+            foreach ($this->aSelectedFields as $fields) {
+                if (strpos($fields, "(") != FALSE && strpos($fields, ")") != FALSE && strpos(strtolower($fields), " as ") != FALSE) {
+                    array_push($aColumn, $fields);
+                }
+            }
+        }
+        $oResult = $this->oBd->fermeResultat();
+        return $aColumn;
+    }
+
+    /**
+     * Display the result from the requested query
+     * Ne gère pas les données géométriques !
+     * @param type $bOnlyReturnStatus
+     * @return int
+     */
+    function getData($bOnlyReturnStatus = false) {
+
+        $sSchema = $this->aValues['schema'];
+        $sTable = $this->aPath[2];
+
+        $aSQLParams = array(
+            'sSchema' => array('value' => $sSchema, 'type' => 'column_name'),
+            'sTable' => array('value' => $sTable, 'type' => 'column_name')
+        );
+
+        if (isset($this->aValues['limit'])) {
+            $aSQLParams['limit'] = array('value' => $this->aValues['limit'], 'type' => 'number');
+        }
+        if (isset($this->aValues['offset'])) {
+            $aSQLParams['offset'] = array('value' => $this->aValues['offset'], 'type' => 'number');
+        }
+        if (isset($this->aValues['sort_order'])) {
+            $aSQLParams['sort_order'] = array('value' => $this->aValues['sort_order'], 'type' => 'column_name');
+        }
+
+
+        $sSql = "SELECT ";
+        if ($this->aValues['distinct'] == "true") {
+            $sSql .= "DISTINCT ";
+        }
+        $aColumn = $this->tableColumns($sSchema, $sTable);
+
+        $aFieldInTable = [];
+        $aAttribute = explode("|", $this->aValues['attributs']);
+        foreach ($aColumn as $value) {
+            if (in_array($value, $aAttribute) || empty($this->aValues['attributs'])) {
+                array_push($aFieldInTable, '"' . $value . '"');
+            }
+        }
+        if (!empty($aFieldInTable)) {
+            foreach ($aFieldInTable as $fields) {
+                if ($sSql == "SELECT " || $sSql == "SELECT DISTINCT ") {
+                    $sSql .= $fields;
+                } else {
+                    $sSql .= ", " . $fields;
+                }
+            }
+        } else {
+            $sSql = "SELECT * ";
+        }
+        $sSql .= ' FROM "[sSchema]"."[sTable]"';
+
+        if (isset($this->aValues['filter'])) {
+            // filtre
+            $aDecodedFilter = $this->decodeJSONFilter($this->aValues['filter'], $sSchema, $sTable);
+            // Ajout dans la requête
+            $sSecuredFilter = $aDecodedFilter['request'];
+            // Ajout des paramètres
+            foreach ($aDecodedFilter['params'] as $key => $value) {
+                $aSQLParams[$key] = $value;
+            }
+            // Ajout à la requête
+            if (!empty(trim($sSecuredFilter))) {
+                if (strpos($sSql, " WHERE ") == FALSE) {
+                    $sSql .= " WHERE " . $sSecuredFilter;
+                } else {
+                    $sSql .= " AND " . $sSecuredFilter;
+                }
+            }
+        }
+        //order by
+        //limit
+        switch ($this->aValues['sgbd']) {
+            case "oci":
+                if (isset($this->aValues['limit']) && isset($this->aValues['offset'])) {
+                    $this->aValues['limit'] = $this->aValues['limit'] + $this->aValues['offset'];
+                }
+                if (isset($this->aValues['limit'])) {
+                    if (strpos($sSql, " WHERE ") == FALSE) {
+                        $sSql .= " WHERE rownum <= [limit]";
+                    } else {
+                        $sSql .= " AND rownum <= [limit]";
+                    }
+                }
+
+                //offset
+                if (isset($this->aValues['order_by'])) {
+                    $aOrder = explode("|", $this->aValues['order_by']);
+                    foreach ($aOrder as $value) {
+
+                        $sOrderKey = 'order_by_' . vitisUniqId();
+                        $aSQLParams[$sOrderKey] = array('value' => $value, 'type' => 'column_name');
+
+                        if (strpos($sSql, "ORDER BY") == FALSE) {
+                            $sSql .= " ORDER BY " . str_replace("=", " ", "\"[" . $sOrderKey . "]\"");
+                        } else {
+                            $sSql .= ", " . str_replace("=", " ", "\"[" . $sOrderKey . "]\"");
+                        }
+                    }
+                    if (isset($this->aValues['sort_order'])) {
+                        switch (strtoupper($this->aValues['sort_order'])) {
+                            case 'ASC':
+                                $sSql .= " ASC";
+                                break;
+                            case 'DESC':
+                                $sSql .= " DESC";
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                }
+                break;
+            default:
+                if (isset($this->aValues['order_by'])) {
+                    $aOrder = explode("|", $this->aValues['order_by']);
+
+                    foreach ($aOrder as $value) {
+
+                        $sOrderKey = 'order_by_' . vitisUniqId();
+                        $aSQLParams[$sOrderKey] = array('value' => $value, 'type' => 'column_name');
+
+                        if (strpos($sSql, "ORDER BY") == FALSE) {
+                            $sSql .= " ORDER BY " . str_replace("=", " ", "\"[" . $sOrderKey . "]\"");
+                        } else {
+                            $sSql .= ", " . str_replace("=", " ", "\"[" . $sOrderKey . "]\"");
+                        }
+                    }
+                    if (isset($this->aValues['sort_order'])) {
+                        switch (strtoupper($this->aValues['sort_order'])) {
+                            case 'ASC':
+                                $sSql .= " ASC";
+                                break;
+                            case 'DESC':
+                                $sSql .= " DESC";
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                }
+                if (isset($this->aValues['limit'])) {
+                    $sSql .= " LIMIT [limit]";
+                }
+                //offset
+                if (isset($this->aValues['offset'])) {
+                    $sSql .= " OFFSET [offset]";
+                }
+                break;
+        }
+        $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams);
+
+        if ($this->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oBd->getBDMessage());
+        } else {
+            while ($aLigne = $oPDOresult->fetch(PDO::FETCH_ASSOC)) {
+                $oObject = new GenericQuery($this->aPath, $this->aValues, $this->aProperties, true, $this->oConnection);
+                $oObject->aFields = $aLigne;
+                array_push($this->aObjects, $oObject);
+            }
+            $this->aFields['list_count'] = $this->oBd->nombreLigne($oPDOresult);
+
+            $aSQLParams2 = array(
+                'sSchema' => array('value' => $sSchema, 'type' => 'column_name'),
+                'sTable' => array('value' => $sTable, 'type' => 'column_name')
+            );
+
+            $sSql = 'select count(*) as "total_row_number" FROM "[sSchema]"."[sTable]"';
+
+            if (isset($this->aValues['filter'])) {
+                // filtre
+                $aDecodedFilter = $this->decodeJSONFilter($this->aValues['filter'], $sSchema, $sTable);
+                // Ajout dans la requête
+                $sSecuredFilter = $aDecodedFilter['request'];
+                // Ajout des paramètres
+                foreach ($aDecodedFilter['params'] as $key => $value) {
+                    $aSQLParams2[$key] = $value;
+                }
+                // Ajout à la requête
+                if (!empty(trim($sSecuredFilter))) {
+                    if (strpos($sSql, " WHERE ") == FALSE) {
+                        $sSql .= " WHERE " . $sSecuredFilter;
+                    } else {
+                        $sSql .= " AND " . $sSecuredFilter;
+                    }
+                }
+            }
+        }
+        $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams2);
+
+        if ($this->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oBd->getBDMessage());
+        } else {
+            $aLigne = $this->oBd->ligneSuivante($oPDOresult);
+            $this->aFields['total_row_number'] = $aLigne['total_row_number'];
+        }
+
+        if (isset($oError)) {
+            $aXmlRacineAttribute['status'] = 0;
+            if (!$bOnlyReturnStatus)
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            $aXmlRacineAttribute['status'] = 1;
+            if (!$bOnlyReturnStatus)
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+
+        if (!$bOnlyReturnStatus)
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+        else
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status']);
+        return $aReturn;
+    }
+
+}
+
+?>
diff --git a/vas/rest/ws/vitis/GenericQuerys.class.sql.inc b/vas/rest/ws/vitis/GenericQuerys.class.sql.inc
new file mode 100755
index 00000000..0e21185d
--- /dev/null
+++ b/vas/rest/ws/vitis/GenericQuerys.class.sql.inc
@@ -0,0 +1,14 @@
+<?php
+
+//Définition des requêtes de l'api Vitis
+$aSql['oci']['getTables'] = "SELECT table_name as \"table_name\" FROM user_tables WHERE TABLESPACE_NAME <> 'SYSTEM'";
+$aSql['oci']['getTableColumns'] = "Select COLUMN_NAME as \"column_name\", data_type as \"data_type\" from USER_TAB_COLUMNS where TABLE_NAME = '[sTable]' ";
+
+$aSql['pgsql']['getTables'] = "SELECT table_name FROM(SELECT tablename as \"table_name\", schemaname FROM pg_catalog.pg_tables) as tables WHERE schemaname = '[sSchema]'";
+$aSql['pgsql']['getViews'] = "SELECT table_name FROM(SELECT viewname as \"table_name\", schemaname FROM pg_catalog.pg_views) as tables WHERE schemaname = '[sSchema]'";
+$aSql['pgsql']['getMatviews'] = "SELECT table_name FROM(SELECT matviewname as \"table_name\", schemaname FROM pg_catalog.pg_matviews) as tables WHERE schemaname = '[sSchema]'";
+$aSql['pgsql']['getTableColumns'] = "SELECT column_name, udt_name as data_type FROM INFORMATION_SCHEMA.COLUMNS where table_schema = '[sSchema]' and table_name = '[sTable]' ORDER BY column_name";
+
+$aSql['pgsql']['getDatabases'] = "select pg_database.datname as database from pg_database order by database";
+$aSql['pgsql']['getSchemas'] = "SELECT DISTINCT(table_schema) as schema_name FROM information_schema.tables";
+?>
diff --git a/vas/rest/ws/vitis/Group.class.inc b/vas/rest/ws/vitis/Group.class.inc
new file mode 100755
index 00000000..653cad90
--- /dev/null
+++ b/vas/rest/ws/vitis/Group.class.inc
@@ -0,0 +1,119 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Group.class.inc
+ * \class Group
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Group php class
+ *
+ * This class defines operation for one Group
+ * 
+ */
+class Group extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("group_id", "name", "nb_members", "users");
+    }
+
+    /**
+     * @SWG\Get(path="/groups/{group_id}", 
+     *   tags={"Groups"},
+     *   summary="Get Group",
+     *   description="Request to get Group by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="group_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *   format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/groups")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "v_group", "group_id");
+        $this->getUsers();
+    }
+
+    /**
+     *  get users of group
+     */
+    function getUsers() {
+        require $this->sRessourcesFile;
+        if (in_array("users", $this->aSelectedFields)) {
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['group_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGroupUsers'], $aParams);
+            $sListUserId = "";
+            $aListUserLogin = array();
+            while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                if ($sListUserId == "") {
+                    $sListUserId = $aLigne["user_id"];
+                } else {
+                    $sListUserId .= "|" . $aLigne["user_id"];
+                }
+                $aListUserLogin[] = $aLigne["login"];
+            }
+            $oPDOresult = $this->oConnection->oBd->fermeResultat();
+            $this->aFields['users'] = $sListUserId;
+            $this->aFields['users_label'] = implode(',', $aListUserLogin);
+        }
+    }
+
+    /**
+     * delete an user
+     */
+    function DELETE() {
+        $this->oConnection->oBd->delete($this->aProperties['schema_framework'], 'v_group', 'group_id', $this->aValues['my_vitis_id'], 'integer');
+        if ($this->oConnection->oBd->enErreur()) {
+            $this->oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+        } else {
+            $this->aFields['group_id'] = $this->aValues['my_vitis_id'];
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Groups.class.inc b/vas/rest/ws/vitis/Groups.class.inc
new file mode 100755
index 00000000..77fd5142
--- /dev/null
+++ b/vas/rest/ws/vitis/Groups.class.inc
@@ -0,0 +1,393 @@
+<?php
+
+/**
+ * \file Groups.class.inc
+ * \class Groups
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis Groups
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Group.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Groups extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/groups",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/groups")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Groups",
+     *   description="Operations about Groups"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("group_id", "name", "nb_members", "users");
+    }
+
+    /**
+     * @SWG\Get(path="/groups",
+     *   tags={"Groups"},
+     *   summary="Get Groups",
+     *   description="Request to get Groups",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="group token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/groups")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Groups
+     * @return  Groups
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_group", "group_id");
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * @SWG\Post(path="/groups",
+     *   tags={"Groups"},
+     *   summary="Add Group",
+     *   description="Request to add group",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="group token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="name",
+     *     in="formData",
+     *     description="Name of the group",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="users",
+     *     in="formData",
+     *     description="Users of the group",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/groups")
+     *     )
+     *  )
+     */
+
+    /**
+     * insert group
+     * @return id of the group created
+     */
+    function POST() {
+        // Importation d'un groupe AD ?
+        if (!empty($this->aValues['action'])) {
+            $sMessage = $this->importLdapGroup();
+        } else {
+            $aReturn = $this->genericPost($this->aProperties['schema_framework'], 'v_group', $this->aProperties['schema_framework'] . '.seq_common', 'group_id');
+            if ($aReturn['sStatus'] == 1) {
+
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                $oGroup = new Group($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+                $oGroup->GET();
+                // Le paramètre "users" est passé dans la requête ?
+                if ($this->aValues['users'] !== NULL) {
+                    // Utilisateurs à rattacher au groupe ?
+                    if (!empty($this->aValues['users'])) {
+                        require $this->sRessourcesFile;
+                        $aUsers = explode('|', $this->aValues['users']);
+                        foreach ($aUsers as $iUserId) {
+                            $aParams = array();
+                            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                            $aParams['user_id'] = array('value' => $iUserId, 'type' => 'number');
+                            $aParams['group_id'] = array('value' => $this->aValues["my_vitis_id"], 'type' => 'number');
+                            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['insertGroupUsers'], $aParams);
+                        }
+                    }
+                }
+            } else {
+                $sMessage = $aReturn['sMessage'];
+            }
+        }
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Put(path="/groups/{group_id}",
+     *   tags={"Groups"},
+     *   summary="Update Group",
+     *   description="Request to update Group",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="group token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="group_id",
+     *     in="path",
+     *     description="id of the group",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="name",
+     *     in="query",
+     *     description="Name of the group",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="users",
+     *     in="query",
+     *     description="Users of the group",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/groups")
+     *     )
+     *  )
+     */
+
+    /**
+     * update group
+     * @return id of the group if ok error object if ko
+     */
+    function PUT() {
+        $aValues = $this->aValues;
+        // Recherche de l'ancien nom de groupe
+        $sSql = "SELECT name FROM [sSchemaFramework].group WHERE group_id = [group_id];";
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['group_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, $aParams);
+        $aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+        $this->aValues = $aValues;
+        $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'v_group', 'group_id');
+        if ($aReturn['sStatus'] == 1) {
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            $oGroup = new Group($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+            $oGroup->GET();
+            // Supprime les Utilisateurs rattachés au groupe.
+            $this->oConnection->oBd->delete($this->aProperties['schema_framework'], 'v_user_group_by_rights', 'group_id', $this->aValues["my_vitis_id"]);
+            // Le paramètre "users" est passé dans la requête ?
+            if ($this->aValues['users'] !== NULL) {
+                // Utilisateurs à rattacher au groupe ?
+                if (!empty($this->aValues['users'])) {
+                    require $this->sRessourcesFile;
+                    $aUsers = explode('|', $this->aValues['users']);
+                    foreach ($aUsers as $iUserId) {
+                        $aParams = array();
+                        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                        $aParams['user_id'] = array('value' => $iUserId, 'type' => 'number');
+                        $aParams['group_id'] = array('value' => $this->aValues["my_vitis_id"], 'type' => 'number');
+                        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['insertGroupUsers'], $aParams);
+                    }
+                }
+            }
+        } else {
+            $sMessage = $aReturn['sMessage'];
+        }
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Delete(path="/groups/",
+     *   tags={"Groups"},
+     *   summary="delete Group",
+     *   description="Request to delete Group",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="group token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="idList",
+     *     in="query",
+     *     description="id of the groups",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/groups")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Delete(path="/groups/{group_id}",
+     *   tags={"Groups"},
+     *   summary="delete Group",
+     *   description="Request to delete Group",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="group token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="group_id",
+     *     in="path",
+     *     description="id of the group",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/groups")
+     *     )
+     *  )
+     */
+
+    /**
+     * delete group
+     * @return id of group deleted or error object if a group is not deleted
+     */
+    function DELETE() {
+        $aReturn = $this->genericDelete($this->aProperties['schema_framework'], 'v_group', 'group_id');
+        return $aReturn['sMessage'];
+    }
+
+    /*
+     * *	Import des groupes de l'A.D.
+     */
+
+    Public function importLdapGroup() {
+        require $this->sRessourcesFile;
+        // Le groupe existe déja ?
+        $aParams = array();
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['sName'] = array('value' => $this->aValues['name'], 'type' => 'string');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGroupId'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            $oResult = $this->oConnection->oBd->objetSuivant($oPDOresult);
+            if ($oResult) {
+                $this->oConnection->oBd->update($this->aProperties["schema_framework"], 'group', $this->aValues, "group_id", $oResult->group_id);
+                $this->aFields['group_id'] = $oResult->group_id;
+            } else {
+                $iId = $this->oConnection->oBd->insert($this->aProperties["schema_framework"], 'group', $this->aValues, $this->aProperties['schema_framework'] . '.seq_common', 'group_id');
+                $this->aFields['group_id'] = $iId;
+            }
+            if ($this->oConnection->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            } else {
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        }
+        return $sMessage;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Logs.class.inc b/vas/rest/ws/vitis/Logs.class.inc
new file mode 100755
index 00000000..29c883fb
--- /dev/null
+++ b/vas/rest/ws/vitis/Logs.class.inc
@@ -0,0 +1,540 @@
+<?php
+
+/**
+ * \file Logs.class.inc
+ * \class Logs
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Logs php class
+ *
+ * This class defines Rest Api to Vitis logs
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once 'Properties.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Logs extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/logs",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/logs")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Logs",
+     *   description="Operations about Logs"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array();
+    }
+
+    /**
+     * @SWG\Get(path="/logs",
+     *   tags={"Logs"},
+     *   summary="Get logs tree",
+     *   description="Request to get the logs tree",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="application_name",
+     *     in="query",
+     *     description="",
+     *     required=true,
+     *     type="string",
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/logs")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/logs/{log_directory}/file/{file_name}",
+     *   tags={"Logs"},
+     *   summary="Get log file content",
+     *   description="Request to get the content of a log file",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="log_directory",
+     *     in="path",
+     *     description="Key in properties.log_directories",
+     *     required=true,
+     *     type="string",
+     *   ),
+     * @SWG\Parameter(
+     *     name="file_name",
+     *     in="path",
+     *     description="",
+     *     required=true,
+     *     type="string",
+     *   ),
+     * @SWG\Parameter(
+     *     name="folder",
+     *     in="query",
+     *     description="File path from the log_directory",
+     *     required=false,
+     *     type="string",
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/logs")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Logs
+     * @return  Logs
+     */
+    function GET() {
+        // Verify connection.
+        if (!empty($this->oConnection->oError)) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        // Privilège "vitis_admin" requis.
+        if (!in_array('vitis_admin', $this->oConnection->aPrivileges)) {
+            $oError = new VitisError(1, "Rights problem : you don't have right to delete log files");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+
+        if (!empty($this->aPath[4])) {
+
+            $sDirectoryName = $this->aPath[2];
+            $sFileName = $this->aPath[4];
+            $sFileFolder = empty($this->aValues['folder']) ? '' : $this->aValues['folder'];
+            $sFilePath = $sFileFolder . '/' . $sFileName;
+
+            // Contenu d'un fichier de log
+            $aReturn = $this->getLogFileContent($sDirectoryName, $sFileName, $sFilePath);
+        } else {
+            // Arborescence de l'arbre
+            $aReturn = $this->getLogsTree();
+        }
+
+        //
+        $aXmlRacineAttribute['status'] = $aReturn['status'];
+        if ($aReturn['status'] == 1)
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        else {
+            $oError = new VitisError($aReturn['error_code'], $aReturn['message']);
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Delete(path="/logs",
+     *   tags={"Logs"},
+     *   summary="delete log files",
+     *   description="Request to delete log files from min_days",
+     *   operationId="DELETE",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="min_days",
+     *     in="query",
+     *     description="number of days from the last revision",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/logs")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Delete(path="/logs/{log_directory}/file/{file_name}",
+     *   tags={"Logs"},
+     *   summary="delete log files",
+     *   description="Request to delete log files",
+     *   operationId="DELETE",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="log_directory",
+     *     in="path",
+     *     description="",
+     *     required=true,
+     *     type="string",
+     *   ),
+     * @SWG\Parameter(
+     *     name="file_name",
+     *     in="path",
+     *     description="",
+     *     required=true,
+     *     type="string",
+     *   ),
+     * @SWG\Parameter(
+     *     name="folder",
+     *     in="query",
+     *     description="File path from the log_directory",
+     *     required=false,
+     *     type="string",
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/logs")
+     *     )
+     *  )
+     */
+
+    /**
+     * delete log files
+     */
+    function DELETE() {
+        // Verify connection.
+        if (!empty($this->oConnection->oError)) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        // Privilège "vitis_admin" requis.
+        if (!in_array('vitis_admin', $this->oConnection->aPrivileges)) {
+            $oError = new VitisError(1, "Rights problem : you don't have right to delete log files");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        $aFilesToDelete = array();
+        if (!empty($this->aValues['min_days'])) {
+            // min_days
+            if (is_numeric($this->aValues['min_days'])) {
+                $iMinDays = $this->aValues['min_days'];
+                if (!empty($this->aProperties['log_directories'])) {
+                    foreach ($this->aProperties['log_directories'] as $sLogName => $sLogDir) {
+                        if (is_dir($sLogDir)) {
+                            $aDirStructure = $this->getDirStructure($sLogDir, $sLogName, $sLogName, "");
+                            if (!empty($aDirStructure["files"])) {
+                                foreach ($aDirStructure["files"] as $aFiles) {
+                                    if ($aFiles['last_modif'] >= $iMinDays) {
+                                        $aFilesToDelete[] = $aFiles['path'];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } else if (!empty($this->aPath[2]) && !empty($this->aPath[4])) {
+
+            $sDirectoryName = $this->aPath[2];
+            $sFileName = $this->aPath[4];
+            $sFileFolder = empty($this->aValues['folder']) ? '' : $this->aValues['folder'];
+            $sFilePath = $sFileFolder . '/' . $sFileName;
+            $aLogDirectories = $this->aProperties['log_directories'];
+
+            if (!isset($aLogDirectories[$sDirectoryName]) || empty($aLogDirectories[$sDirectoryName])) {
+                $aReturn = array('status' => 0, 'message' => "FILE_NOT_FOUND_LOGS", 'error_code' => 1);
+                return $aReturn;
+            }
+
+            $sPath = realpath($aLogDirectories[$sDirectoryName] . '/' . $sFilePath);
+            $aFilesToDelete[] = $sPath;
+        } else {
+            $oError = new VitisError(1, "Wrong given params");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+
+        $aReturn = $this->deleteFilesList($aFilesToDelete);
+
+        //
+        $aXmlRacineAttribute['status'] = $aReturn['status'];
+        if ($aReturn['status'] == 1) {
+            $this->aFields['files_deleted'] = $aReturn['files_deleted'];
+            $this->aFields['files_not_found'] = $aReturn['files_not_found'];
+            $this->aFields['files_not_deleted'] = $aReturn['files_not_deleted'];
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            $oError = new VitisError($aReturn['error_code'], $aReturn['message']);
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+
+    /**
+     * Get logs tree.
+     */
+    function getLogsTree() {
+        require $this->sRessourcesFile;
+        $aReturn = array('status' => 1, 'message' => '');
+        // Liste des modules de l'application.
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['application_name'] = array('value' => $this->aValues['application_name'], 'type' => 'string');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getApplicationModules'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $aReturn = array('status' => 1, 'message' => $this->oConnection->oBd->getBDMessage(), 'error_code' => 1);
+            /*
+              $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+              $aXmlRacineAttribute['status'] = 0;
+              $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+             */
+        } else {
+            // Charge toutes les properties.
+            $oProperties = new Properties($this->aPath, $this->aValues, $this->aProperties);
+            $oProperties->GET();
+            $properties = $oProperties->aFields;
+            // Création de l'arborescence des fichiers de logs.
+            if (!empty($properties['log_directories'])) {
+                foreach ($properties['log_directories'] as $sLogName => $sLogDir) {
+                    if (is_string($sLogDir)) {
+                        if (is_dir($sLogDir)) {
+                            $aDirStructure = $this->getDirStructure($sLogDir, $sLogName, $sLogName, "");
+                            $aTreeviewLogs["data"][] = $aDirStructure["data"];
+                            if (!empty($aDirStructure["files"])) {
+                                foreach ($aDirStructure["files"] as $aFiles) {
+                                    $aTreeviewLogs["files"][] = $aFiles;
+                                }
+                            }
+                        } else
+                            writeToErrorLog('scandir(' . $sLogDir . '): failed to open dir');
+                    }
+                }
+            }
+            $this->aFields['tree'] = $aTreeviewLogs;
+        }
+        return $aReturn;
+    }
+
+    /*
+     * Retourne l'arborescence d'un répertoire formaté pour "bootstrap-treeview".
+     */
+
+    function getDirStructure($sLogDir, $sDirName, $sLogName, $sFolder) {
+        $aFilteredDir['data'] = array('text' => $sDirName, 'selectable' => false);
+        $aDir = scandir($sLogDir);
+
+        if ($sDirName !== $sLogName) {
+            $sFolder .= '/' . $sDirName;
+        }
+
+        foreach ($aDir as $sName) {
+            $sPath = $sLogDir . '/' . $sName;
+            $sFileType = filetype($sPath);
+            // Répertoire ?
+            if ($sFileType == 'dir') {
+                if ($sName != '.' && $sName != '..') {
+                    if (is_dir($sPath)) {
+                        $aDirStructure = $this->getDirStructure($sPath . '/', $sName, $sLogName, $sFolder);
+                        if (!empty($aDirStructure['data']['nodes'])) {
+                            // Structure du répertoire.
+                            $aFilteredDir['data']['nodes'][] = $aDirStructure['data'];
+                            // Liste des fichiers .log du répertoire.
+                            foreach ($aDirStructure["files"] as $aFiles) {
+                                $aFilteredDir["files"][] = $aFiles;
+                            }
+                        }
+                    } else
+                        writeToErrorLog('scandir(' . $sPath . '): failed to open dir');
+                }
+            }
+            // fichier et .log ?
+            if ($sFileType == 'file' && pathinfo($sName, PATHINFO_EXTENSION) == 'log') {
+                // Taille + unité du fichier.
+                //$iFileSize = filesize($sPath);
+                $aFileInfos = stat($sPath);
+                $iFileSizeLabel = $aFileInfos['size'];
+                $aFileSizeUnity = array('o', 'Ko', 'Mo', 'Go', 'To');
+                $i = 0;
+                while ($iFileSizeLabel > 1024) {
+                    $iFileSizeLabel /= 1024;
+                    $i++;
+                }
+                // Sauve la structure du fichier pour le treeview.
+                $sFileLabel = $sName . ' (' . round($iFileSizeLabel) . ' ' . $aFileSizeUnity[$i] . ')';
+                $aFilteredDir['data']['nodes'][] = array(
+                    'folder' => $sFolder,
+                    'log_directory' => $sLogName,
+                    'name' => $sName,
+                    'text' => $sFileLabel,
+                    'icon' => 'glyphicon glyphicon-file',
+                    'path' => $sLogName . $sFolder . '/' . $sName,
+                    //'tags' => array('<span class="glyphicon glyphicon-trash"></span>'),
+                    'size' => $aFileInfos['size']
+                );
+                // Sauve le nom et la date du fichier.
+                $aFilteredDir['files'][] = array(
+                    'path' => $sPath,
+                    'last_modif' => floor((time() - $aFileInfos['mtime']) / (24 * 3600))    // dernière modif. (Nb jours). 
+                );
+            }
+        }
+        return $aFilteredDir;
+    }
+
+    /**
+     * Delete the log files defined in $aFilesToDelete
+     * @param array $aFilesToDelete
+     */
+    function deleteFilesList($aFilesToDelete) {
+
+        $aReturn = array('status' => 1, 'message' => '');
+        $aFilesDeleted = array();
+        $aFilesNotFound = array();
+        $aFilesNotDeleted = array();
+        foreach ($aFilesToDelete as $sPath) {
+            if (!empty($sPath)) {
+                if ($this->isLogFile($sPath)) {
+                    if (is_file($sPath)) {
+                        if (unlink($sPath)) {
+                            $aFilesDeleted[] = $sPath;
+                        } else {
+                            $aFilesNotDeleted[] = $sPath;
+                            $aLastError = error_get_last();
+                            if (strpos(strtolower($aLastError['message']), 'permission denied') !== false) {
+                                $sErrorMessage = 'DELETE_FILE_ERROR_PERMISSION_DENIED_LOGS';
+                            }
+                        }
+                    } else {
+                        $aFilesNotFound[] = $sPath;
+                    }
+                }
+            }
+        }
+        //
+        if (empty($aFilesDeleted)) {
+            $aReturn = array('status' => 0, 'error_code' => 1);
+            if (isset($sErrorMessage)) {
+                $aReturn['message'] = $sErrorMessage;
+            } else if (count($aFilesToDelete) == 1) {
+                $aReturn['message'] = 'DELETE_FILE_ERROR_LOGS';
+            } else {
+                $aReturn['message'] = 'DELETE_FILES_ERROR_LOGS';
+            }
+        }
+        if (!empty($aFilesNotFound) && count($aFilesToDelete) == 1) {
+            $aReturn = array('status' => 0, 'message' => "FILE_NOT_FOUND_LOGS", 'error_code' => 1);
+        }
+
+        if ($aReturn['status'] == 1) {
+            $aReturn['files_deleted'] = $aFilesDeleted;
+            $aReturn['files_not_found'] = $aFilesNotFound;
+            $aReturn['files_not_deleted'] = $aFilesNotDeleted;
+        }
+
+        return $aReturn;
+    }
+
+    /**
+     * Get the content of a log file.
+     */
+    function getLogFileContent($sDirectoryName, $sFileName, $sFilePath) {
+
+        // Charge toutes les properties.
+        $oProperties = new Properties($this->aPath, $this->aValues, $this->aProperties);
+        $oProperties->GET();
+        $properties = $oProperties->aFields;
+        $aLogDirectories = $properties['log_directories'];
+        if (!isset($aLogDirectories[$sDirectoryName]) || empty($aLogDirectories[$sDirectoryName])) {
+            $aReturn = array('status' => 0, 'message' => "FILE_NOT_FOUND_LOGS", 'error_code' => 1);
+            return $aReturn;
+        }
+
+        $sPath = realpath($aLogDirectories[$sDirectoryName] . '/' . $sFilePath);
+        $aReturn = array('status' => 1, 'message' => '');
+        if (file_exists($sPath) && $this->isLogFile($sPath)) {
+            $sFileContent = iconv("UTF-8", "UTF-8//IGNORE", file_get_contents($sPath));
+            if ($sFileContent !== false) {
+                $this->aFields['file'] = $sFileContent;
+            } else {
+                $aReturn = array('status' => 0, 'message' => "LOADING_FILE_ERROR_LOGS");
+            }
+        } else {
+            $aReturn = array('status' => 0, 'message' => "FILE_NOT_FOUND_LOGS", 'error_code' => 1);
+        }
+        return $aReturn;
+    }
+
+    /**
+     * .
+     */
+    function isLogFile($sFilePath) {
+        $bIsLogFile = false;
+        $aPathInfo = pathinfo($sFilePath);
+
+        // Charge toutes les properties.
+        $oProperties = new Properties($this->aPath, $this->aValues, $this->aProperties);
+        $oProperties->GET();
+        $properties = $oProperties->aFields;
+
+        // Extension ".log" obligatoire.
+        if ($aPathInfo['extension'] == 'log') {
+            // Répertoire des logs sans backslashes et plusieurs slashes.
+            $aLogDirectories = $properties['log_directories'];
+            foreach ($aLogDirectories as &$sLogDirectorie) {
+                if (is_string($sLogDirectorie))
+                    $sLogDirectorie = realpath($sLogDirectorie);
+            }
+            // Fichier de log sans backslashes et plusieurs slashes.
+            $sFilePath = realpath($sFilePath);
+
+            // Le fichier est dans un des répertoires de logs ?
+            foreach ($aLogDirectories as $sLogDirectorie) {
+                if (stripos($sFilePath, $sLogDirectorie) !== false) {
+                    $bIsLogFile = true;
+                    break;
+                }
+            }
+        }
+        return $bIsLogFile;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Mode.class.inc b/vas/rest/ws/vitis/Mode.class.inc
new file mode 100755
index 00000000..ca8a6d0f
--- /dev/null
+++ b/vas/rest/ws/vitis/Mode.class.inc
@@ -0,0 +1,86 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Mode.class.inc
+ * \class Mode
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Mode php class
+ *
+ * This class defines operation for one Mode
+ * 
+ */
+class Mode extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("mode_id", "index", "application_name", "module_name", "objects");
+    }
+
+    /**
+     * @SWG\Get(path="/modes/{mode_id}", 
+     *   tags={"Modes"},
+     *   summary="Get Mode",
+     *   description="Request to get Mode by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="mode_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *   format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/modes")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "v_mode", "mode_id");
+        $aValues = array("filter" => '{"column":"mode_id","compare_operator":"=","value":"' . $this->aFields["mode_id"] . '"}', "token" => $this->aValues['token']);
+        require_once'Tabs.class.inc';
+        $oTabs = new Tabs($this->aPath, $aValues, $this->aProperties);
+        $oTabs->GET();
+        array_push($this->aObjects, $oTabs);
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Modes.class.inc b/vas/rest/ws/vitis/Modes.class.inc
new file mode 100755
index 00000000..f9754ec0
--- /dev/null
+++ b/vas/rest/ws/vitis/Modes.class.inc
@@ -0,0 +1,233 @@
+<?php
+
+/**
+ * \file Modes.class.inc
+ * \class Modes
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis modes
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Mode.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Modes extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/Modes",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/Modes")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Modes",
+     *   description="Operations about Modes"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("mode_id", "index", "application_name", "module_name", "objects");
+    }
+
+    /**
+     * @SWG\Get(path="/modes",
+     *   tags={"Modes"},
+     *   summary="Get Modes",
+     *   description="Request to get Modes",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="action",
+     *     in="query",
+     *     type="string",
+     *         @SWG\Items(type="string"),
+     *         enum={"", "getAll"},
+     *     description="object of test",
+     *     required=false,
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Modes
+     * @return  Modes
+     */
+    function GET() {
+        if ($this->oConnection->oError == null) {
+            if (isset($this->aValues['action']) && !empty($this->aValues['action'])) {
+                if ($this->aValues['action'] == 'getAll') {
+                    $aReturn = $this->genericGet($this->aProperties['schema_framework'], "vm_mode_rolname", "mode_id", true);
+                } else {
+                    $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_mode", "mode_id", true);
+                }
+            } else {
+                $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_mode", "mode_id", true);
+            }
+            if ((!isset($this->aValues['attributs']) || strpos($this->aValues['attibuts'], 'objects') != false) && $aReturn['sStatus'] == 1) {
+                $aObjects = $this->aObjects;
+                $this->aObjects = array();
+                require_once'Tabs.class.inc';
+                foreach ($aObjects as $oMode) {
+                    $oMode->aFields["reload"] = true;
+                    $aValues = array("filter" => '{"relation": "AND","operators":[{"column": "mode_id","compare_operator": "=","value": "' . $oMode->aFields["mode_id"] . '"}, {"column": "lang","compare_operator": "=","value": "' . $this->aProperties["language"] . '"}]}', "token" => $this->aValues['token'], 'order_by' => 'index');
+                    $oTabs = new Tabs($this->aPath, $aValues, $this->aProperties);
+                    $oTabs->GET();
+                    array_push($oMode->aObjects, $oTabs);
+                    array_push($this->aObjects, $oMode);
+                }
+            }
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            http_response_code(403);
+            $aXmlRacineAttribute['status'] = 0;
+            $this->aFields['error'] = "ERROR : invalid token";
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Put(path="/modes/sorting",
+     *   tags={"Modes"},
+     *   summary="Sort modes",
+     *   description="Request to sort the modes of the application",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="modes_id",
+     *     in="query",
+     *     description="Modes of the application",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Properties Response",
+     *         @SWG\Schema(ref="#/definitions/modes")
+     *     ),
+     *  )
+     */
+
+    /**
+     * modify mode
+     * @return array containing the status and the message
+     */
+    function PUT() {
+        require $this->sRessourcesFile;
+        if (!empty($this->aPath[2])) {
+            if ($this->aPath[2] == "sorting") {
+                if (!empty($this->aValues['modes_id'])) {
+                    $aXmlRacineAttribute['status'] = 1;
+                    $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    $aModes = explode('|', $this->aValues['modes_id']);
+                    $i = 1;
+                    foreach ($aModes as $iModeId) {
+                        $aParams = array();
+                        $aParams['sSchemaName'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                        $aParams['mode_id'] = array('value' => $iModeId, 'type' => 'string');
+                        $aParams['index'] = array('value' => $i, 'type' => 'number');
+                        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['updateModesIndex'], $aParams);
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $this->oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            break;
+                        }
+                        $i++;
+                    }
+                }
+            }
+        }
+        return $sMessage;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/PhpInfo.class.inc b/vas/rest/ws/vitis/PhpInfo.class.inc
new file mode 100755
index 00000000..a9966a3a
--- /dev/null
+++ b/vas/rest/ws/vitis/PhpInfo.class.inc
@@ -0,0 +1,100 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+/**
+ * \file phpinfo.class.inc
+ * \class Phpinfo
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Phpinfo php class
+ *
+ * This class defines the rest api for phpinfo
+ * 
+ */
+class Phpinfo extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/phpinfo",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/phpinfo")
+     *   }
+     * )
+     * @SWG\Tag(
+     *   name="Phpinfo",
+     *   description="Operations about phpinfo"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $phpinfo ptroperties
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+    }
+
+    /**
+     * @SWG\Get(path="/phpinfo",
+     *   tags={"Phpinfo"},
+     *   summary="Get phpinfo",
+     *   description="Request to get phpinfo",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/phpinfo")
+     *     )
+     *  )
+     */
+
+    /**
+     * 
+     * @return phpinfo
+     */
+    function GET() {
+        if ($this->oConnection->oError == null && in_array("vitis_admin", $this->oConnection->aPrivileges)) {
+            define('STYLE_START', '<style');
+            define('STYLE_END', '</style>');
+
+            ob_start();
+            phpinfo();
+            $sPhpInfo = ob_get_contents();
+
+            // Supprime les styles des éléments
+            if (stripos($sPhpInfo, STYLE_START) !== false && stripos($sPhpInfo, STYLE_END) !== false) {
+                $sPhpInfoNoStyle = substr($sPhpInfo, 0, stripos($sPhpInfo, STYLE_START));
+                $sPhpInfoNoStyle .= substr($sPhpInfo, stripos($sPhpInfo, STYLE_END) + strlen(STYLE_END));
+            }
+            ob_end_clean();
+            //echo $sPhpInfoNoStyle;
+            //
+            $this->aFields['phpinfo'] = $sPhpInfoNoStyle;
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        } else {
+            http_response_code(403);
+            $aXmlRacineAttribute['status'] = 0;
+            $this->aFields['phpinfo'] = "ERROR : invalid token";
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/PrivateToken.class.inc b/vas/rest/ws/vitis/PrivateToken.class.inc
new file mode 100644
index 00000000..649dc10c
--- /dev/null
+++ b/vas/rest/ws/vitis/PrivateToken.class.inc
@@ -0,0 +1,289 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once("inc/MetadataAccess.class.inc");
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file PrivateToken.class.inc
+ * \class PrivateToken
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the PrivateToken php class
+ *
+ * This class defines Rest Api to private token
+ */
+class PrivateToken extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/privatetoken",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/privatetoken")
+     *   },
+     * )
+     *  @SWG\Tag(
+     *   name="Token",
+     *   description="Operations about token"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+    }
+
+    /**
+     * @SWG\Post(path="/privatetoken",
+     *   tags={"Token"},
+     *   summary="Get private token",
+     *   description="Request to get a token",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     * @SWG\Parameter(
+     *     name="user",
+     *     in="formData",
+     *     description="Login of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="formData",
+     *     description="Password of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="duration",
+     *     in="formData",
+     *     description="Session duration (minutes)",
+     *     required=false,
+     *     type="integer",
+     *     format="int32",
+     *     default="60"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Token Response",
+     *         @SWG\Schema(ref="#/definitions/privatetoken")
+     *     )
+     *  )
+     */
+
+    /**
+     * Post function to generate a token
+     * @return the token
+     */
+    function POST() {
+
+        // Si token est déjà définit, génère un nouveau token
+        if (isset($this->aValues['token']) && !empty($this->aValues['token']) && $this->aValues['token'] !== 'undefined') {
+            if (empty($this->aValues['user']) && empty($this->aValues['password'])) {
+                $oConnection = new Connection($this->aValues, $this->aProperties);
+                if (!empty($oConnection->oBd->login) && $oConnection->oBd->mdp) {
+                    $this->aValues['user'] = $oConnection->oBd->login;
+                    $this->aValues['password'] = $oConnection->oBd->mdp;
+                    session_regenerate_id(false);
+                    session_write_close();;
+                }
+            }
+        }
+
+        session_name(md5($this->aValues["user"] . '_' . uniqid()));
+        session_start();
+        require_once $this->sRessourcesFile;
+        $bXMLError = false;
+        // verify parameters
+        if ((!isset($this->aValues['user'])) || (!isset($this->aValues['password']))) {
+            $oError = new VitisError(2, "Missing parameters.");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument($this->aValues['xslstylesheet'], 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            $bXMLError = true;
+        } else {
+            if ($this->aProperties["allow_public_connection"] == false && $this->aValues['user'] == $this->aProperties["public_login"]) {
+                $oError = new VitisError(1, "Connection forbidden with public account.");
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                $bXMLError = true;
+                writeToErrorLog('ERROR : Connection forbidden with public account.');
+            } else {
+                // Suppression des majuscules et accents.
+                $this->aValues['user'] = mb_strtolower($this->aValues['user'], 'UTF-8');
+                $this->aValues['user'] = str_replace(array('à', 'â', 'ä', 'á', 'ã', 'å', 'î', 'ï', 'ì', 'í', 'ô', 'ö', 'ò', 'ó', 'õ', 'ø', 'ù', 'û', 'ü', 'ú', 'é', 'è', 'ê', 'ë', 'ç', 'ÿ', 'ñ'), array('a', 'a', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'e', 'e', 'e', 'e', 'c', 'y', 'n',), $this->aValues['user']);
+                //
+                if (!isset($this->aValues['duration'])) {
+                    if (!empty($this->aProperties['cookie_lifetime']))
+                        $this->aValues['duration'] = $this->aProperties['cookie_lifetime'];
+                    else
+                        $this->aValues['duration'] = 10;
+                }
+                if (isset($this->aValues['crypted']) && $this->aValues['crypted'] == 'true') {
+                    $this->aValues['password'] = trim(des(rtrim(utf8_decode($this->aValues["user"])), hexToString(rtrim($this->aValues["password"])), 0, 0, null));
+                }
+            }
+        }
+
+        if (!$bXMLError) {
+            //connect to database
+            $oBd = new BD($this->aValues["user"], $this->aValues["password"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"], $this->aProperties["page_encoding"]);
+            $_SESSION["ses_Login"] = $this->aValues["user"];
+            $ciphertext = stringToHex(des($this->aValues["user"], $this->aValues["password"], 1, 0));
+            $_SESSION["ses_Password"] = $ciphertext;
+            $_SESSION["ses_Remember"] = false;
+            $_SESSION["ses_Date"] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
+            if ($oBd->erreurRencontree) {
+                $oError = new VitisError(1, $oBd->sMessage);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                $bXMLError = true;
+            } else {
+                // Privilège 'vitis_user' obligatoire.
+                $aParams['sLogin'] = array('value' => $this->aValues["user"], 'type' => 'string');
+                $oPDOresult = $oBd->executeWithParams($aSql['getUserConnectionPrivileges'], $aParams);
+                if ($oBd->nombreLigne($oPDOresult) == 0) {
+                    $oError = new VitisError(18, "No 'vitis_user' privilege.");
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    writeToErrorLog("ERROR : No 'vitis_user' privilege for user '" . $this->aValues["user"] . "'.");
+                } else {
+                    // L'utilisateur doit exister dans la table s_vitis.user
+                    $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                    $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
+                    $oPDOresult = $oBd->executeWithParams($aSql['checkUser'], $aParams);
+                    if ($oBd->nombreLigne($oPDOresult) == 0) {
+                        $oError = new VitisError(1, 'The user ' . $_SESSION["ses_Login"] . ' does not exist');
+                        $aXmlRacineAttribute['status'] = 0;
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                        writeToErrorLog('ERROR : The user ' . $_SESSION["ses_Login"] . ' does not exist.');
+                    } else {
+                        //verify the ip from wich the user is connected
+                        $aParams = array();
+                        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                        $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
+                        $oPDOresult = $oBd->executeWithParams($aSql['checkIP'], $aParams);
+                        $aFields = $oBd->ligneSuivante($oPDOresult);
+                        $oMetadataAccess = new MetadataAccess($oBd, $_SESSION["ses_Login"], $_SESSION["ses_Password"], session_id(), $this->aProperties);
+                        $bAuthorizedIp = $oMetadataAccess->checkUserIp($_SERVER['REMOTE_ADDR']);
+                        if (!$bAuthorizedIp) {
+                            $oError = new VitisError(11, 'Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            $bXMLError = true;
+                            writeToErrorLog('ERROR : Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                        } else {
+
+                            error_log('session_id():' . session_id());
+
+                            $oConnection = new Connection(Array('token' => session_id()), $this->aProperties);
+                            $this->aFields['token'] = session_id();
+                            $this->aFields['user'] = $_SESSION["ses_Login"];
+                            $this->aFields['validity_date'] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
+                            $this->aFields['user_id'] = $aFields['user_id'];
+                            $this->aFields['privileges'] = $oConnection->aPrivileges;
+                            if ($this->aValues['output'] === 'application/xml') {
+                                $this->aFields['privileges'] = implode(',', $this->aFields['privileges']);
+                            }
+                            $_SESSION["ses_user_id"] = $aFields['user_id'];
+                            $_SESSION["ses_restriction"] = $aFields['restriction'];
+                            $aXmlRacineAttribute['status'] = 1;
+                            $aParams = array();
+                            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                            $aParams['user_id'] = array('value' => $aFields['user_id'], 'type' => 'number');
+                            $aParams['date'] = array('value' => gmdate('Y-m-d H:i:s'), 'type' => 'string');
+                            $oPDOresult = $oBd->executeWithParams($aSql['updateLastConnection'], $aParams);
+                            $sLogString = "connection" . $this->aProperties["log_delim"] . $_SESSION["ses_Login"] . $this->aProperties["log_delim"] . session_id();
+                            writeToLog($sLogString, $this->aProperties["connexion_log_file"]);
+                            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                        }
+                    }
+                }
+            }
+        }
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Get(path="/privatetoken",
+     *   tags={"Token"},
+     *   summary="Get token",
+     *   description="Request to get a token",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     * @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="token of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *
+     *
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Token Response",
+     *         @SWG\Schema(ref="#/definitions/privatetoken")
+     *     )
+     *  )
+     */
+
+    /**
+     * function get to verify the validity of the token
+     * @return token
+     */
+    function GET() {
+        require_once $this->sRessourcesFile;
+        $oConnection = new Connection($this->aValues, $this->aProperties);
+        if ($oConnection->oError != null) {
+            $oError = $oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            // L'utilisateur doit exister dans la table s_vitis.user
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
+            $oPDOresult = $oConnection->oBd->executeWithParams($aSql['checkUser'], $aParams);
+            if ($oConnection->oBd->nombreLigne($oPDOresult) == 0) {
+                $oError = new VitisError(1, 'The user ' . $_SESSION["ses_Login"] . ' does not exist');
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                writeToErrorLog('ERROR : The user ' . $_SESSION["ses_Login"] . ' does not exist.');
+            } else {
+                $this->aFields['token'] = $this->aValues['token'];
+                $this->aFields['user'] = $oConnection->aValues['login'];
+                $this->aFields['user_id'] = $_SESSION['ses_user_id'];
+                $this->aFields['validity_date'] = $oConnection->aValues['validity_date'];
+                $this->aFields['privileges'] = $oConnection->aPrivileges;
+                if ($this->aValues['output'] === 'application/xml') {
+                    $this->aFields['privileges'] = implode(',', $this->aFields['privileges']);
+                }
+                $sLogString = "connection" . $this->aProperties["log_delim"] . $_SESSION["ses_Login"] . $this->aProperties["log_delim"] . session_id();
+                writeToLog($sLogString, $this->aProperties["connexion_log_file"]);
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+
+                // Écrit dans la variable de session
+                $oBd = $oConnection->oBd;
+                $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
+                $oPDOresult = $oBd->executeWithParams($aSql['checkIP'], $aParams);
+                $aFields = $oBd->ligneSuivante($oPDOresult);
+                $_SESSION["ses_user_id"] = $aFields['user_id'];
+                $_SESSION["ses_restriction"] = $aFields['restriction'];
+            }
+        }
+        return $sMessage;
+    }
+
+}
+
+?>
diff --git a/vas/rest/ws/vitis/Privilege.class.inc b/vas/rest/ws/vitis/Privilege.class.inc
new file mode 100755
index 00000000..7d97f640
--- /dev/null
+++ b/vas/rest/ws/vitis/Privilege.class.inc
@@ -0,0 +1,115 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Privilege.class.inc
+ * \class Privilege
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Privilege php class
+ *
+ * This class defines operation for one Privilege
+ * 
+ */
+class Privilege extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("rolname", "description", "type", "users");
+    }
+
+    /**
+     * @SWG\Get(path="/privileges/{rolname}", 
+     *   tags={"Privileges"},
+     *   summary="Get Privilege",
+     *   description="Request to get Privilege by rolname",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="rolname",
+     *     in="path",
+     *     description="rolname",
+     *     required=true,
+     *     type="string",
+     *   ),
+     *   @SWG\Parameter(
+     *     name="description",
+     *     in="query",
+     *     description="description of privilege",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="users",
+     *     in="query",
+     *     description="Users of the privilege",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/privileges")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "privileges", "rolname");
+        $this->getUsers();
+    }
+
+    /**
+     *  get users of privilege
+     */
+    function getUsers() {
+        require $this->sRessourcesFile;
+        if (in_array("users", $this->aSelectedFields)) {
+            $excludeLogin = '';
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['vitis_user'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'string');
+            $aParams['excludeLogin'] = array('value' => $excludeLogin, 'type' => 'string');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getUsersPrivileges'], $aParams);
+            $sListUserId = "";
+            $aListUserName = array();
+            while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                if ($sListUserId == "") {
+                    $sListUserId = $aLigne["user_id"];
+                } else {
+                    $sListUserId .= "|" . $aLigne["user_id"];
+                }
+                $aListUserName[] = $aLigne["login"];
+            }
+            $oPDOresult = $this->oConnection->oBd->fermeResultat();
+            $this->aFields['users'] = $sListUserId;
+            $this->aFields['users_label'] = implode(',', $aListUserName);
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Privileges.class.inc b/vas/rest/ws/vitis/Privileges.class.inc
new file mode 100755
index 00000000..2c408ff4
--- /dev/null
+++ b/vas/rest/ws/vitis/Privileges.class.inc
@@ -0,0 +1,280 @@
+<?php
+
+/**
+ * \file Privileges.class.inc
+ * \class Privileges
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis Privileges
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Privilege.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Privileges extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/privileges",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/privileges")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Privileges",
+     *   description="Operations about Privileges"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("rolname", "description", "type", "users");
+    }
+
+    /**
+     * @SWG\Get(path="/privileges",
+     *   tags={"Privileges"},
+     *   summary="Get Privileges",
+     *   description="Request to get Privileges",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="privilege token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/privileges")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Privileges
+     * @return  Privileges
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "privileges", "rolname");
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * @SWG\Put(path="/privileges/{rolname}",
+     *   tags={"Privileges"},
+     *   summary="Update Privilege",
+     *   description="Request to update Privilege",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="privilege token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="rolname",
+     *     in="path",
+     *     description="id of the privilege",
+     *     required=true,
+     *     type="string",
+     *   ),
+     * * @SWG\Parameter(
+     *     name="description",
+     *     in="query",
+     *     description="description of the privilege",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="users",
+     *     in="query",
+     *     description="Users of the privilege",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/privileges")
+     *     )
+     *  )
+     */
+
+    /**
+     * update privilege
+     * @return id of the privilege if ok error object if ko
+     */
+    function PUT() {
+        require $this->sRessourcesFile;
+        // id = string.
+        $iId = $this->aValues['my_vitis_id'];
+
+        $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'privileges', 'rolname');
+        // $this->aValues['my_vitis_id'] = "'" . $this->aValues['my_vitis_id'] . "'";
+        if ($this->oConnection->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        } else {
+            // Le paramètre "users" est passé dans la requête ?
+            if ($this->aValues['users'] !== NULL) {
+                $excludeLogin = '';
+                if ($this->aValues['my_vitis_id'] == 'vitis_admin' || $this->aValues['my_vitis_id'] == 'vitis_user')
+                    $excludeLogin = $_SESSION['ses_Login'];
+
+                //Chargement des utilisateurs qui ne sont pas dans le groupe
+                $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                $aParams['sId'] = array('value' => $iId, 'type' => 'string');
+                $aParams['excludeLogin'] = array('value' => $excludeLogin, 'type' => 'string');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getUsename'], $aParams);
+                $aUsers = $this->oConnection->oBd->getResultTableAssoc($oPDOresult);
+                if ($this->oConnection->oBd->enErreur()) {
+                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                } else {
+                    // Revoke sur tous les utilisateurs le privilège.
+                    for ($i = 0; $i < count($aUsers); $i++) {
+                        $aParams = array();
+                        $aParams['sValue'] = array('value' => $aUsers[$i]["usename"], 'type' => 'double_quote');
+                        $aParams['sId'] = array('value' => $iId, 'type' => 'double_quote');
+                        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['revokePrivilege'], $aParams);
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            return $sMessage;
+                        } else {
+                            if ($iId == 'vitis_admin') {
+                                $aParams = array();
+                                $aParams['sValue'] = array('value' => $aUsers[$i]["usename"], 'type' => 'double_quote');
+                                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['revokeCREATEROLE'], $aParams);
+                                if ($this->oConnection->oBd->enErreur()) {
+                                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                                    $aXmlRacineAttribute['status'] = 0;
+                                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                                    return $sMessage;
+                                }
+                            }
+                        }
+                    }
+                    // Utilisateurs à associer au privilège ?
+                    if (!empty($this->aValues['users'])) {
+                        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                        $aParams['user_id'] = array('value' => $this->aValues['users'], 'type' => 'group');
+                        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getUsers'], $aParams);
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            return $sMessage;
+                        } else {
+                            // Grant sur tous les utilisateurs sélectionnés.
+                            $aUsers = $this->oConnection->oBd->getResultTableAssoc($oPDOresult);
+                            for ($i = 0; $i < count($aUsers); $i++) {
+                                $aParams = array();
+                                $aParams['sValue'] = array('value' => $aUsers[$i]["login"], 'type' => 'double_quote');
+                                $aParams['sId'] = array('value' => $iId, 'type' => 'double_quote');
+                                $this->oConnection->oBd->executeWithParams($aSql['grantPrivilege'], $aParams);
+                                if ($this->oConnection->oBd->enErreur()) {
+                                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                                    $aXmlRacineAttribute['status'] = 0;
+                                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                                    return $sMessage;
+                                } else {
+                                    if ($iId == 'vitis_admin') {
+                                        $aParams = array();
+                                        $aParams['sValue'] = array('value' => $aUsers[$i]["login"], 'type' => 'double_quote');
+                                        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['grantCREATEROLE'], $aParams);
+                                        if ($this->oConnection->oBd->enErreur()) {
+                                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                                            $aXmlRacineAttribute['status'] = 0;
+                                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                                            return $sMessage;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        $aXmlRacineAttribute['status'] = 1;
+        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        return $sMessage;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Properties.class.inc b/vas/rest/ws/vitis/Properties.class.inc
new file mode 100755
index 00000000..d363c986
--- /dev/null
+++ b/vas/rest/ws/vitis/Properties.class.inc
@@ -0,0 +1,427 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+//require_once 'Domain.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+/**
+ * \file properties.class.inc
+ * \class Properties
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Properties php class
+ *
+ * This class defines the rest api for properties
+ * 
+ */
+class Properties extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/properties",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/properties")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Properties",
+     *   description="Operations about properties"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+
+        $this->aSelectedFields = Array("services_alias", 'language', 'domain.*', 'vas_home', 'database', 'sign_up', 'password_forgotten', 'login_remember_me', 'login_remember_me_default');
+
+        // Properties accessibles
+        if (in_array('vitis_admin', $this->oConnection->aPrivileges)) {
+            $this->aSelectedFields = array_merge($this->aSelectedFields, $properties['aAdminFields']);
+        }
+        if (in_array('vitis_user', $this->oConnection->aPrivileges)) {
+            $this->aSelectedFields = array_merge($this->aSelectedFields, $properties['aUserFields']);
+        }
+    }
+
+    /**
+     * @SWG\Get(path="/properties", 
+     *   tags={"Properties"},
+     *   summary="Get properties",
+     *   description="Request to get properties",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *  @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/properties")
+     *     )
+     *  )
+     */
+
+    /**
+     * 
+     * @return properties
+     */
+    function GET() {
+
+        if (isset($this->aSelectedFields) && !empty($this->aSelectedFields)) {
+            $this->aFields = $this->getSelectedFields($this->aProperties);
+        } else {
+            $this->aFields = $this->aProperties;
+        }
+        require_once __DIR__ . "/../../conf/version.inc";
+
+        if (VM_STATUS != "STABLE") {
+            $this->aFields['VM_STATUS'] = "UNSTABLE";
+        } else {
+            $this->aFields['VM_STATUS'] = "STABLE";
+            if ($pointeur = opendir(__DIR__ . "/../../conf/")) {
+                while (($fichier = readdir($pointeur)) !== false) {
+
+                    if (($fichier != '.') && ($fichier != '..')) {
+
+                        if (is_dir(__DIR__ . "/../../conf/" . $fichier)) {
+                            $sTexte = file_get_contents(__DIR__ . "/../../conf/" . $fichier . "/version.inc");
+
+                            if (strpos($sTexte, "define (\"VM_STATUS\", \"STABLE\");") == false) {
+                                $this->aFields['VM_STATUS'] = "UNSTABLE";
+                            }
+                        }
+                    }
+                }
+                //fermeture du pointeur
+                closedir($pointeur);
+            }
+            //pour chaque fichier et dossier
+        }
+        $aXmlRacineAttribute['status'] = 1;
+        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        return $sMessage;
+    }
+
+    /**
+     * Returns the properties to display
+     * @param arrya $aProperties
+     * @return array
+     */
+    function getSelectedFields($aProperties) {
+        $aFields = Array();
+        foreach ($aProperties as $key => $value) {
+            if (is_array($aProperties[$key])) {
+                foreach ($this->aSelectedFields as $sSelectedField) {
+                    if (strpos($sSelectedField, '.')) {
+                        $aSubSelectedFields = explode('.', $sSelectedField);
+                        if ($aSubSelectedFields[0] === $key) {
+                            if ($aSubSelectedFields[1] === '*') {
+                                $aFields[$key] = $aProperties[$key];
+                            } else {
+                                if (!array_key_exists($key, $aFields)) {
+                                    $aFields[$key] = array();
+                                }
+                                if (!array_key_exists($aSubSelectedFields[1], $aFields[$key])) {
+                                    $aFields[$key][$aSubSelectedFields[1]] = array();
+                                }
+                                $aFields[$key][$aSubSelectedFields[1]] = $this->recursiveGetSubSelectedFields($aProperties[$key], $aSubSelectedFields, $aFields[$key], 1);
+                            }
+                        }
+                    }
+                }
+            } else {
+                if (in_array($key, $this->aSelectedFields)) {
+                    $aFields[$key] = $aProperties[$key];
+                }
+            }
+        }
+        return $aFields;
+    }
+
+    /**
+     * Recursive function called by getSelectedFields that returns the sub-selected fields
+     * @param array $aSubProperties
+     * @param array $aSubSelectedFields
+     * @param array $aField
+     * @param number $index
+     * @return array|string
+     */
+    function recursiveGetSubSelectedFields($aSubProperties, $aSubSelectedFields, $aField, $index) {
+        if (isset($aSubProperties[$aSubSelectedFields[$index]]) && !empty($aSubProperties[$aSubSelectedFields[$index]])) {
+            if (empty($aSubSelectedFields[$index + 1])) {
+                $aSubSelectedFields[$index + 1] = "";
+            }
+            if ($aSubSelectedFields[$index + 1] === '*') {
+                $aField[$aSubSelectedFields[$index]] = $aSubProperties[$aSubSelectedFields[$index]];
+            } else {
+                if (is_array($aSubProperties[$aSubSelectedFields[$index]])) {
+                    foreach ($aSubProperties[$aSubSelectedFields[$index]] as $key => $value) {
+                        if ($key === $aSubSelectedFields[$index + 1]) {
+                            if (!empty($aSubProperties[$aSubSelectedFields[$index]][$aSubSelectedFields[$index + 1]])) {
+                                if (!array_key_exists($aSubSelectedFields[$index], $aField)) {
+                                    $aField[$aSubSelectedFields[$index]] = array();
+                                }
+                                $aField[$aSubSelectedFields[$index]][$key] = $this->recursiveGetSubSelectedFields($aSubProperties[$aSubSelectedFields[$index]], $aSubSelectedFields, $aField[$aSubSelectedFields[$index]], $index + 1);
+                            }
+                        }
+                    }
+                    if (empty($aField[$aSubSelectedFields[$index]])) {
+                        $aField[$aSubSelectedFields[$index]] = null;
+                    }
+                } else {
+                    $aField[$aSubSelectedFields[$index]] = $aSubProperties[$aSubSelectedFields[$index]];
+                }
+            }
+        }
+
+        return $aField[$aSubSelectedFields[$index]];
+    }
+
+    /**
+     * @SWG\Put(path="/properties/{module_name}",
+     *   tags={"Properties"},
+     *   summary="Update properties",
+     *   description="Request to update the properties",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="module_name",
+     *     in="path",
+     *     description="module name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/properties")
+     *     ),
+     * 
+     *  )
+     */
+
+    /**
+     * Update properties
+     */
+    function PUT() {
+        // Verify connection.
+        if (!empty($this->oConnection->oError)) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        // Privilège "vitis_admin" requis.
+        if (!in_array('vitis_admin', $this->oConnection->aPrivileges)) {
+            $oError = new VitisError(1, "Rights problem : you don't have right to delete log files");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        if (!empty($this->aValues["properties"])) {
+            // Répertoire partagé par défaut si non spécifié.
+            if (empty($this->aValues["properties"]->shared_dir))
+                $this->aValues["properties"]->shared_dir = $this->aProperties['vas_home'] . '/shared';
+            // Paramètres pour le fichier de 'properties'
+            define('PROPERTIES_HEADER', 'require "constants.inc";' . PHP_EOL . 'require "properties_server.inc";' . PHP_EOL . 'require "properties_domain.inc";' . PHP_EOL . 'require "selected_properties.inc";');
+            define('PROPERTIES_FOOTER', PHP_EOL . PHP_EOL
+                    . '// Require tous les fichiers de tous les dossiers contenus sans properties' . PHP_EOL
+                    . '$aDir = scandir(__DIR__);' . PHP_EOL
+                    . 'foreach ($aDir as $dir) {' . PHP_EOL
+                    . '	if($dir != \'.\' && $dir != \'..\'){' . PHP_EOL
+                    . '		if(is_dir(__DIR__.\'/\'.$dir)){' . PHP_EOL
+                    . '			$aFiles = scandir(__DIR__.\'/\'.$dir);' . PHP_EOL
+                    . '			foreach ($aFiles as $file) {' . PHP_EOL
+                    . '				if((filetype(__DIR__.\'/\'.$dir.\'/\'.$file) == \'file\') && (pathinfo(__DIR__.\'/\'.$dir.\'/\'.$file)[\'extension\']) == \'inc\' && $file != "version.inc"){' . PHP_EOL
+                    . '					require_once __DIR__.\'/\'.$dir.\'/\'.$file;' . PHP_EOL
+                    . '				}' . PHP_EOL
+                    . '			}' . PHP_EOL
+                    . '		}' . PHP_EOL
+                    . '	}' . PHP_EOL
+                    . '}' . PHP_EOL
+                    . PHP_EOL . 'require "properties_post.inc";' . PHP_EOL . 'include "php_conf.inc";');
+            define('PROPERTIES_TEMPLATE', '$properties[\'[key]\'] = [value];'); // Modèle pour chaque ligne du fichier
+            define('PHP_START', '<?php'); // Début du php
+            define('PHP_END', '?>'); // Fin du php
+            define('ARRAY_DECLARATION_TEMPLATE', 'array([value])'); // Modèle de la déclaration d'un tableau
+            define('ARRAY_CONTENT_TEMPLATE', '[key] => [value]'); // Modèle du contenu d'un tableau
+            define('ARRAY_VALUE_SEPARATOR', ', '); // Caractère séparant les valeurs d'un tableau
+            define('STR_CH_ENCLOSE', '\''); // Caractère entourant les valeurs de type 'string'
+            define('NUMERIC_ENCLOSE', false); // Entoure avec des simples/doubles quotes les valeurs numérique comme les chaines de caractères ?
+            define('REQUEST_SUCCESS', 0);
+            define('REQUEST_ERROR', 1);
+
+            $aReturn = $this->writeProperties($this->aValues["properties"]);
+        }
+        //
+        $aXmlRacineAttribute['status'] = $aReturn['status'];
+        if ($aReturn['status'] == 1)
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        else {
+            $oError = new VitisError($aReturn['error_code'], $aReturn['message']);
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+
+    /*     * ********************************
+      Ecrase le fichier des properties avec le
+      contenu des paramètres du formulaire
+      $aPropertiesForm : tableau contenant la liste des clés/valeurs à écrire dans le fichier de properties
+      $aPropertiesExclude : tableau contenant des champs du formulaire à exclure pour l'écriture du fichier de properties
+     * ********************************* */
+
+    function writeProperties($aPropertiesForm, $aPropertiesExclude = array()) {
+        $aReturn = array('status' => 1, 'message' => '');
+        // Vérifie que le formulaire de properties n'est pas vide
+        if (!empty($aPropertiesForm)) {
+
+            // Message de retour
+            $aMessage = array('status' => REQUEST_SUCCESS);
+
+            // Ouverture de php	
+            $sPropertiesFile = PHP_START . PHP_EOL;
+
+            // Texte à ajouter avant le tableau des properties
+            if ($this->aValues['module_name'] == 'vitis')
+                $sPropertiesFile .= PROPERTIES_HEADER . PHP_EOL;
+
+            // Convertit chaque valeur du tableau 'properties' en ligne de code php
+            foreach ($aPropertiesForm as $sKey => $v) {
+                // La valeur n'est pas à exclure ?
+                if (!in_array($sKey, $aPropertiesExclude)) {
+                    // Formate la valeur suivant le type
+                    if (is_array($v))
+                        $v = $this->exportArray($v);
+                    else {
+                        // Booléen ?
+                        if ($v == 'true')
+                            $v = true;
+                        else if ($v == 'false')
+                            $v = false;
+
+                        $v = $this->formatValue($v);
+                    }
+
+                    // Exception pour 'max_upload_file_size' : conversion en octets
+                    if ($sKey == 'max_upload_file_size')
+                        $v .= ' * 1024 * 1024';
+
+                    // Remplit la clé, la valeur et le retour à la ligne
+                    $sKey = str_replace('.', "']['", $sKey);
+                    $sPropertiesLine = str_replace('[key]', $sKey, PROPERTIES_TEMPLATE);
+                    $sPropertiesLine = str_replace('[value]', $v, $sPropertiesLine);
+                    $sPropertiesLine .= PHP_EOL;
+
+                    // Ajoute la nouvelle ligne
+                    $sPropertiesFile .= $sPropertiesLine;
+                }
+            }
+
+            // Texte à ajouter après le tableau des properties
+            if ($this->aValues['module_name'] == 'vitis') {
+                $sPropertiesFile .= PROPERTIES_FOOTER . PHP_EOL;
+            }
+
+            // Fermeture de php	
+            $sPropertiesFile .= PHP_END;
+
+            // Sauve le fichier (LOCK_EX = accés exclusif au fichier)
+            if ($this->aValues['module_name'] == 'vitis')
+                $sPathProperties = __DIR__ . '/../../conf/properties.inc';
+            else
+                $sPathProperties = __DIR__ . '/../../conf/' . $this->aValues['module_name'] . '/properties.inc';
+            //
+            if (file_put_contents($sPathProperties, $sPropertiesFile, LOCK_EX) === false)
+                $aReturn = array('status' => 0, 'message' => "FORM_ERROR_FILE_WRITING_CONFIGURATION");
+        }
+        //else
+        //$aReturn = array('status' => 0, 'message' => "Le formulaire de properties passé en paramètre est vide");
+        // Retourne le tableau contenant le message
+        return $aReturn;
+    }
+
+    /*     * ********************************
+      Retourne la déclaration d'un tableau en php
+      (fonction récursive pour les tableaux multi-dimmensions)
+      $aArray : le tableau à retourner
+     * ********************************* */
+
+    function exportArray($aArray) {
+        $sMyArray = '';
+        foreach ($aArray as $sKey => $v) {
+            // Pas la 1ere valeur du tableau ?
+            if ($sMyArray != '')
+                $sMyArray .= ARRAY_VALUE_SEPARATOR;
+
+            // Ajoute la clé du tableau
+            if (is_int($sKey))
+                $sMyArray .= str_replace('[key]', $sKey, ARRAY_CONTENT_TEMPLATE);
+            else
+                $sMyArray .= str_replace('[key]', (STR_CH_ENCLOSE . $sKey . STR_CH_ENCLOSE), ARRAY_CONTENT_TEMPLATE);
+
+            // Si la valeur est un tableau : récursif
+            if (is_array($v))
+                $v = exportArray($v);
+            else
+                $v = $this->formatValue($v);
+
+            // Ajoute la valeur du tableau
+            $sMyArray = str_replace('[value]', $v, $sMyArray);
+        }
+
+        // Ajoute la valeur du tableau
+        $sMyArray = str_replace('[value]', $sMyArray, ARRAY_DECLARATION_TEMPLATE);
+        return $sMyArray;
+    }
+
+    /*     * ********************************
+      Retourne une valeur formatée suivant le type (str, nombre, bool...)
+      $MyValue : Valeur du tableau à formater
+     * ********************************* */
+
+    function formatValue($MyValue) {
+        // Type numérique ?	--> pour les nombres qui sont entre 'quotes'
+        if (is_numeric($MyValue)) {
+            if (is_int($MyValue)) {
+                $MyValue = (int) $MyValue; // Force en entier
+            } else if (is_float($MyValue)) {
+                $MyValue = (float) $MyValue; // Force en décimal
+            }
+            // Transforme les valeur numériques	en chaine de caractères ?
+            if (NUMERIC_ENCLOSE) {
+                $MyValue = STR_CH_ENCLOSE . addslashes($MyValue) . STR_CH_ENCLOSE;
+            }
+        }
+        // Une chaine de caractère ?
+        else if (is_string($MyValue))
+            $MyValue = STR_CH_ENCLOSE . addslashes($MyValue) . STR_CH_ENCLOSE;
+        else
+            $MyValue = var_export($MyValue, true);
+
+        return $MyValue;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/PublicToken.class.inc b/vas/rest/ws/vitis/PublicToken.class.inc
new file mode 100755
index 00000000..332c094f
--- /dev/null
+++ b/vas/rest/ws/vitis/PublicToken.class.inc
@@ -0,0 +1,105 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once("inc/MetadataAccess.class.inc");
+
+/**
+ * \file PublicToken.class.inc
+ * \class PublicToken
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the PublicToken php class
+ *
+ * This class defines Rest Api to public token
+ */
+class PublicToken extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/publictoken",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/publictoken")
+     *   },
+     * )
+     *  @SWG\Tag(
+     *   name="Token",
+     *   description="Operations about token"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+    }
+
+    /**
+     * @SWG\Get(path="/publictoken", 
+     *   tags={"Token"},
+     *   summary="Get public token",
+     *   description="Request to get a token",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Token Response",
+     *         @SWG\Schema(ref="#/definitions/publictoken")
+     *     )
+     *  )
+     */
+
+    /**
+     * Method get to get a public token
+     * @return user array
+     */
+    function GET() {
+        session_name(md5(uniqid('', true)));
+        session_start();
+        require_once $this->sRessourcesFile;
+        //define the session
+        session_id($this->aProperties['public_token']);
+        $this->aValues["user"] = $this->aProperties['public_login'];
+        $this->aValues["password"] = $this->aProperties['public_password'];
+        $oBd = new BD($this->aValues["user"], $this->aValues["password"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"], $this->aProperties["page_encoding"]);
+        $_SESSION["ses_Login"] = $this->aValues["user"];
+        $ciphertext = stringToHex(des($this->aValues["user"], $this->aValues["password"], 1, 0));
+        $_SESSION["ses_Password"] = $ciphertext;
+        $_SESSION["ses_Remember"] = false;
+        if ($oBd->erreurRencontree) {
+            $oError = new VitisError(1, $oBd->sMessage);
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            //verify if the ip from wich the user connect is allowed
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
+            $oPDOresult = $oBd->executeWithParams($aSql['checkIP'], $aParams);
+            $aFields = $oBd->ligneSuivante($oPDOresult);
+            $oMetadataAccess = new MetadataAccess($oBd, $_SESSION["ses_Login"], $_SESSION["ses_Password"], session_id(), $this->aProperties);
+            $bAuthorizedIp = $oMetadataAccess->checkUserIp($_SERVER['REMOTE_ADDR']);
+            if (!$bAuthorizedIp) {
+                $oError = new VitisError(11, 'Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            } else {
+                //if no error return the token
+                $this->aFields['token'] = session_id();
+                $this->aFields['validity_date'] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        }
+        return $sMessage;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Ressources.class.inc b/vas/rest/ws/vitis/Ressources.class.inc
new file mode 100755
index 00000000..0beb40ec
--- /dev/null
+++ b/vas/rest/ws/vitis/Ressources.class.inc
@@ -0,0 +1,140 @@
+<?php
+
+/**
+ * \file Ressources.class.inc
+ * \class Ressources
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Ressources php class
+ *
+ * This class defines Rest Api to Vitis Ressources
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Ressources extends Vitis {
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("ressource_id", "module", "name", "description", "fields", "columns", "objects", "actions");
+    }
+
+    /**
+     * get Columns
+     * @return Columns
+     */
+    function GET() {
+        require("../doc/vendor/autoload.php");
+
+
+        if (isset($this->aPath[2]) && isset($this->aPath[3])) {
+            $this->aValues['ressource_id'] = $this->aPath[2] . '/' . $this->aPath[3];
+            $this->getData($this->aPath[2]);
+        } else {
+            if (is_dir("./ws")) {
+                $aDir = scandir("./ws");
+                foreach ($aDir as $sDir) {
+                    if ($sDir != "." && $sDir != "..") {
+                        $this->getData($sDir);
+                    }
+                }
+            } else
+                writeToErrorLog('scandir(./ws): failed to open dir');
+        }
+
+        $aXmlRacineAttribute['status'] = 1;
+        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        return $sMessage;
+    }
+
+    function getData($sDir) {
+        if (isset($this->aValues['attributs'])) {
+            $aAttributs = explode("|", $this->aValues['attributs']);
+            $aFields = array_intersect($aAttributs, $this->aSelectedFields);
+        } else {
+            $aFields = $this->aSelectedFields;
+        }
+
+        $swagger = \Swagger\scan('./ws/' . $sDir);
+        $aServer = explode("://", $this->aProperties["web_server_name"]);
+        $swagger = str_replace("[service_alias]", $this->aProperties["services_alias"], $swagger);
+        $swagger = str_replace("[protocol]", $aServer[0], $swagger);
+        $swagger = str_replace("[server]", $aServer[1], $swagger);
+        $oJson = json_decode($swagger);
+        foreach ($oJson->tags as $value) {
+            if (strtolower($this->aValues['ressource_id']) == strtolower($sDir . "/" . $value->name) || !isset($this->aValues['ressource_id'])) {
+                if (file_exists("./ws/" . $sDir . "/" . $value->name . ".class.inc")) {
+                    require_once("./ws/" . $sDir . "/" . $value->name . ".class.inc");
+                    $sClassName = $value->name;
+                    $sClass = new $sClassName($this->aPath, $this->aValues, $this->aProperties);
+                    if (in_array("ressource_id", $aFields)) {
+                        $sClass->aFields["ressource_id"] = strtolower($sDir . "/" . $value->name);
+                    }
+                    if (in_array("module", $aFields)) {
+                        $sClass->aFields["module"] = $sDir;
+                    }
+                    if (in_array("name", $aFields)) {
+                        $sClass->aFields["name"] = $value->name;
+                    }
+                    if (in_array("description", $aFields)) {
+                        $sClass->aFields["description"] = $value->description;
+                    }
+                    if (in_array("fields", $aFields)) {
+                        $sClass->aFields["fields"] = "";
+                        foreach ($sClass->aSelectedFields as $sFields) {
+                            if (strpos($sFields, " as ")) {
+                                $field = explode(" as ", $sFields)[1];
+                            } else {
+                                $field = $sFields;
+                            }
+                            if ($sClass->aFields["fields"] == "") {
+                                $sClass->aFields["fields"] = $field;
+                            } else {
+                                $sClass->aFields["fields"] .= ", " . $field;
+                            }
+                        }
+                    }
+                    if (in_array("columns", $aFields)) {
+                        require_once 'Columns.class.inc';
+                        $this->aValues["ressource_id"] = $sClass->aFields["ressource_id"];
+                        $this->aValues["module"] = $sDir;
+                        $oColumn = new Columns($this->aPath, $this->aValues, $this->aProperties, false);
+                        $oColumn->GET();
+                        array_push($sClass->aObjects, $oColumn);
+                    }
+                    if (in_array("actions", $aFields)) {
+                        require_once 'Actions.class.inc';
+                        $this->aValues["ressource_id"] = $sClass->aFields["ressource_id"];
+                        $this->aValues["module"] = $sDir;
+                        $oActions = new Actions($this->aPath, $this->aValues, $this->aProperties, false);
+                        $oActions->GET();
+                        array_push($sClass->aObjects, $oActions);
+                    }
+                    if (in_array("objects", $aFields)) {
+                        require_once'Tabs.class.inc';
+                        $aValues = array("filter" => '{"relation": "AND","operators":[{"column": "ressource_id","compare_operator": "=","value": "' . $sClass->aFields["ressource_id"] . '"}, {"column": "lang","compare_operator": "=","value": "' . $this->aProperties["language"] . '"}]}', "token" => $this->aValues['token'], 'order_by' => 'index');
+                        $oTabs = new Tabs($this->aPath, $aValues, $this->aProperties);
+                        $oTabs->GET();
+                        array_push($sClass->aObjects, $oTabs);
+                    }
+                    array_push($this->aObjects, $sClass);
+                    unset($oObject);
+                }
+            }
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Schema.class.inc b/vas/rest/ws/vitis/Schema.class.inc
new file mode 100755
index 00000000..9124b4a5
--- /dev/null
+++ b/vas/rest/ws/vitis/Schema.class.inc
@@ -0,0 +1,34 @@
+<?php
+
+require_once 'Vitis.class.inc';
+
+/**
+ * \file Action.class.inc
+ * \class Action
+ *
+ * \author Armand Bahi
+ *
+ * 	\brief This file contains the Action php class
+ *
+ * This class defines operation for one Action
+ * 
+ */
+class Schema extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aSchema) {
+        $this->aFields = $aSchema;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/SmtpServer.class.inc b/vas/rest/ws/vitis/SmtpServer.class.inc
new file mode 100755
index 00000000..f49c20fb
--- /dev/null
+++ b/vas/rest/ws/vitis/SmtpServer.class.inc
@@ -0,0 +1,123 @@
+<?php
+
+/**
+ * \file SmtpServer.class.inc
+ * \class SmtpServer
+ *
+ * \author Armand Bahi <armand.bahi@veremes.com>.
+ *
+ * \brief This file contains the SmtpServer php class
+ *
+ * This class defines Rest Api to SmtpServer
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\Exception;
+require_once 'PHPMailer/src/Exception.php';
+require_once 'PHPMailer/src/PHPMailer.php';
+require_once 'PHPMailer/src/SMTP.php';
+
+class SmtpServer extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/smtpserver",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/smtpserver")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="SmtpServer",
+     *   description="SMTP test Class"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+    }
+
+    /**
+     * @SWG\Get(path="/smtpserver/Check",
+     *   tags={"SmtpServer"},
+ *   summary="Check smtp server connection",
+     *   description="Request to check the connection to the Smtp Server",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/smtpserver")
+     *     )
+     *  )
+     */
+
+    /**
+     * get SmtpServer
+     * @return  SmtpServer
+     */
+    function GET() {
+        if (!empty($this->aPath[2])) {
+            if ($this->aPath[2] == "Check")
+                $sMessage = $this->checkSmtpServerConnection();
+            return $sMessage;
+        }
+    }
+
+    /**
+     * Retourne les symboles du fichier "symbols.sym".
+     */
+    function checkSmtpServerConnection() {
+        $mail = new PHPMailer;
+        $mail->isSMTP();                                                // Set mailer to use SMTP
+        //$mail->SMTPDebug = 3;                                         // debugger level (3 all with connection)
+        $mail->Debugoutput = function($str, $level) {error_log("debug level $level; message: $str");};
+        $mail->Host = $this->aProperties["smtp_host"];                  // Specify main and backup SMTP servers
+        $mail->Port = $this->aProperties["smtp_port"];                  // TCP port to connect to
+        $mail->SMTPAuth = $this->aProperties["smtp_authentification"];  // Enable SMTP authentication
+        // if authentication add parameter to connect SMTP
+        if ($this->aProperties["smtp_authentification"] === true){
+            $mail->AuthType = 'LOGIN';
+            $mail->Username = $this->aProperties["smtp_login"];             // SMTP username
+            $mail->Password = $this->aProperties["smtp_password"];          // SMTP password
+            $mail->SMTPSecure = 'tls';                                      // Enable TLS encryption, `ssl` also accepted (deprecated)
+        }
+        // Depuis PHP 5.6 -> vérification du certificat SSL.
+        if (!$this->aProperties['proxy_check_ssl']) {
+            $mail->SMTPOptions = array(
+                'ssl' => array(
+                    'verify_peer' => false,
+                    'verify_peer_name' => false,
+                    'allow_self_signed' => true
+                )
+            );
+        }
+        if ($mail->smtpConnect()) {
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        else {
+            $oError = new VitisError(1, 'MODAL_CONTENT_ERROR_CHECK_SMTP_CONNECTION_CONFIGURATION');
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Tab.class.inc b/vas/rest/ws/vitis/Tab.class.inc
new file mode 100755
index 00000000..aa41796b
--- /dev/null
+++ b/vas/rest/ws/vitis/Tab.class.inc
@@ -0,0 +1,80 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file Tab.class.inc
+ * \class Tab
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Tab php class
+ *
+ * This class defines operation for one Tab
+ * 
+ */
+class Tab extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("label", "event", "tab_id", "mode_id", "index", "lang", "ressource_id", "show_column", "edit_column", "sorted_by", "sorted_dir", "name");
+    }
+
+    /**
+     * @SWG\Get(path="/tabs/{tab_id}", 
+     *   tags={"Tabs"},
+     *   summary="Get Tab",
+     *   description="Request to get Tab by mode id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="tab_id",
+     *     in="path",
+     *     description="tab id",
+     *     required=true,
+     *     type="string",
+     *   ),
+     *   @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/tabs")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about table tabs
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "v_tab", "tab_id");
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Table.class.inc b/vas/rest/ws/vitis/Table.class.inc
new file mode 100755
index 00000000..5ec19316
--- /dev/null
+++ b/vas/rest/ws/vitis/Table.class.inc
@@ -0,0 +1,34 @@
+<?php
+
+require_once 'Vitis.class.inc';
+
+/**
+ * \file Action.class.inc
+ * \class Action
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Action php class
+ *
+ * This class defines operation for one Action
+ * 
+ */
+class Table extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aTable) {
+        $this->aFields = $aTable;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Tabs.class.inc b/vas/rest/ws/vitis/Tabs.class.inc
new file mode 100755
index 00000000..8208915e
--- /dev/null
+++ b/vas/rest/ws/vitis/Tabs.class.inc
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * \file Tabs.class.inc
+ * \class Tabs
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Tabs php class
+ *
+ * This class defines Rest Api to Vitis tabs
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Tab.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Tabs extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/Tabs",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/Tabs")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Tabs",
+     *   description="Operations about Tabs"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("label", "event", "tab_id", "mode_id", "index", "lang", "ressource_id", "show_column", "edit_column", "sorted_by", "sorted_dir", "name");
+    }
+
+    /**
+     * @SWG\Get(path="/tabs",
+     *   tags={"Tabs"},
+     *   summary="Get Tabs",
+     *   description="Request to get Tabs",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Tabs
+     * @return Tabs
+     */
+    function GET() { // getTabs
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_tab", "tab_id");
+        return $aReturn['sMessage'];
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/TimeZone.class.inc b/vas/rest/ws/vitis/TimeZone.class.inc
new file mode 100755
index 00000000..fadd7760
--- /dev/null
+++ b/vas/rest/ws/vitis/TimeZone.class.inc
@@ -0,0 +1,78 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file TimeZone.class.inc
+ * \class TimeZone
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the TimeZone php class
+ *
+ * This class defines operation for one TimeZone
+ * 
+ */
+class TimeZone extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("name", "abbrev", "utc_offset", 'is_dst', "CONCAT(name, ' ', 'GMT',' ',substr(CASE WHEN (substr(utc_offset::text, 1, 1) = '-') THEN utc_offset::text ELSE CONCAT('+', utc_offset) END::text, 1, 6)) as label");
+    }
+
+    /**
+     * @SWG\Get(path="/timezones/{name}",
+     *   tags={"TimeZones"},
+     *   summary="Get TimeZone",
+     *   description="Request to get TimeZone by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="name",
+     *     in="path",
+     *     description="timezone name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/timezones")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about mode
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields('pg_catalog', 'pg_timezone_names', 'name');
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/TimeZones.class.inc b/vas/rest/ws/vitis/TimeZones.class.inc
new file mode 100755
index 00000000..4dc61036
--- /dev/null
+++ b/vas/rest/ws/vitis/TimeZones.class.inc
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * \file TimeZones.class.inc
+ * \class TimeZones
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Modes php class
+ *
+ * This class defines Rest Api to Vitis TimeZones
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'TimeZone.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class TimeZones extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/timezones",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/timezones")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="TimeZones",
+     *   description="Operations about TimeZones"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("name", "abbrev", "utc_offset", 'is_dst', "CONCAT(name, ' ', 'GMT',' ',substr(CASE WHEN (substr(utc_offset::text, 1, 1) = '-') THEN utc_offset::text ELSE CONCAT('+', utc_offset) END::text, 1, 6)) as label");
+    }
+
+    /**
+     * @SWG\Get(path="/timezones",
+     *   tags={"TimeZones"},
+     *   summary="Get TimeZones",
+     *   description="Request to get TimeZones",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/timezones")
+     *     )
+     *  )
+     */
+
+    /**
+     * get TimeZones
+     * @return  TimeZones
+     */
+    function GET() {
+        $aReturn = $this->genericGet('pg_catalog', 'pg_timezone_names', 'name');
+        return $aReturn['sMessage'];
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/User.class.inc b/vas/rest/ws/vitis/User.class.inc
new file mode 100755
index 00000000..c959df67
--- /dev/null
+++ b/vas/rest/ws/vitis/User.class.inc
@@ -0,0 +1,189 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file User.class.inc
+ * \class User
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the User php class
+ *
+ * This class defines operation for one user
+ * 
+ */
+class User extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("user_id", "login", "email", "name", "company", "department", "ip_constraint", "domain", "domain_id", "restriction", $this->getDateSelectedFields('last_connection', 'yeartosecond'), "groups", "privileges", "role", "restriction", "name || ' (' || login || ')' as user_string", "dataencrypt", 'billinggroup_id', 'billinggroup', "phone", "acceptnotification", 'timezone_id', 'formatdate_id', 'formatdate');
+    }
+
+    /**
+     * @SWG\Get(path="/users/{user_id}", 
+     *   tags={"Users"},
+     *   summary="Get User",
+     *   description="Request to get User by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="user_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *   format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about user
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "v_user", "user_id");
+        $this->getGroups();
+        $this->getPrivileges();
+    }
+
+    /**
+     *  get groups of user
+     */
+    function getGroups() {
+        require $this->sRessourcesFile;
+        if (in_array("groups", $this->aSelectedFields)) {
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['user_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGroups'], $aParams);
+            $sListGroupId = "";
+            $aListGroupName = array();
+            while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                if ($sListGroupId == "") {
+                    $sListGroupId = $aLigne["group_id"];
+                } else {
+                    $sListGroupId .= "|" . $aLigne["group_id"];
+                }
+                $aListGroupName[] = $aLigne["name"];
+            }
+            $oPDOresult = $this->oConnection->oBd->fermeResultat();
+            $this->aFields['groups'] = $sListGroupId;
+            $this->aFields['groups_label'] = implode(',', $aListGroupName);
+        }
+    }
+
+    /**
+     * get privileges of the user
+     */
+    function getPrivileges() {
+        require $this->sRessourcesFile;
+        if (in_array("privileges", $this->aSelectedFields)) {
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['user_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getUserPrivileges'], $aParams);
+            $sListPrivileges = "";
+            while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                if ($sListPrivileges == "") {
+                    $sListPrivileges = $aLigne["groname"];
+                } else {
+                    $sListPrivileges .= "|" . $aLigne["groname"];
+                }
+            }
+            $oPDOresult = $this->oConnection->oBd->fermeResultat();
+            $this->aFields['privileges'] = $sListPrivileges;
+            $this->aFields['privileges_label'] = str_replace('|', ',', $sListPrivileges);
+        }
+    }
+
+    /**
+     * delete an user
+     */
+    function DELETE() {
+        require $this->sRessourcesFile;
+        $sErrorMesssage = '';
+        $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+        $aParams['user_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getLoginbyId'], $aParams);
+        $oUserDeleted = $this->oConnection->oBd->objetSuivant($oPDOresult);
+        if (!$this->oConnection->oBd->enErreur()) {
+            // Liste des privilèges de l'utilisateur présents dans la table s_vitis.privileges.
+            $aParams = array();
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['login'] = array('value' => $oUserDeleted->login, 'type' => 'string');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['userApplicationPrivileges'], $aParams);
+            if ($this->oConnection->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                return $sMessage;
+            } else {
+                if ($oPDOresult->rowCount() > 0) {
+                    $aUserPrivileges = $this->oConnection->oBd->getResultTableAssoc($oPDOresult);
+                    // Revoke sur les privilèges.
+                    foreach ($aUserPrivileges as $aPrivilege) {
+                        $aParams = array();
+                        $aParams['sValue'] = array('value' => $oUserDeleted->login, 'type' => 'double_quote');
+                        $aParams['sId'] = array('value' => $aPrivilege['groname'], 'type' => 'double_quote');
+                        $this->oConnection->oBd->executeWithParams($aSql['revokePrivilege'], $aParams);
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            return $sMessage;
+                        }
+                    }
+                }
+                // Si l'utilisateur n'a plus de privilèges associés -> suppression du rôle de connexion.
+                $aParams = array();
+                $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                $aParams['login'] = array('value' => $oUserDeleted->login, 'type' => 'string');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getAllUserPrivileges'], $aParams);
+                if ($oPDOresult->rowCount() == 0) {
+                    $oSgbdDataAccess = new PgsqlDataAccess($this->oConnection->oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+                    $sErrorMesssage = $oSgbdDataAccess->DeleteDatabaseRole($oUserDeleted->login);
+                }
+                // Supprime l'utilisateur dans la table s_vitis.user.
+                $this->deleteChild($this->aProperties['schema_framework'], 'v_user', 'user_id', "vitis_admin");
+            }
+            if ($sErrorMesssage == "") {
+                $this->aFields["user_id"] = $this->aValues['my_vitis_id'];
+            } else {
+                $this->oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            }
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Users.class.inc b/vas/rest/ws/vitis/Users.class.inc
new file mode 100755
index 00000000..fa87387f
--- /dev/null
+++ b/vas/rest/ws/vitis/Users.class.inc
@@ -0,0 +1,746 @@
+<?php
+
+/**
+ * \file USers.class.inc
+ * \class Users
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Users php class
+ *
+ * This class Rest api for users
+ *
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'User.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Users extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/Users",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/Users")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Users",
+     *   description="Operations about Users"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("user_id", "login", "email", "name", "company", "department", "ip_constraint", "domain", "domain_id", "restriction", $this->getDateSelectedFields('last_connection', 'yeartosecond'), "groups", "privileges", "role", "restriction", "name || ' (' || login || ')' as user_string", "dataencrypt", "phone", "acceptnotification", 'timezone_id', 'formatdate_id', 'formatdate');
+    }
+
+    /**
+     * @SWG\Get(path="/users",
+     *   tags={"Users"},
+     *   summary="Get Users",
+     *   description="Request to get Users",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json",  "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * get users
+     * @return  users
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_user", "user_id");
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * @SWG\Post(path="/users",
+     *   tags={"Users"},
+     *   summary="Add User",
+     *   description="Request to add user",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="login",
+     *     in="formData",
+     *     description="Login of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="action",
+     *     in="formData",
+     *     description="action",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="name",
+     *     in="formData",
+     *     description="Name of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="email",
+     *     in="formData",
+     *     description="Email of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="company",
+     *     in="formData",
+     *     description="Company of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="department",
+     *     in="formData",
+     *     description="Departement of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="groups",
+     *     in="formData",
+     *     description="Groups of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="privileges",
+     *     in="formData",
+     *     description="Privileges of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="ip_constraint",
+     *     in="formData",
+     *     description="Workstation IP address",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="formData",
+     *     description="Password of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password_confirm",
+     *     in="formData",
+     *     description="Password confirmation of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="restriction",
+     *     in="formData",
+     *     description="Password confirmation of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     * )
+     */
+
+    /**
+     * insert user
+     * @return id of the user created
+     */
+    function POST() {
+        //verify the connection
+        if ($this->oConnection->oError != null) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            // Importation d'un utilisateur AD ?
+            if (!empty($this->aValues['action'])) {
+                $sMessage = $this->importLdapUser();
+            }
+            // verify if the user is vitis_admin
+            else if (in_array("vitis_admin", $this->oConnection->aPrivileges)) {
+                // Changement de mot de passe ?
+                require_once $this->sRessourcesFile;
+                $this->aValues["login"] = mb_strtolower($this->aValues["login"], 'UTF-8');
+                $this->aValues["login"] = str_replace(array('à', 'â', 'ä', 'á', 'ã', 'å', 'î', 'ï', 'ì', 'í', 'ô', 'ö', 'ò', 'ó', 'õ', 'ø', 'ù', 'û', 'ü', 'ú', 'é', 'è', 'ê', 'ë', 'ç', 'ÿ', 'ñ'), array('a', 'a', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'e', 'e', 'e', 'e', 'c', 'y', 'n',), $this->aValues["login"]);
+                $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                $aParams['sLoginUser'] = array('value' => $this->aValues["login"], 'type' => 'string');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['loginUnique'], $aParams);
+                if ($this->oConnection->oBd->nombreLigne($oPDOresult) > 0) {
+                    $oError = new VitisError(1, "user already exists");
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                } else {
+                    // create postgres user if not exists
+                    $oSgbdDataAccess = new PgsqlDataAccess($this->oConnection->oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+                    $sErrorMessage = $oSgbdDataAccess->createSgbdUser($this->aValues["login"], $this->aValues["password"]);
+                    if ($sErrorMessage != "") {
+                        $oError = new VitisError(1, $sErrorMessage);
+                        $aXmlRacineAttribute['status'] = 0;
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    } else {
+                        // insert user in table
+                        $iId = $this->oConnection->oBd->insert($this->aProperties['schema_framework'], 'v_user', $this->aValues, $this->aProperties['schema_framework'] . '.seq_common', 'user_id');
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                        } else {
+                            $this->aFields["user_id"] = $iId;
+                            $aXmlRacineAttribute['status'] = 1;
+                            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+
+                            // Attribution des privilèges.
+                            if ($this->aValues['privileges'] == NULL) {
+                                $this->aValues['privileges'] = 'vitis_user';
+                            }
+
+                            $sMessage = $this->setPrivileges($iId);
+                        }
+                    }
+                }
+            } else {
+                $oError = new VitisError(1, "Rights problem : you don't have right to insert users");
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        }
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Put(path="/users/{user_id}",
+     *   tags={"Users"},
+     *   summary="Update User",
+     *   description="Request to update User",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="user_id",
+     *     in="path",
+     *     description="id of the user",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="login",
+     *     in="query",
+     *     description="login of the user",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="name",
+     *     in="query",
+     *     description="Name of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="email",
+     *     in="query",
+     *     description="Email of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="company",
+     *     in="query",
+     *     description="Company of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="department",
+     *     in="query",
+     *     description="Departement of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="groups",
+     *     in="query",
+     *     description="Groups of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="privileges",
+     *     in="query",
+     *     description="Privileges of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="ip_constraint",
+     *     in="query",
+     *     description="Workstation IP address",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password",
+     *     in="query",
+     *     description="Password of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="password_confirm",
+     *     in="query",
+     *     description="Password confirmation of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="restriction",
+     *     in="query",
+     *     description="Password confirmation of the user",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * update user
+     * @return id of the user if ok error object if ko
+     */
+    function PUT() {
+        if ($this->aValues['login'] == $_SESSION['ses_Login'] || in_array("vitis_admin", $this->oConnection->aPrivileges)) {
+            $sLogin = mb_strtolower($this->aValues["login"], 'UTF-8');
+            $sLogin = str_replace(array('à', 'â', 'ä', 'á', 'ã', 'å', 'î', 'ï', 'ì', 'í', 'ô', 'ö', 'ò', 'ó', 'õ', 'ø', 'ù', 'û', 'ü', 'ú', 'é', 'è', 'ê', 'ë', 'ç', 'ÿ', 'ñ'), array('a', 'a', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'e', 'e', 'e', 'e', 'c', 'y', 'n',), $sLogin);
+            unset($this->aValues['login']);
+            if (!empty($this->aValues['encrypted_secretkey']))
+                $this->aValues['secretkey'] = $this->aValues['encrypted_secretkey'];
+            else
+                $this->aValues['secretkey'] = null;
+            $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'v_user', 'user_id');
+            $aXmlRacineAttribute['status'] = $aReturn['sStatus'];
+            $sMessage = $aReturn['sMessage'];
+            if ($aReturn['sStatus'] == 1) {
+                // Attribution des privilèges.
+                if (in_array("vitis_admin", $this->oConnection->aPrivileges)) {
+                    $sMessage = $this->setPrivileges($this->aValues['my_vitis_id']);
+                }
+                // Changement de mot de passe
+                if (!empty($this->aValues['password'])) {
+                    // update password if sent
+                    $oSgbdDataAccess = new PgsqlDataAccess($this->oConnection->oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+                    $sErrorMessage = $oSgbdDataAccess->updateUserPassword($sLogin, $this->aValues["password"]);
+                    if ($sErrorMessage != "") {
+                        $oError = new VitisError(1, $sErrorMessage);
+                        $aXmlRacineAttribute['status'] = 0;
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                        return $sMessage;
+                    }
+                }
+            }
+        } else {
+            http_response_code(403);
+            $aXmlRacineAttribute['status'] = 0;
+            $this->aFields['error'] = "ERROR : invalid token";
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+
+        return $sMessage;
+    }
+
+    /**
+     *  Set privileges of user.
+     */
+    function setPrivileges($iUserId) {
+        require $this->sRessourcesFile;
+
+        // Le paramètre "groups" est passé dans la requête ?
+        if (isset($this->aValues['groups'])) {
+            // Suppression des groupes rattachés à l'utilisateur.
+            $aParams = array();
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['user_id'] = array('value' => $iUserId, 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['deleteUserGroups'], $aParams);
+            if ($this->oConnection->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                return $sMessage;
+            }
+        }
+
+        // Groupes à rattacher à l'utilisateur ?
+        if (!empty($this->aValues['groups'])) {
+            $sSql = "select login from " . $this->aProperties['schema_framework'] . ".\"user\" where user_id = [user_id];";
+            $aParams = array();
+            $aParams['user_id'] = array('value' => $iUserId, 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, $aParams);
+            if ($oPDOresult->rowCount() > 0) {
+                while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                    $sLogin = $aLigne['login'];
+                }
+            }
+            $aGroups = explode('|', $this->aValues['groups']);
+            foreach ($aGroups as $iGroupId) {
+                $aParams = array();
+                $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                $aParams['user_id'] = array('value' => $iUserId, 'type' => 'number');
+                $aParams['group_id'] = array('value' => $iGroupId, 'type' => 'number');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['insertUserGroups'], $aParams);
+                if ($this->oConnection->oBd->enErreur()) {
+                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+        }
+
+        // Le paramètre "privileges" est passé dans la requête ?
+        if (isset($this->aValues['privileges'])) {
+            // Récupère le login de l'utilisateur.
+            $this->aValues['my_vitis_id'] = $iUserId;
+            $oUser = new User($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+            $oUser->GET();
+
+            // Si login = l'utilisateur -> interdiction de supprimer les privilèges 'vitis_admin' et 'vitis_user'.
+            if ($oUser->aFields['login'] == $_SESSION['ses_Login'])
+                $sExcludePrivileges = "vitis_admin|vitis_user";
+            else
+                $sExcludePrivileges = "";
+            // Supprime tous les privilèges de l'utilisateur.
+            $aParams = array();
+            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+            $aParams['login'] = array('value' => $oUser->aFields['login'], 'type' => 'string');
+            $aParams['sExcludePrivileges'] = array('value' => $sExcludePrivileges, 'type' => 'group');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['userPrivileges'], $aParams);
+            if ($this->oConnection->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                return $sMessage;
+            } else {
+                if ($oPDOresult->rowCount() > 0) {
+                    $aResult = $this->oConnection->oBd->getResultTableAssoc($oPDOresult);
+                    foreach ($aResult as $aRow) {
+                        $aParams = array();
+                        $aParams['sValue'] = array('value' => $oUser->aFields['login'], 'type' => 'double_quote');
+                        $aParams['sId'] = array('value' => $aRow['groname'], 'type' => 'double_quote');
+                        $this->oConnection->oBd->executeWithParams($aSql['revokePrivilege'], $aParams);
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            return $sMessage;
+                        }
+                    }
+                    /*if (!in_array("vitis_admin", $aResult))
+                        {
+                            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['revokeCREATEROLE'], $aParams);
+                            if ($this->oConnection->oBd->enErreur()) {
+                                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                                $aXmlRacineAttribute['status'] = 0;
+                                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                                return $sMessage;
+                            }
+                        }*/
+                }
+            }
+        }
+        if (!empty($this->aValues['privileges'])) {
+            // Privilèges à rattacher à l'utilisateur ?
+            if (!empty($this->aValues['privileges'])) {
+                $this->oBd = new BD($this->aProperties["vitis_owner_login"], $this->aProperties["vitis_owner_pass"], $this->oConnection->oBd->base, $this->oConnection->oBd->serveur, $this->oConnection->oBd->port, $this->oConnection->oBd->sgbd, $this->oConnection->oBd->sPageEncoding);
+                $aPrivileges = explode('|', $this->aValues['privileges']);
+                foreach ($aPrivileges as $sPrivilegeId) {
+                    $aParams = array();
+                    $aParams['sValue'] = array('value' => $oUser->aFields['login'], 'type' => 'double_quote');
+                    $aParams['sId'] = array('value' => $sPrivilegeId, 'type' => 'double_quote');
+                    $oPDOresult = $this->oBd->executeWithParams($aSql['grantPrivilege'], $aParams);
+                    if ($this->oConnection->oBd->enErreur()) {
+                        $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                        $aXmlRacineAttribute['status'] = 0;
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                        return $sMessage;
+                    }
+                }
+                if (in_array("vitis_admin", $aPrivileges))
+                    {
+                        $oPDOresult = $this->oBd->executeWithParams($aSql['grantCREATEROLE'], $aParams);
+                        if ($this->oConnection->oBd->enErreur()) {
+                            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                            $aXmlRacineAttribute['status'] = 0;
+                            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                            return $sMessage;
+                        }
+                    }
+                    else{
+                            $oPDOresult = $this->oBd->executeWithParams($aSql['revokeCREATEROLE'], $aParams);
+                            if ($this->oConnection->oBd->enErreur()) {
+                                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                                $aXmlRacineAttribute['status'] = 0;
+                                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                                return $sMessage;
+                            }
+                    }
+            }
+
+            // L'utilisateur est administrateur ?
+            if (!empty($this->aValues['login']) && $this->aValues['login'] != $_SESSION['ses_Login']) {
+                // L'utilisateur est administrateur ?
+                if (in_array('vitis_admin', $aPrivileges))
+                    $sSql = $aSql['userCreateRole'];
+                else
+                    $sSql = $aSql['userNoCreateRole'];
+                $aParams = array();
+                $aParams['login'] = array('value' => $oUser->aFields['login'], 'type' => 'double_quote');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, $aParams);
+                if ($this->oConnection->oBd->enErreur()) {
+                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            }
+        }
+        //
+        $aXmlRacineAttribute['status'] = 1;
+        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        return $sMessage;
+    }
+
+    /**
+     * @SWG\Delete(path="/users/",
+     *   tags={"Users"},
+     *   summary="delete User",
+     *   description="Request to delete User",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="idList",
+     *     in="path",
+     *     description="id of the users",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Delete(path="/users/{user_id}",
+     *   tags={"Users"},
+     *   summary="delete User",
+     *   description="Request to delete User",
+     *   operationId="DELETE",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="user_id",
+     *     in="path",
+     *     description="id of the user",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/users")
+     *     )
+     *  )
+     */
+
+    /**
+     * delete user
+     * @return id of user deleted or error object if an user is not deleted
+     */
+    function DELETE() {
+        if ($this->oConnection->oError == null && in_array("vitis_admin", $this->oConnection->aPrivileges)) {
+            $aReturn = $this->genericDelete($this->aProperties['schema_framework'], 'v_user', 'user_id');
+        } else {
+            $oError = new Error(1, "Invalid token");
+            $aXmlRacineAttribute['status'] = 0;
+            $aReturn['sMessage'] = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+
+        return $aReturn['sMessage'];
+    }
+
+    /**
+     * Import des utilisateurs de l'A.D.
+     */
+    function importLdapUser() {
+        $oSgbdDataAccess = new PgsqlDataAccess($this->oConnection->oBd, $this->aProperties["database"], $this->aProperties["server"], "vitis_user", "vitis_admin", $this->aProperties["schema_framework"]);
+        $this->aValues["login"] = mb_strtolower($this->aValues["login"], 'UTF-8');
+        $this->aValues["login"] = str_replace(array('à', 'â', 'ä', 'á', 'ã', 'å', 'î', 'ï', 'ì', 'í', 'ô', 'ö', 'ò', 'ó', 'õ', 'ø', 'ù', 'û', 'ü', 'ú', 'é', 'è', 'ê', 'ë', 'ç', 'ÿ', 'ñ'), array('a', 'a', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'e', 'e', 'e', 'e', 'c', 'y', 'n',), $this->aValues["login"]);
+        $sErrorMessage = $oSgbdDataAccess->createSgbdUserNoPassword($this->aValues["login"]);
+        if ($sErrorMessage != "") {
+            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            require $this->sRessourcesFile;
+            $aParams = array();
+            $aParams['sLdapName'] = array('value' => 'vitis_' . $this->aValues['ldap_name'], 'type' => 'double_quote');
+            $aParams['sLogin'] = array('value' => $this->aValues['login'], 'type' => 'double_quote');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['grantUser'], $aParams);
+            if ($this->oConnection->oBd->enErreur()) {
+                $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            } else {
+                $aParams = array();
+                $aParams['sSchemaName'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                $aParams['sName'] = array('value' => 'user', 'type' => 'column_name');
+                $aParams['sLogin'] = array('value' => $this->aValues['login'], 'type' => 'string');
+                $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getLogin'], $aParams);
+                $oResult = $this->oConnection->oBd->objetSuivant($oPDOresult);
+                if ($this->oConnection->oBd->enErreur()) {
+                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                } else {
+                    // Création ou maj de l'utilisateur
+                    if ($oResult) {
+                        $this->oConnection->oBd->update($this->aProperties["schema_framework"], 'user', $this->aValues, "user_id", $oResult->user_id);
+                        $this->aFields['user_id'] = $oResult->user_id;
+                    } else {
+                        $iId = $this->oConnection->oBd->insert($this->aProperties["schema_framework"], 'user', $this->aValues, $this->aProperties['schema_framework'] . '.seq_common', 'user_id');
+                        $this->aFields['user_id'] = $iId;
+                    }
+                    //
+                    if ($this->oConnection->oBd->enErreur()) {
+                        $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                        $aXmlRacineAttribute['status'] = 0;
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    } else {
+                        $aXmlRacineAttribute['status'] = 1;
+                        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    }
+                }
+            }
+        }
+        return $sMessage;
+    }
+
+}
+
+?>
diff --git a/vas/rest/ws/vitis/Versions.class.inc b/vas/rest/ws/vitis/Versions.class.inc
new file mode 100755
index 00000000..62b9cfcc
--- /dev/null
+++ b/vas/rest/ws/vitis/Versions.class.inc
@@ -0,0 +1,204 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+
+/**
+ * \file versions.class.inc
+ * \class Versions
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Versions php class
+ *
+ * This class defines the rest api for versions
+ * 
+ */
+class Versions extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/versions",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/versions")
+     *   }
+     * )
+     * @SWG\Tag(
+     *   name="Versions",
+     *   description="Operations about versions"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $versions ptroperties
+     */
+    function __construct($aPath, $aValues, $properties) {
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+        if (!empty($this->aValues['token'])) {
+            $this->oConnection = new Connection($this->aValues, $this->aProperties);
+        }
+    }
+
+    /**
+     * @SWG\Get(path="/versions",
+     *   tags={"Versions"},
+     *   summary="Get versions",
+     *   description="Request to get versions",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *  @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/versions")
+     *     )
+     *  )
+     */
+
+    /**
+     * 
+     * @return versions
+     */
+    function GET() {
+        if ($this->oConnection->oError == null) {
+            $this->getVersion();
+            if (!empty($this->aValues['token']) && in_array("vitis_admin", $this->oConnection->aPrivileges)) {
+
+                //$this->aFields = $this->aVersions;
+                $this->aFields['php_version'] = phpversion();
+
+                //*** PDO
+                $bPdo = false;
+                if (extension_loaded('pdo'))
+                    $bPdo = true;
+                else
+                    $bVeremap = false;
+                $this->aFields['pdo_extension_loaded'] = $bPdo;
+
+                //*** PDO Postgresql
+                $bPdoPgsql = false;
+                if (extension_loaded('pdo_pgsql'))
+                    $bPdoPgsql = true;
+                else
+                    $bVeremap = false;
+                $this->aFields['pdo_pgsql_extension_loaded'] = $bPdoPgsql;
+
+                //*** Curl
+                $bCurl = false;
+                if (extension_loaded('curl'))
+                    $bCurl = true;
+                else
+                    $bVeremap = false;
+                $this->aFields['curl_extension_loaded'] = $bCurl;
+
+                //*** Xsl
+                $bXsl = false;
+                if (extension_loaded('xsl'))
+                    $bXsl = true;
+                $this->aFields['xsl_extension_loaded'] = $bXsl;
+
+                //*** Ldap
+                $bLdap = false;
+                if (extension_loaded('ldap'))
+                    $bLdap = true;
+                $this->aFields['ldap_extension_loaded'] = $bLdap;
+
+                // OS.
+                $this->aFields['os_version'] = php_uname();
+
+                // Info disque.
+                $this->aFields['disk_free_space'] = round(disk_free_space("/") / 1073741824) . ' Go';
+                $this->aFields['disk_total_space'] = round(disk_total_space("/") / 1073741824) . ' Go';
+
+                //
+                $this->aFields['server_software'] = $_SERVER['SERVER_SOFTWARE'];
+                $this->aFields['server_addr'] = $_SERVER['SERVER_ADDR'];
+                $this->aFields['server_name'] = $_SERVER['SERVER_NAME'];
+                $this->aFields['server_port'] = $_SERVER['SERVER_PORT'];
+
+                //** Postgresql et Postgis
+                $bPostgresql = false;
+                $bPostgis = false;
+                if (!$this->oConnection->oBd->erreurRencontree) {
+                    $bPostgresql = true;
+                    $sSql = "SHOW server_version";
+                    $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, array());
+                    $oPgVersion = $this->oConnection->oBd->objetSuivant($oPDOresult);
+                    $sPostgresql = $oPgVersion->server_version;
+                    $this->aFields['postgresql_version'] = $sPostgresql;
+                    $this->oConnection->oBd->fermeResultat();
+
+                    $aVersion = explode(".", $sPostgresql);
+                    $bExtension = false;
+                    if ($aVersion[0] >= 9) {
+                        if ($aVersion[1] >= 1) {
+                            $bExtension = true;
+                        }
+                    }
+                    if ($bExtension == true) {
+                        $sSql = "SELECT default_version FROM pg_catalog.pg_available_extensions where name = 'postgis';";
+                        $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, array());
+                        if ($aPostgis = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                            $bPostgis = true;
+                            $sPostgis = $aPostgis['default_version'];
+                        } else {
+                            $bPostgis = false;
+                        }
+                    } else {
+                        $sSql = "SELECT datname FROM pg_catalog.pg_database where datname = 'template_postgis_20';";
+                        $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, array());
+                        if ($aPostgis = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                            $bPostgis = true;
+                            $sPostgis = '2.0';
+                        } else {
+                            $bPostgis = false;
+                        }
+                    }
+                    $this->aFields['postgis_version'] = $sPostgis;
+                    $this->oConnection->oBd->fermeResultat();
+                    $sSql = 'SELECT distinct module_id from [sSchemaFramework].vm_mode';
+                    $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                    $oPDOresult = $this->oConnection->oBd->executeWithParams($sSql, $aParams);
+                    while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                        $aModules[] = $aLigne['module_id'];
+                    }
+                    $iRecordset = $this->oConnection->oBd->fermeResultat();
+                }
+                $this->aFields['postgresql'] = $bPostgresql;
+                $this->aFields['postgis'] = $bPostgis;
+
+                // Recherche de mise à jour
+                // 
+                if (!empty($this->aValues['app'])) {
+                    $sUrl = "http://update.veremes.net/vai/" . $this->aValues['app'] . ".json";
+                    $json = file_get_contents($sUrl);
+                    $data = json_decode($json, TRUE);
+                    $this->aFields['appVersion'] = $data['version'];
+                }
+            }
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            http_response_code(403);
+            $aXmlRacineAttribute['status'] = 0;
+            $this->aFields['errorMessage'] = "ERROR : invalid token";
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+
+        return $sMessage;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/Vitis.class.inc b/vas/rest/ws/vitis/Vitis.class.inc
new file mode 100755
index 00000000..8a8bb421
--- /dev/null
+++ b/vas/rest/ws/vitis/Vitis.class.inc
@@ -0,0 +1,1507 @@
+<?php
+
+require_once(__DIR__ . "/../../class/vitis_lib/DbClass.class.inc");
+
+/**
+ * \file vitis.class.inc
+ * \class Vitis
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the vitis php class
+ *
+ * This class defines generics parameters and functions accessible by vitis php classes
+ *
+ */
+class Vitis extends DbClass {
+
+    /**
+     * file containing sql request for vitis classes
+     */
+    var $sRessourcesFile = "Vitis.class.sql.inc";
+
+    /**
+     * parameters sent to rest api
+     */
+    public $aValues = array();
+
+    /**
+     * url sent to rest api
+     */
+    public $aPath = array();
+
+    /**
+     * vitis properties
+     */
+    public $aProperties = array();
+
+    /**
+     * result array of the object
+     */
+    public $aFields = array();
+
+    /**
+     * Connection object(connect to the database, get user groups and privileges)
+     */
+    public $oConnection;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        if ($bShortcut !== true) {
+            $this->aValues = $aValues;
+            $this->aPath = $aPath;
+            $this->aProperties = $properties;
+            if (empty($oConnection)) {
+                $this->oConnection = new Connection($this->aValues, $this->aProperties);
+            } else {
+                $this->oConnection = $oConnection;
+            }
+        }
+    }
+
+    /**
+     * accessible data of the object
+     */
+    public $aSelectedFields = Array();
+    public $aOrganizedFields = Array();
+    public $aTablePrivileges = Array();
+
+    /**
+     * Generic function which get fields of the object stored in the database
+     * @param type $sSchema
+     * @param type $sTable
+     * @param type $sIdField
+     *
+     */
+    function getFields($sSchema, $sTable, $sIdField) {
+
+        $this->aSqlParams = array();
+
+        //generate the structure of the result
+        $this->addSelectedFields();
+
+        // Format $this->aSelectedFields for spatial use
+        $this->formatSelectedFieldsForGeom($sSchema, $sTable);
+
+        //get the fields present in the database
+        $aColumn = $this->getTableColumns($sSchema, $sTable);
+
+        $aData = null;
+
+        //intersect the structure and the fields in the database to get only fields present in the database and the structure
+        if (empty($this->aSelectedFields)) {
+            $aFieldInTable = $aColumn;
+        } else {
+            $aFieldInTable = array_intersect($aColumn, $this->aSelectedFields);
+        }
+        //build request
+        if (!empty($aFieldInTable)) {
+            if (!in_array($sIdField, $aFieldInTable)) {
+                array_push($aFieldInTable, $sIdField);
+            }
+            $sSql = "SELECT ";
+            // les field ne sont pas passés en tant que paramètre column_name car des fois ils ont pour valeur des fonctions ex: "ST_SRID(geom) as proj"
+            foreach ($aFieldInTable as $field) {
+                if (strpos($field, "(") == FALSE && strpos($field, ")") == FALSE && strpos(strtolower($field), " as ") == FALSE) {
+                    $field = "\"" . $field . "\"";
+                }
+                if ($sSql == "SELECT ") {
+                    $sSql .= $field;
+                } else {
+                    $sSql .= ", " . $field;
+                }
+            }
+
+            $this->aSqlParams['sSchema'] = array('value' => $sSchema, 'type' => 'column_name');
+            $this->aSqlParams['sTable'] = array('value' => $sTable, 'type' => 'column_name');
+            $this->aSqlParams['sIdField'] = array('value' => $sIdField, 'type' => 'column_name');
+            $this->aSqlParams['my_vitis_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'string');
+
+            $sSql .= " FROM \"[sSchema]\".\"[sTable]\" WHERE \"[sIdField]\" IN ([my_vitis_id])";
+
+            //Get result
+            $oResult = $this->oConnection->oBd->executeWithParams($sSql, $this->aSqlParams);
+            if (empty($this->oConnection->oBd->enErreur) && $this->oConnection->oBd->nombreLigne($oResult) > 0) {
+                $aData = array();
+                while ($aObject = $this->oConnection->oBd->ligneSuivante($oResult)) {
+                    foreach ($aObject as $sParamKey => $sParamValue) {
+
+                        $aData[$sParamKey] = $sParamValue;
+                    }
+                }
+            }
+        }
+        return $aData;
+    }
+
+    /**
+     * Get the columns of the table
+     * @param type $sSchema
+     * @param type $sTable
+     * @return array
+     */
+    function getTableColumns($sSchema, $sTable) {
+        require $this->sRessourcesFile;
+        $aColumn = Array();
+        $sSql = $aSql['getTableColumn'];
+        $aSqlParams = array(
+            'sSchemaFramework' => array('value' => $sSchema, 'type' => 'column_name'),
+            'sTable' => array('value' => $sTable, 'type' => 'column_name')
+        );
+
+        $oResult = $this->oConnection->oBd->executeWithParams($sSql, $aSqlParams);
+
+        if (!empty($oResult)) {
+            while ($aObject = $this->oConnection->oBd->ligneSuivante($oResult)) {
+                array_push($aColumn, $aObject['column_name']);
+            }
+            foreach ($this->aSelectedFields as $fields) {
+                if (strpos($fields, "(") != FALSE && strpos($fields, ")") != FALSE && strpos(strtolower($fields), " as ") != FALSE) {
+                    array_push($aColumn, $fields);
+                }
+            }
+        }
+        return $aColumn;
+    }
+
+    /**
+     * Get the geometry columns of the table
+     * @param string $sSchema
+     * @param string $sTable
+     * @return array
+     */
+    function getGeometryColumns($sSchema, $sTable) {
+        require $this->sRessourcesFile;
+        $aColumn = Array();
+        $sSql = $aSql['getGeometryColumns'];
+
+        $aSqlParams = array(
+            'sSchemaFramework' => array('value' => $sSchema, 'type' => 'column_name'),
+            'sTable' => array('value' => $sTable, 'type' => 'column_name')
+        );
+
+        $oResult = $this->oConnection->oBd->executeWithParams($sSql, $aSqlParams);
+
+        // vide si postGis n'est pas installé
+        if (!empty($oResult)) {
+            while ($aObject = $this->oConnection->oBd->ligneSuivante($oResult)) {
+                array_push($aColumn, $aObject['f_geometry_column']);
+            }
+        }
+
+        return $aColumn;
+    }
+
+    // fonction get générique à tous les objets
+    /**
+     * Generic function which get data of the objects in tables
+     * @param $sSchema schema of the table
+     * @param $sTable table name
+     * @param $sIdField name of the id field
+     * @param $bOnlyReturnStatus
+     * @param $sVitisObjectName Name of the vitis object, if provide and the object contains files stored in ws_data/vitis/$sVitisObjectName the values will be url formed
+     * @return the array of objects
+     */
+    function genericGet($sSchema, $sTable, $sIdField, $bOnlyReturnStatus = false, $sVitisObjectName = "") {
+        if (!empty($this->aProperties['ws_data_alias']))
+            $ws_data_alias = $this->aProperties['ws_data_alias'];
+        else
+            $ws_data_alias = '';
+        $sParentClassName = get_class($this);
+        $sChildClassName = substr($sParentClassName, 0, -1);
+        //$oObject = new $sChildClassName($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+        $date = new DateTime();
+        $this->aSqlParams = array();
+        $this->aSqlParams['sSchema'] = array('value' => $sSchema, 'type' => 'column_name');
+        $this->aSqlParams['sTable'] = array('value' => $sTable, 'type' => 'column_name');
+        if (isset($this->aValues['sEncoding']))
+            $sEncoding = $this->aValues['sEncoding'];
+        else
+            $sEncoding = null;
+        if (isset($this->aValues['sSourceEncoding']))
+            $sSourceEncoding = $this->aValues['sSourceEncoding'];
+        else
+            $sSourceEncoding = null;
+        if (isset($this->aValues['output']))
+            $output = $this->aValues['output'];
+        else
+            $output = null;
+        //Verify connection
+        if ($this->oConnection->oError != null) {
+            $oError = $this->oConnection->oError;
+        } else {
+            $this->getTablePrivileges($sSchema, $sTable);
+            //$aPrivileges = array_intersect($this->oConnection->aPrivileges, $this->aTablePrivileges) ;
+            if (in_array('SELECT', $this->aTablePrivileges)) {
+                //verify if id is present in the url
+                if (isset($this->aValues['my_vitis_id'])) {
+
+                    //object instantiation
+                    $oObject = new $sChildClassName($this->aPath, $this->aValues, $this->aProperties, false, $this->oConnection);
+                    $oObject->GET();
+
+                    // Vérifie si il y a des fichiers à renvoyer
+                    if ($sVitisObjectName != "") {
+                        $sDataDir = $this->aProperties['ws_data_dir'] . '/vitis/' . $sVitisObjectName . '/documents/' . $oObject->aFields[$sIdField];
+                        $sDataUrl = $this->aProperties['web_server_name'] . "/" . $ws_data_alias . "/vitis/" . $sVitisObjectName . "/documents/" . $oObject->aFields[$sIdField];
+                        if (is_dir($sDataDir)) {
+                            // Remplace le nom du fichier par son url
+                            foreach ($oObject->aFields as $key => $value) {
+                                if (is_dir($sDataDir . "/" . $key)) {
+                                    $oObject->aFields[$key] = $sDataUrl . "/" . $key . "/" . $value . "?d=" . $date->getTimestamp();
+                                }
+                            }
+                        }
+                    }
+                    array_push($this->aObjects, $oObject);
+                    $oError = $oObject->oError;
+                    //$sMessage = $this->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $output);
+                } else {
+
+                    //build request to get Ids
+                    $sSql = "SELECT ";
+                    if (!empty($this->aValues['distinct']) && $this->aValues['distinct'] == "true") {
+                        $sSql .= "DISTINCT ";
+                    }
+                    // Format $this->aSelectedFields for spatial use
+                    if (empty($this->aValues['result_srid']))
+                        $this->aValues['result_srid'] = null;
+                    //Fields
+                    $this->addSelectedFields();
+                    $this->formatSelectedFieldsForGeom($sSchema, $sTable, $this->aValues['result_srid']);
+                    //get the fields present in the database
+                    $aColumn = $this->getTableColumns($sSchema, $sTable);
+
+                    //intersect the structure and the fields in the database to get only fields present in the database and the structure
+                    $aFieldInTable = array();
+                    if (empty($this->aSelectedFields)) {
+                        foreach ($aColumn as $value) {
+                            array_push($aFieldInTable, '"' . $value . '"');
+                        }
+                    } else {
+                        foreach ($this->aOrganizedFields as $key => $value) {
+                            if (in_array($key, $aColumn) || in_array($key . " as " . $value, $aColumn)) {
+                                // Attention: Injections possible!
+                                if (strpos($key, "(") == FALSE && strpos($key, ")") == FALSE) {
+                                    if ($value == "") {
+                                        array_push($aFieldInTable, '"' . $key . '"');
+                                    } else {
+                                        array_push($aFieldInTable, '"' . $key . '" as "' . $value . '"');
+                                    }
+                                } else {
+                                    array_push($aFieldInTable, $key . ' as "' . $value . '"');
+                                }
+                            }
+                        }
+                    }
+                    //build request
+                    // les field ne sont pas passés en tant que paramètre column_name car des fois ils ont pour valeur des fonctions ex: "ST_SRID(geom) as proj"
+                    if (!empty($aFieldInTable)) {
+                        foreach ($aFieldInTable as $fields) {
+                            if ($sSql == "SELECT " || $sSql == "SELECT DISTINCT ") {
+                                $sSql .= $fields;
+                            } else {
+                                $sSql .= ", " . $fields;
+                            }
+                        }
+                    }
+
+                    // Filter
+                    $sSql .= " FROM \"[sSchema]\".\"[sTable]\"";
+                    if (!empty($this->aValues['filter'])) {
+                        // filtre
+                        $aDecodedFilter = $this->decodeJSONFilter($this->aValues['filter'], $sSchema, $sTable);
+                        // Ajout dans la requête
+                        $sSecuredFilter = $aDecodedFilter['request'];
+                        // Ajout des paramètres
+                        foreach ($aDecodedFilter['params'] as $key => $value) {
+                            $this->aSqlParams[$key] = $value;
+                        }
+
+                        // Ajout du filtre dans la requête
+                        if (!empty(trim($sSecuredFilter))) {
+                            if (strpos($sSql, " WHERE ") == FALSE) {
+                                $sSql .= " WHERE " . $sSecuredFilter;
+                            } else {
+                                $sSql .= " AND " . $sSecuredFilter;
+                            }
+                        }
+                    }
+                    if (!empty($this->aValues['group_by'])) {
+                        $aGroup = explode("|", $this->aValues['group_by']);
+                        foreach ($aGroup as $value) {
+                            $sColumnKey = 'column_' . vitisUniqId();
+                            if (strpos($sSql, "GROUP BY") == FALSE) {
+                                $sSql .= " GROUP BY " . str_replace("=", " ", "[" . $sColumnKey . "]");
+                            } else {
+                                $sSql .= ", " . str_replace("=", " ", "[" . $sColumnKey . "]");
+                            }
+                            $this->aSqlParams[$sColumnKey] = array('value' => $value, 'type' => 'column_name');
+                        }
+                    }
+                    //order by
+                    if (!empty($this->aValues['order_by'])) {
+                        $aOrder = explode("|", $this->aValues['order_by']);
+                        foreach ($aOrder as $value) {
+                            $sColumnKey = 'column_' . vitisUniqId();
+                            if (strpos($sSql, "ORDER BY") == FALSE) {
+                                $sSql .= " ORDER BY " . str_replace("=", " ", "[" . $sColumnKey . "]");
+                            } else {
+                                $sSql .= ", " . str_replace("=", " ", "[" . $sColumnKey . "]");
+                            }
+                            $this->aSqlParams[$sColumnKey] = array('value' => $value, 'type' => 'column_name');
+                        }
+                        if (!empty($this->aValues['sort_order'])) {
+                            switch (strtoupper($this->aValues['sort_order'])) {
+                                case 'ASC':
+                                    $sSql .= " ASC";
+                                    break;
+                                case 'DESC':
+                                    $sSql .= " DESC";
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+
+                        if (!empty($this->aValues['null_order'])) {
+                            switch (strtoupper($this->aValues['null_order'])) {
+                                case 'LAST':
+                                    $sSql .= " NULLS LAST";
+                                    break;
+                                case 'FIRST':
+                                    $sSql .= " NULLS FIRST";
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                    }
+
+                    //limit
+                    if (!empty($this->aValues['limit'])) {
+                        $sLimitKey = 'limit_' . vitisUniqId();
+                        $sSql .= " LIMIT [" . $sLimitKey . "]";
+                        $this->aSqlParams[$sLimitKey] = array('value' => $this->aValues['limit'], 'type' => 'number');
+                    }
+                    //offset
+                    if (!empty($this->aValues['offset'])) {
+                        $sOffsetKey = 'offset_' . vitisUniqId();
+                        $sSql .= " OFFSET [" . $sOffsetKey . "]";
+                        $this->aSqlParams[$sOffsetKey] = array('value' => $this->aValues['offset'], 'type' => 'number');
+                    }
+
+                    //get the result
+                    $oResult = $this->oConnection->oBd->executeWithParams($sSql, $this->aSqlParams);
+
+                    // if no error get the result
+                    $this->aValues['my_vitis_id'] = "";
+                    $aParams2 = array();
+                    if (empty($this->oConnection->oBd->enErreur) && $this->oConnection->oBd->nombreLigne($oResult) > 0) {
+                        while ($aLigne = $this->oConnection->oBd->ligneSuivante($oResult)) {
+                            $oObject = new $sChildClassName($this->aPath, $this->aValues, $this->aProperties, true);
+                            $oObject->aFields = $aLigne;
+                            array_push($this->aObjects, $oObject);
+                            // Vérifie si il y a des fichiers à renvoyer
+                            if ($sVitisObjectName != "") {
+                                $sDataDir = $this->aProperties['ws_data_dir'] . '/vitis/' . $sVitisObjectName . '/documents/' . $oObject->aFields[$sIdField];
+                                $sDataUrl = $this->aProperties['web_server_name'] . "/" . $ws_data_alias . "/vitis/" . $sVitisObjectName . "/documents/" . $oObject->aFields[$sIdField];
+                                if (is_dir($sDataDir)) {
+                                    // Remplace le nom du fichier par son url
+                                    foreach ($oObject->aFields as $key => $value) {
+                                        if (is_dir($sDataDir . "/" . $key)) {
+                                            $oObject->aFields[$key] = $sDataUrl . "/" . $key . "/" . $value . "?d=" . $date->getTimestamp();
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    $this->aFields['list_count'] = $this->oConnection->oBd->nombreLigne($oResult);
+                    $sSql = "select count(*) as total_row_number FROM \"[sSchema]\".\"[sTable]\"";
+                    $aParams2['sSchema'] = array('value' => $sSchema, 'type' => 'column_name');
+                    $aParams2['sTable'] = array('value' => $sTable, 'type' => 'column_name');
+                    if (!empty($this->aValues['filter'])) {
+                        // filtre
+                        $aDecodedFilter = $this->decodeJSONFilter($this->aValues['filter'], $sSchema, $sTable);
+                        // Ajout dans la requête
+                        $sSecuredFilter = $aDecodedFilter['request'];
+                        // Ajout des paramètres
+                        foreach ($aDecodedFilter['params'] as $key => $value) {
+                            $aParams2[$key] = $value;
+                        }
+
+                        // Ajout à la requête
+                        if (!empty(trim($sSecuredFilter))) {
+                            if (strpos($sSql, " WHERE ") == FALSE) {
+                                $sSql .= " WHERE " . $sSecuredFilter;
+                            } else {
+                                $sSql .= " AND " . $sSecuredFilter;
+                            }
+                        }
+                    }
+
+                    $oResult = $this->oConnection->oBd->executeWithParams($sSql, $aParams2);
+                    $aLigne = $this->oConnection->oBd->ligneSuivante($oResult);
+                    $this->aFields['total_row_number'] = $aLigne['total_row_number'];
+                }
+            } else {
+                $oError = new VitisError(1, "Rights problem : you don't have right to list " . $sChildClassName);
+            }
+        }
+
+        if (isset($oError)) {
+            $aXmlRacineAttribute['status'] = 0;
+            if (!$bOnlyReturnStatus)
+                $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $output);
+        } else {
+            $aXmlRacineAttribute['status'] = 1;
+            if (!$bOnlyReturnStatus)
+                $sMessage = $this->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $output);
+        }
+        if (!$bOnlyReturnStatus)
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+        else
+            $aReturn = array('sStatus' => $aXmlRacineAttribute['status']);
+
+        return $aReturn;
+    }
+
+    /**
+     * Define the structure of the object (fields returned)
+     */
+    function addSelectedFields() {
+        foreach ($this->aSelectedFields as $value) {
+            if (strpos($value, " as ") != false) {
+                $aValue = explode(" as ", $value);
+                $this->aOrganizedFields[$aValue[0]] = $aValue[1];
+            } else {
+                $this->aOrganizedFields[$value] = $value;
+            }
+        }
+        if (!empty($this->aValues["attributs"])) {
+            if (strpos($this->aValues["attributs"], "-") === 0) {
+                $aAtttributs = explode("|", substr($this->aValues["attributs"], 1));
+                foreach ($aAtttributs as $value) {
+                    if (in_array($value, $this->aOrganizedFields)) {
+                        unset($this->aOrganizedFields[array_search($value, $this->aOrganizedFields)]);
+                    }
+                }
+            } else {
+                if (strpos($this->aValues["attributs"], "+") === 0) {
+                    $aAtttributs = explode("|", substr($this->aValues["attributs"], 1));
+                } else {
+                    $aAtttributs = explode("|", $this->aValues["attributs"]);
+                }
+                $oldSelectedFields = $this->aOrganizedFields;
+                $this->aOrganizedFields = array();
+                foreach ($aAtttributs as $value) {
+                    if (in_array($value, $oldSelectedFields)) {
+                        $this->aOrganizedFields[array_search($value, $oldSelectedFields)] = $value;
+                    } elseif (isset($oldSelectedFields[$value])) {
+                        $this->aOrganizedFields[$value] = $oldSelectedFields[$value];
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *
+     * @param type $sSchema schema containing the table
+     * @param type $sTable table to update
+     * @param type $sSequence  used sequence to get the id
+     * @param type $sIdField id field name
+     * @param type $sPrivilegeParent privilege to do the insertion
+     * @return array containing the status and the message
+     */
+    function genericPost($sSchema, $sTable, $sSequence, $sIdField) {
+        if (isset($this->aValues['sEncoding']))
+            $sEncoding = $this->aValues['sEncoding'];
+        else
+            $sEncoding = null;
+        if (isset($this->aValues['sSourceEncoding']))
+            $sSourceEncoding = $this->aValues['sSourceEncoding'];
+        else
+            $sSourceEncoding = null;
+        //verify the connection
+        if ($this->oConnection->oError != null) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+        } else {
+            // verify if the user is framework_admin
+            $this->getTablePrivileges($sSchema, $sTable);
+            //$aPrivileges = array_intersect($this->oConnection->aPrivileges, $this->aTablePrivileges) ;
+            if (in_array('INSERT', $this->aTablePrivileges)) {
+                // insert user in table
+                $iId = $this->oConnection->oBd->insert($sSchema, $sTable, $this->aValues, $sSequence, $sIdField);
+                if ($this->oConnection->oBd->enErreur()) {
+                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+                } else {
+                    $this->aFields[$sIdField] = $iId;
+                    $this->aValues['my_vitis_id'] = $iId;
+
+                    $aXmlRacineAttribute['status'] = 1;
+                    $sMessage = $this->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+                }
+            } else {
+                $oError = new VitisError(1, "Rights problem : you don't have right to insert in " . $sSchema . "." . $sTable);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+            }
+        }
+        $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+        return $aReturn;
+    }
+
+    /**
+     *
+     * @param type $sSchema schema containing the table
+     * @param type $sTable table to update
+     * @param type $sIdField id field name
+     * @param type $sPrivilegeParent privilege to do the insertion
+     * @return array containing the status and the message
+     */
+    function genericPut($sSchema, $sTable, $sIdField) {
+        if (isset($this->aValues['sEncoding']))
+            $sEncoding = $this->aValues['sEncoding'];
+        else
+            $sEncoding = null;
+        if (isset($this->aValues['sSourceEncoding']))
+            $sSourceEncoding = $this->aValues['sSourceEncoding'];
+        else
+            $sSourceEncoding = null;
+        if ($this->oConnection->oError != null) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+        } else {
+            $this->getTablePrivileges($sSchema, $sTable);
+            //$aPrivileges = array_intersect($this->oConnection->aPrivileges, $this->aTablePrivileges) ;
+            if (in_array('UPDATE', $this->aTablePrivileges)) {
+                $iId = $this->oConnection->oBd->update($sSchema, $sTable, $this->aValues, $sIdField, $this->aValues['my_vitis_id'], "text");
+                if ($this->oConnection->oBd->enErreur()) {
+                    $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+                    $aXmlRacineAttribute['status'] = 0;
+                    $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+                } else {
+                    $this->aFields[$sIdField] = $this->aValues['my_vitis_id'];
+                    $aXmlRacineAttribute['status'] = 1;
+                    $sMessage = $this->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+                }
+            } else {
+                $oError = new VitisError(1, "Rights problem : you don't have right to update in " . $sSchema . "." . $sTable);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+            }
+        }
+        $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+        return $aReturn;
+    }
+
+    function genericDelete($sSchema, $sTable, $sIdField) {
+        if (isset($this->aValues['sEncoding']))
+            $sEncoding = $this->aValues['sEncoding'];
+        else
+            $sEncoding = null;
+        if (isset($this->aValues['sSourceEncoding']))
+            $sSourceEncoding = $this->aValues['sSourceEncoding'];
+        else
+            $sSourceEncoding = null;
+        $sParentClassName = get_class($this);
+        $sChildClassName = substr($sParentClassName, 0, -1);
+        if ($this->oConnection->oError != null) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+        } else {
+            $this->getTablePrivileges($sSchema, $sTable);
+            //$aPrivileges = array_intersect($this->oConnection->aPrivileges, $this->aTablePrivileges) ;
+            if (in_array('DELETE', $this->aTablePrivileges)) {
+                if (isset($this->aValues['my_vitis_id'])) {
+                    $oObject = new $sChildClassName($this->aPath, $this->aValues, $this->aProperties, false, $this->oConnection);
+                    $oObject->DELETE();
+                    array_push($this->aObjects, $oObject);
+                } else {
+                    //if several id
+                    $aIdList = explode("|", $this->aValues['idList']);
+                    foreach ($aIdList as $value) {
+                        $this->aValues['my_vitis_id'] = $value;
+                        $oObject = new $sChildClassName($this->aPath, $this->aValues, $this->aProperties, false, $this->oConnection);
+                        $oObject->DELETE();
+                        array_push($this->aObjects, $oObject);
+                    }
+                }
+            } else {
+                $oError = new VitisError(12, "Rights problem : you don't have right to delete in" . $sSchema . "." . $sTable);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+            }
+        }
+        foreach ($this->aObjects as $oObject) {
+            if ($oObject->oError != null) {
+                $oError = $this->oConnection->oError;
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+            } else {
+                if (!empty($this->aFields['idDeleted']) && !empty($this->aFields['user_id'])) {
+                    if ($this->aFields['idDeleted'] == "")
+                        $this->aFields['idDeleted'] .= $oUser->aFields['user_id'];
+                    else
+                        $this->aFields['idDeleted'] .= "|" . $oUser->aFields['user_id'];
+                }
+            }
+        }
+        if (!isset($sMessage)) {
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']);
+        }
+        $aReturn = array('sStatus' => $aXmlRacineAttribute['status'], "sMessage" => $sMessage);
+        return $aReturn;
+    }
+
+    function deleteChild($sSchema, $sTable, $sIdField, $sPrivilegeParent = "") {
+        $this->oConnection->oBd->delete($this->aProperties['schema_framework'], 'v_user', 'user_id', $this->aValues['my_vitis_id'], 'integer');
+        if ($this->oConnection->oBd->enErreur()) {
+            $this->oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+        } else {
+            $this->aFields["user_id"] = $this->aValues['my_vitis_id'];
+        }
+    }
+
+    function getVersion($sRessources = "") {
+        require_once (__DIR__ . '/../../conf/' . $sRessources . '/version.inc');
+        $this->aFields["version"] = VM_VERSION;
+        $this->aFields["build"] = VM_BUILD;
+        $this->aFields["date"] = VM_MONTH_YEAR;
+    }
+
+    /**
+     * Add to the sSelectedFields the PostGIS function to get the geometry on
+     * EWKT format instead binary (WKB)
+     * @param string $sSchema
+     * @param string $sTable
+     * @param string $sResultSRID SRID of the resulted proj
+     */
+    function formatSelectedFieldsForGeom($sSchema, $sTable, $sResultSRID = "") {
+
+        $aGeomColumnsInfos = $this->getTableGeomColumnsInfos($sSchema, $sTable);
+
+        $aGeomColumns = array();
+        for ($i = 0; $i < count($aGeomColumnsInfos); $i++) {
+            if (in_array($aGeomColumnsInfos[$i]['f_geometry_column'], $this->aSelectedFields)) {
+                array_push($aGeomColumns, $aGeomColumnsInfos[$i]['f_geometry_column']);
+            }
+        }
+
+        for ($i = 0; $i < count($this->aSelectedFields); $i++) {
+            if (in_array($this->aSelectedFields[$i], $aGeomColumns)) {
+                $sColumnKey = 'column_' . vitisUniqId();
+                $sColumnName = $this->aSelectedFields[$i];
+                if (!empty($this->aOrganizedFields[$sColumnName])) {
+                    if (!empty($sResultSRID)) {
+                        $this->aSelectedFields[$i] = "ST_AsEWKT(ST_Transform([" . $sColumnKey . "], [result_srid]::integer)) as " . $this->aSelectedFields[$i];
+                        $this->aOrganizedFields["ST_AsEWKT(ST_Transform([" . $sColumnKey . "], [result_srid]::integer))"] = $sColumnName;
+
+                        $this->aSqlParams['result_srid'] = array('value' => $sResultSRID, 'type' => 'integer');
+                        $this->aSqlParams[$sColumnKey] = array('value' => $sColumnName, 'type' => 'column_name');
+                    } else {
+                        $this->aSelectedFields[$i] = "ST_AsEWKT([" . $sColumnKey . "]) as " . $this->aSelectedFields[$i];
+                        $this->aOrganizedFields["ST_AsEWKT([" . $sColumnKey . "])"] = $sColumnName;
+
+                        $this->aSqlParams[$sColumnKey] = array('value' => $sColumnName, 'type' => 'column_name');
+                    }
+                    unset($this->aOrganizedFields[$sColumnName]);
+                }
+            }
+        }
+    }
+
+    /**
+     * return a uniq file name create with datetime and random number in range 0-100000
+     *
+     */
+    function UniqFileName() {
+        $sUniqFileName = date('YmdHis', time()) . rand(1, 100000);
+        return $sUniqFileName;
+    }
+
+    /**
+     * Update a table Join (2PK with FK on other table)
+     * @param string $sSchema Schema's name
+     * @param string $sTable Table's name
+     * @param string $sFieldIdFromRequest Field's name for Delete row and common insert
+     * @param string $sFieldIdToUpdate Fild's name for insert list value
+     * @param string $sRole Role's name
+     * @param string $sNameList List's key in aValues
+     */
+    function updateJoinTable($sSchema, $sTable, $sFieldIdFromRequest, $sFieldIdToUpdate, $sRole, $sNameList) {
+
+        if (!isset($this->aValues[$sFieldIdFromRequest])) {
+            $this->aValues[$sFieldIdFromRequest] = $this->aValues['my_vitis_id'];
+        }
+        if ($this->aValues[$sNameList] !== null && $this->aValues[$sNameList] !== "") {
+            $aIdItems = explode("|", $this->aValues[$sNameList]);
+        } else {
+            $aIdItems = array();
+        }
+        $sMode = 'text';
+        if (is_numeric($this->aValues[$sFieldIdFromRequest]))
+            $sMode = 'integer';
+        $this->oConnection->oBd->delete($sSchema, $sTable, $sFieldIdFromRequest, $this->aValues[$sFieldIdFromRequest], $sMode);
+        foreach ($aIdItems as $aIdItem) {
+            $this->aValues[$sFieldIdToUpdate] = $aIdItem;
+            $aReturn = $this->genericPost($sSchema, $sTable, null, $sFieldIdFromRequest);
+        }
+
+        return $aReturn;
+    }
+
+    function deleteFromJoinTable($sSchema, $sTable, $sFieldIdFromRequest, $sFieldIdToUpdate, $sRole, $sNameList) {
+        $this->aValues[$sNameList] = array();
+        return $this->updateJoinTable($sSchema, $sTable, $sFieldIdFromRequest, $sFieldIdToUpdate, $sRole, $sNameList);
+    }
+
+    /**
+     * Save a file in public dir
+     * @param string $sFieldName Field's name form request for DB save
+     * @param string $sPath realtive path from public_dir
+     */
+    function postFileSave($sFieldName, $sPath, $sDir = null) {
+        $aReturn = array('sStatus' => 0, 'sMessage' => '');
+        if ($sDir === null) {
+            $sDir = $this->UniqFileName();
+        }
+        $sPictureDir = $this->aProperties['dir_export'] . $sPath;
+
+        $this->aValues[$sFieldName] = $sDir . "/" . $_FILES[$sFieldName]['name'];
+
+        $sFilePathName = $sPictureDir . $this->aValues[$sFieldName];
+
+        if (!is_dir($sPictureDir . $sDir)) {
+            mkdir($sPictureDir . $sDir, 0777, true);
+        }
+
+        if (!move_uploaded_file($_FILES[$sFieldName]['tmp_name'], $sFilePathName)) {
+            writeToErrorLog(ERROR_0031 . $_FILES[$sFieldName]['name'] . " " . $sFilePathName);
+            $aReturn = array('sStatus' => 1, 'sMessage' => WORKSPACE_ERROR_COPYING_FILE);
+        }
+
+        return $aReturn;
+    }
+
+    /**
+     * Update a file in public dir
+     * @param string $sFieldName Field's name from request for DB save
+     * @param string $sPath relative path from public_dir
+     * @param string $sSchema Schema's name
+     * @param string $sTable Table's name
+     * @param string $sFieldId Field's name for get path of file to update
+     */
+    function putFileUpdate($sFieldName, $sPath, $sSchema, $sTable, $sFieldId) {
+        if (array_key_exists($sFieldName . '_file', $this->aValues) && array_key_exists($sFieldName . '_name', $this->aValues)) {
+            $this->aFields = $this->getFields($sSchema, $sTable, $sFieldId);
+            $aDir = explode("/", $this->aFields[$sFieldName]);
+
+            if (count($aDir) === 1) {
+                array_unshift($aDir, $this->UniqFileName());
+            } else if (count($aDir) > 2) {
+                writeToErrorLog("ERROR: Too few folder for this file");
+            }
+
+            $sFilePathName = $this->aProperties['dir_export'] . $sPath . $aDir[0] . "/" . $this->aValues[$sFieldName . '_name'];
+            if (!is_Dir($this->aProperties['dir_export'] . $sPath . $aDir[0] . "/")) {
+                mkdir($this->aProperties['dir_export'] . $sPath . $aDir[0], 0777, true);
+            }
+            if (file_exists($this->aProperties['dir_export'] . $sPath . $aDir[0] . "/" . $aDir[1])) {
+                if ($aDir[0] . "/" . $aDir[1] !== $this->aValues[$sFieldName . '_name']) {
+                    @unlink($this->aProperties['dir_export'] . $sPath . $aDir[0] . "/" . $aDir[1]);
+                }
+            }
+            $fPicture = fopen($sFilePathName, "w+");
+            if (!fwrite($fPicture, $this->aValues[$sFieldName . '_file'])) {
+                writeToErrorLog("ERROR: picture save failed");
+            }
+            fclose($fPicture);
+            $this->aValues[$sFieldName] = $aDir[0] . "/" . $this->aValues[$sFieldName . "_name"];
+        }
+    }
+
+    /**
+     * Save a file in ws_data/$sVitisObjectName/documents/$sId/$sFieldName
+     * @param string $sFieldName
+     * @param string $sVitisObjectName
+     * @param string $sId
+     * @param string $aReturn
+     */
+    function postFileSaveWsData($sFieldName, $sVitisObjectName, $sId, $aReturn) {
+        if (!isset($aReturn)) {
+            $aReturn = array("sStatus" => 1);
+        }
+        if (!empty($_FILES[$sFieldName])) {
+            $sImageDir = $this->aProperties['ws_data_dir'] . '/vitis/' . $sVitisObjectName . '/documents/' . $sId . '/' . $sFieldName . '/' . $_FILES[$sFieldName]["name"];
+            $sDirPath = $this->createElementFilesFolder($sVitisObjectName, $sId);
+            $sDirColumnPath = $sDirPath . '/' . $sFieldName;
+            if (!is_dir($sDirColumnPath)) {
+                mkdir($sDirColumnPath, 0777, true);
+            }
+            $sErrorMessage = uploadFile($sFieldName, "", $sImageDir, $_FILES[$sFieldName]['size'] + 1);
+            if ($sErrorMessage != "") {
+                $aReturn = array("sStatus" => 0, "sMessage" => $sErrorMessage);
+                writeToErrorLog($sErrorMessage);
+            }
+        }
+        return $aReturn;
+    }
+
+    /**
+     * Update a file in ws_data/$sVitisObjectName/documents/$sId/$sFieldName
+     * @param string $sFieldName
+     * @param string $sVitisObjectName
+     * @param string $sId
+     * @param string $aReturn
+     */
+    function putFileUpdateWsData($sFieldName, $sVitisObjectName, $sId, $aReturn) {
+        if (!isset($aReturn)) {
+            $aReturn = array("sStatus" => 1);
+        }
+        if (!empty($this->aValues[$sFieldName . "_file"])) {
+
+            $sImageDir = $this->aProperties['ws_data_dir'] . '/vitis/' . $sVitisObjectName . '/documents/' . $sId . '/' . $sFieldName . '/' . $this->aValues[$sFieldName . "_name"];
+
+            // Crée les répertoires si ils n'existent pas
+            $sDirPath = $this->createElementFilesFolder($sVitisObjectName, $sId);
+            $sDirColumnPath = $sDirPath . '/' . $sFieldName;
+            if (!is_dir($sDirColumnPath)) {
+                mkdir($sDirColumnPath, 0777, true);
+            }
+
+            // la colonne $sFieldName vaudra le nom du fichier
+            $this->aValues[$sFieldName] = $this->aValues[$sFieldName . "_name"];
+            $fp = fopen($sImageDir, "w");
+            if (!$fp) {
+                return array(sStatus => 0, sMessage => WORKSPACE_ERROR_COPYING_FILE);
+            }
+            $bOK = fwrite($fp, $this->aValues[$sFieldName . "_file"]);
+            if (!$bOK) {
+                return array(sStatus => 0, sMessage => WORKSPACE_ERROR_COPYING_FILE);
+            }
+            $bOK = fclose($fp);
+            if (!$bOK) {
+                return array(sStatus => 0, sMessage => WORKSPACE_ERROR_COPYING_FILE);
+            }
+        }
+        return $aReturn;
+    }
+
+    function getTablePrivileges($sSchema, $sTable) {
+        $this->aTablePrivileges = $this->oConnection->getTableRights($sSchema, $sTable);
+    }
+
+    /**
+     * Create the element files container
+     * @param string $sVitisObjectName
+     * @param string $sId
+     * @return string Path to the created directory
+     */
+    function createElementFilesFolder($sVitisObjectName, $sId) {
+        // Répertoires présents ?
+        if (is_dir($this->aProperties['ws_data_dir'])) {
+            $sDirPath = $this->aProperties['ws_data_dir'] . '/vitis';
+            if (!is_dir($sDirPath)) {
+                mkdir($sDirPath, 0777, true);
+            }
+            $sDirPath = $sDirPath . '/' . $sVitisObjectName;
+            if (!is_dir($sDirPath)) {
+                mkdir($sDirPath, 0777, true);
+            }
+            $sDirPath = $sDirPath . '/documents';
+            if (!is_dir($sDirPath)) {
+                mkdir($sDirPath, 0777, true);
+            }
+            $sDirPath = $sDirPath . '/' . $sId;
+            if (!is_dir($sDirPath)) {
+                mkdir($sDirPath, 0777, true);
+            }
+        }
+
+        return $sDirPath;
+    }
+
+    /**
+     * Delete the documents binded to the elements specified in $aIds
+     * @param string $sVitisObjectName
+     * @param array $aIds
+     */
+    function deleteElementsDocuments($sVitisObjectName, $aIds) {
+        if (!isset($aIds)) {
+            if (!empty($this->aValues['idList'])) {
+                $aIds = explode("|", $this->aValues['idList']);
+            }
+            if (!empty($this->aPath['2'])) {
+                $aIds = array($this->aPath['2']);
+            }
+        }
+        for ($i = 0; $i < count($aIds); $i++) {
+            $sDir = $this->aProperties['ws_data_dir'] . '/vitis/' . $sVitisObjectName . '/documents/' . $aIds[$i];
+            if (is_dir($sDir)) {
+                clearDir($sDir);
+            }
+        }
+    }
+
+    /**
+     * Decode a JSON filter and returns an array witch contains
+     * the string request and the array parameters
+     * @param string $sJSONFilter JSON filter, can be passed by string, object or array
+     * @param string $sSchema
+     * @param string $sTable
+     * @return array
+     */
+    function decodeJSONFilter($sJSONFilter, $sSchema = null, $sTable = null) {
+
+        if (is_object($sJSONFilter) || is_array($sJSONFilter)) {
+            $sJSONFilter = json_encode($sJSONFilter);
+        }
+
+        $aJSONFilter = json_decode($sJSONFilter, true);
+        $sFilter = '';
+        $aParams = array();
+
+        // Valeurs par défaut si juste un operator est passé en paramètre
+        if (isset($aJSONFilter['column']) &&
+                isset($aJSONFilter['compare_operator'])) {
+            $aJSONFilter = array(
+                'relation' => 'AND',
+                'operators' => array($aJSONFilter)
+            );
+        }
+
+        if (empty($aJSONFilter['relation']) ||
+                !is_array($aJSONFilter['operators'])) {
+            if (strlen(trim($sJSONFilter)) > 0) {
+                writeToErrorLog(ERROR_0034 . ': missing argument on ' . $sJSONFilter);
+            }
+            return array('request' => $sFilter, 'params' => $aParams);
+        }
+
+        if (is_array($aJSONFilter['operators'])) {
+
+            // Vérifie relation
+            $sRelation = $this->checkRelationOperator($aJSONFilter['relation']);
+            if (empty($sRelation)) {
+                writeToErrorLog(ERROR_0034 . ': relation not valid');
+                return array('request' => $sFilter, 'params' => $aParams);
+            }
+
+            // Pour chacun des opérateurs
+            for ($i = 0; $i < count($aJSONFilter['operators']); $i++) {
+
+                // Filtre imbriquée ?
+                if (!empty($aJSONFilter['operators'][$i]['relation'])) {
+
+                    // Récupère récursivement le contenu du filtre imbriqué
+                    $aDecodedSubFilter = $this->decodeJSONFilter($aJSONFilter['operators'][$i], $sSchema, $sTable);
+
+                    // Ajout des paramètres
+                    foreach ($aDecodedSubFilter['params'] as $key => $value) {
+                        $aParams[$key] = $value;
+                    }
+
+                    // Ajout dans la requête
+                    if (strlen($sFilter) > 0) {
+                        $sFilter .= ' ' . $sRelation . ' ';
+                    } else {
+                        $sFilter .= '(';
+                    }
+                    $sFilter .= $aDecodedSubFilter['request'];
+                } else {
+
+                    $aOperator = $this->decodeOperator($aJSONFilter['operators'][$i], $sSchema, $sTable);
+
+                    if (!empty($aOperator)) {
+
+                        // Ajout des paramètres
+                        foreach ($aOperator['params'] as $key => $value) {
+                            $aParams[$key] = $value;
+                        }
+
+                        // Ajout dans la requête
+                        if (strlen($sFilter) > 0) {
+                            $sFilter .= ' ' . $sRelation . ' ';
+                        } else {
+                            $sFilter .= '(';
+                        }
+                        $sFilter .= $aOperator['request'];
+                    }
+                }
+            }
+            if (strlen($sFilter) > 0) {
+                $sFilter .= ')';
+            }
+        }
+
+        return array('request' => $sFilter, 'params' => $aParams);
+    }
+
+    /**
+     * Decode a filter operator and returns an array witch contains
+     * the string request and the array parameters
+     * @param array $aOperator
+     * @param string $sSchema
+     * @param string $sTable
+     * @return array
+     */
+    function decodeOperator($aOperator, $sSchema = null, $sTable = null) {
+
+        $sFilter = '';
+        $aParams = array();
+
+        $aOperator['value'] = $this->parseBools($aOperator['value']);
+
+        // Vérifications
+        if (empty($aOperator['column']) ||
+                empty($aOperator['compare_operator'])) {
+            return null;
+        }
+        if (!isset($aOperator['value']) || $aOperator['value'] == '') {
+            switch (strtoupper(trim($aOperator['compare_operator']))) {
+                case 'NULL':
+                case 'IS NULL':
+                case 'NOT NULL':
+                case 'IS NOT NULL':
+                    $aOperator['value'] = "";
+                    break;
+                default:
+                    if (strlen(trim(json_encode($aOperator))) > 0) {
+                        writeToErrorLog(ERROR_0034 . ': missing argument on ' . json_encode($aOperator));
+                    }
+                    return null;
+                    break;
+            }
+        }
+
+
+        // Vérifie compare_operator
+        $sCompare = $this->checkCompareOperator($aOperator['compare_operator']);
+        if (empty($sCompare)) {
+            writeToErrorLog(ERROR_0034 . ': compare_operator not valid');
+            null;
+        }
+
+        // Clées à utiliser en guise de variables
+        $sColumnKey = 'column_' . vitisUniqId();
+        $sValueKey = 'value_' . vitisUniqId();
+
+        switch ($sCompare) {
+            case 'IS NULL':
+            case 'IS NOT NULL':
+                // Ajoute les paramètres
+                $aParams[$sColumnKey] = array('value' => $aOperator['column'], 'type' => 'column_name');
+                // Ajoute à la requête
+                $sFilter .= '"[' . $sColumnKey . ']" ' . $sCompare;
+                break;
+            case 'IN':
+            case 'NOT IN':
+                if (is_array($aOperator['value'])) {
+                    $sInFilter = '';
+                    for ($i = 0; $i < count($aOperator['value']); $i++) {
+                        if (strlen($sInFilter) > 0) {
+                            $sInFilter .= ', ';
+                        }
+                        // Clée à utiliser en guise de variable
+                        $sValueKey = 'value_' . vitisUniqId() . $i;
+                        // Ajout du paramètre
+                        $aParams[$sValueKey] = array('value' => $aOperator['value'][$i], 'type' => 'string');
+                        // Ajout à la requête
+                        $sInFilter .= '[' . $sValueKey . ']';
+                    }
+                    // Ajout de la colonne
+                    $aParams[$sColumnKey] = array('value' => $aOperator['column'], 'type' => 'column_name');
+                    // Ajout à la requête
+                    $sFilter .= '"[' . $sColumnKey . ']" ' . $sCompare . ' (' . $sInFilter . ')';
+                }
+                break;
+            case 'LIKE':
+
+                // Ajoute les paramètres
+                $aParams[$sColumnKey] = array('value' => $aOperator['column'], 'type' => 'column_name');
+                $aParams[$sValueKey] = array('value' => $aOperator['value'], 'type' => 'quoted_string');
+
+                $sValueFilter = '[' . $sValueKey . ']';
+                $sColumnFilter = '"[' . $sColumnKey . ']"';
+
+                if (!empty($aOperator['compare_operator_options'])) {
+                    if ($aOperator['compare_operator_options']['case_insensitive'] == 'true' ||
+                            $aOperator['compare_operator_options']['case_insensitive'] == true) {
+
+                        $sValueFilter = 'LOWER(' . $sValueFilter . ')';
+                        $sColumnFilter = 'LOWER(' . $sColumnFilter . '::text)';
+                    }
+                }
+
+                // Ajoute à la requête
+                $sFilter .= $sColumnFilter . ' LIKE ' . $sValueFilter;
+
+                break;
+            case 'INTERSECT':
+
+                $sGeomDefKey = 'geom_def_' . vitisUniqId();
+                $sGeomColumnKey = 'geom_column_' . vitisUniqId();
+                $aParams[$sGeomDefKey] = array('value' => $aOperator['value'], 'type' => 'geometry');
+                $aParams[$sGeomColumnKey] = array('value' => $aOperator['column'], 'type' => 'column_name');
+
+                $sSQLGeom = "[" . $sGeomDefKey . "]";
+                $sSQLColumn = "[" . $sGeomColumnKey . "]";
+
+                // compare_operator_options
+                if (!empty($aOperator['compare_operator_options'])) {
+                    // source_proj
+                    if (!empty($aOperator['compare_operator_options']['source_proj'])) {
+                        $sSourceProjKey = 'source_proj_' . vitisUniqId();
+                        $aParams[$sSourceProjKey] = array('value' => $aOperator['compare_operator_options']['source_proj'], 'type' => 'integer');
+                        $sSQLSRID = "[" . $sSourceProjKey . "]::integer";
+                        $sSRID = $aOperator['compare_operator_options']['source_proj'];
+                    }
+                    // intersect_buffer
+                    if (!empty($aOperator['compare_operator_options']['intersect_buffer'])) {
+                        $sIntersectBufferKey = 'intersect_buffer' . vitisUniqId();
+                        $aParams[$sIntersectBufferKey] = array('value' => $aOperator['compare_operator_options']['intersect_buffer'], 'type' => 'integer');
+                        $sSQLBuffer = "[" . $sIntersectBufferKey . "]::float";
+                    }
+                    // intersect_buffer_geom_type
+                    if (!empty($aOperator['compare_operator_options']['intersect_buffer_geom_type'])) {
+                        $aIntersectTypes = explode('|', strtoupper($aOperator['compare_operator_options']['intersect_buffer_geom_type']));
+
+                        // Types necessitant un buffer
+                        $aTypesWithBuffer = array();
+                        for ($i = 0; $i < count($aIntersectTypes); $i++) {
+                            switch ($aIntersectTypes[$i]) {
+                                case 'POINT':
+                                    array_push($aTypesWithBuffer, 'ST_Point');
+                                    array_push($aTypesWithBuffer, 'ST_MultiPoint');
+                                    break;
+                                case 'LINE':
+                                    array_push($aTypesWithBuffer, 'ST_Linestring');
+                                    array_push($aTypesWithBuffer, 'ST_MultiLinestring');
+                                    break;
+                                case 'POLYGON':
+                                    array_push($aTypesWithBuffer, 'ST_Polygon');
+                                    array_push($aTypesWithBuffer, 'ST_MultiPolygon');
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+
+                        // Types qui ne necessitent pas de buffer
+                        $aExcludeBufferTypes = array(
+                            'ST_Point',
+                            'ST_MultiPoint',
+                            'ST_Linestring',
+                            'ST_MultiLinestring',
+                            'ST_Polygon',
+                            'ST_MultiPolygon'
+                        );
+                        for ($i = 0; $i < count($aTypesWithBuffer); $i++) {
+                            if (array_search($aTypesWithBuffer[$i], $aExcludeBufferTypes) !== false) {
+                                array_splice($aExcludeBufferTypes, array_search($aTypesWithBuffer[$i], $aExcludeBufferTypes), 1);
+                            }
+                        }
+
+                        // Ajout dans les paramètres
+                        $aPostgisIntersectWithoutBufferTypes = array();
+                        for ($ii = 0; $ii < count($aExcludeBufferTypes); $ii++) {
+                                $sPostgisGeomTypeKey = 'postgis_geom_type_' . vitisUniqId() . $i . $ii;
+                            $aParams[$sPostgisGeomTypeKey] = array('value' => $aExcludeBufferTypes[$ii], 'type' => 'string');
+                            array_push($aPostgisIntersectWithoutBufferTypes, "[" . $sPostgisGeomTypeKey . "]");
+                            }
+                        }
+                    }
+
+                // Si le SRID source n'est pas renseigné
+                if (empty($sSQLSRID)) {
+                    if (!empty($sSchema) && !empty($sTable)) {
+                        $sSRID = $this->getColumnProjection($sSchema, $sTable, $aOperator['column']);
+                        $sSourceProjKey = 'source_proj_' . vitisUniqId();
+                        $aParams[$sSourceProjKey] = array('value' => $sSRID, 'type' => 'integer');
+                        $sSQLSRID = "[" . $sSourceProjKey . "]::integer";
+                    } else {
+                        writeToErrorLog(ERROR_0034 . ': missing $sSchema and $sTable params');
+                        break;
+                    }
+                }
+
+                if (empty($sSRID)) {
+                    $sSRID = 2154;
+                }
+                // Géométrie
+                if ($sSRID === '4326') {
+                    $sIntersectFilter = 'ST_GeomFromEWKT(' . $sSQLGeom . ')::geography';
+                } else {
+                    $sIntersectFilter = 'ST_GeomFromEWKT(' . $sSQLGeom . ')';
+                }
+
+                // Buffer de sélection
+                if (!empty($sSQLBuffer)) {
+                    // Mise en place du buffer
+                    if ($sSRID === '4326') {
+                        $sBufferFilter = 'ST_Buffer(' . $sIntersectFilter . ', ' . $sSQLBuffer . ')::geometry';
+                    } else {
+                        $sBufferFilter = 'ST_Buffer(' . $sIntersectFilter . ', ' . $sSQLBuffer . ')';
+                    }
+                        }
+                // Reprojection
+                if (!empty($sSQLSRID)) {
+                    $sIntersectFilter = 'ST_Transform(' . $sIntersectFilter . ', ' . $sSQLSRID . ')';
+                    if (!empty($sBufferFilter)) {
+                        $sBufferFilter = 'ST_Transform(' . $sBufferFilter . ', ' . $sSQLSRID . ')';
+                }
+                }
+                // Intersection
+                if (!empty($sSQLColumn)) {
+                    $sIntersectFilter = 'ST_Intersects(' . $sIntersectFilter . ', ' . $sSQLColumn . ')';
+                    if (!empty($sBufferFilter)) {
+                        $sBufferFilter = 'ST_Intersects(' . $sBufferFilter . ', ' . $sSQLColumn . ')';
+                }
+                }
+
+                // Buffer de sélection
+                if (!empty($sBufferFilter) && count($aPostgisIntersectWithoutBufferTypes) > 0) {
+                    $sNoBufferTypesFilter = '';
+                    for ($i = 0; $i < count($aPostgisIntersectWithoutBufferTypes); $i++) {
+                        if ($i > 0) {
+                            $sNoBufferTypesFilter .= " AND ";
+                        }
+                        $sNoBufferTypesFilter .= "ST_GeometryType(" . $sSQLColumn . ")!=" . $aPostgisIntersectWithoutBufferTypes[$i] . "";
+                    }
+                    $sIntersectFilter = '(' . $sIntersectFilter . ') OR ((' . $sNoBufferTypesFilter . ') AND ' . $sBufferFilter . ')';
+                }
+
+                // Ajout au filtre
+                $sFilter .= '(' . $sIntersectFilter . ')';
+                break;
+            default:
+                // Ajoute les paramètres
+                $aParams[$sColumnKey] = array('value' => $aOperator['column'], 'type' => 'column_name');
+                if (is_bool($aOperator['value']))
+                    $aParams[$sValueKey] = array('value' => var_export($aOperator['value'], true), 'type' => 'boolean');
+                else
+                    $aParams[$sValueKey] = array('value' => $aOperator['value'], 'type' => 'string');
+
+                // Ajoute à la requête
+                $sFilter .= '"[' . $sColumnKey . ']"' . $sCompare . '[' . $sValueKey . ']';
+                break;
+        }
+
+        return array('request' => $sFilter, 'params' => $aParams);
+    }
+
+    /**
+     * Get a column projection
+     * @param string $sSchema
+     * @param string $sTable
+     * @param string $sColumn
+     * @return string
+     */
+    function getColumnProjection($sSchema, $sTable, $sColumn) {
+        return $this->oConnection->oBd->getColumnSRID($sSchema, $sTable, $sColumn);
+    }
+
+    /**
+     * Check the given compare operator and return
+     * a well formed compare operator string
+     * @param string $sCompareOperator
+     * @return string
+     */
+    function checkCompareOperator($sCompareOperator) {
+        $sCompare = null;
+        switch (strtoupper(trim($sCompareOperator))) {
+            case '=':
+                $sCompare = '=';
+                break;
+            case '!=':
+                $sCompare = '!=';
+                break;
+            case '<>':
+                $sCompare = '<>';
+                break;
+            case '>=':
+                $sCompare = '>=';
+                break;
+            case '<=':
+                $sCompare = '<=';
+                break;
+            case '>':
+                $sCompare = '>';
+                break;
+            case '<':
+                $sCompare = '<';
+                break;
+            case 'IN':
+                $sCompare = 'IN';
+                break;
+            case 'NOT IN':
+                $sCompare = 'NOT IN';
+                break;
+            case 'NULL':
+            case 'IS NULL':
+                $sCompare = 'IS NULL';
+                break;
+            case 'NOT NULL':
+            case 'IS NOT NULL':
+                $sCompare = 'IS NOT NULL';
+                break;
+            case 'LIKE':
+                $sCompare = 'LIKE';
+                break;
+            case 'INTERSECT':
+                $sCompare = 'INTERSECT';
+                break;
+            default:
+                break;
+        }
+        return $sCompare;
+    }
+
+    function boolToString($boolVal = false) {
+        return ($boolVal ? 'true' : 'false');
+    }
+
+    function parseBools($value) {
+        if (is_bool($value)) {
+            $value = $this->boolToString($value);
+        }
+        return $value;
+    }
+
+    /**
+     * Check the given relation operator and return
+     * a well formed relation operator string
+     * @param string $sRelationOperator
+     * @return string
+     */
+    function checkRelationOperator($sRelationOperator) {
+        $sRelation = null;
+        switch (strtoupper(trim($sRelationOperator))) {
+            case 'AND':
+                $sRelation = 'AND';
+                break;
+            case 'OR':
+                $sRelation = 'OR';
+                break;
+            default:
+                break;
+        }
+        return $sRelation;
+    }
+
+    function pictureResampler($sFilePath, $iDstWidth, $iDstHeight, $iCropX = 0, $iCropY = 0, $iOffsetX = 0, $iOffsetY = 0) {
+        // récupération de l'extension pour ouverture du fichier
+        $sType = strtolower(substr(strrchr($sFilePath, "."), 1));
+        if ($sType == 'jpeg' || $sType == 'JPG') {
+            $sType = 'jpg';
+        }
+        // Récupération du format de la source
+        list($iCurrentWidth, $iCurrentHeight) = getimagesize($sFilePath);
+        list($width, $height) = $this->sizeCalculator($iCurrentWidth, $iCurrentHeight, $iDstWidth, $iDstHeight);
+        // Ouverture de la ressource return false si format non réconnu
+        switch ($sType) {
+            case 'bmp': $img = imagecreatefromwbmp($sFilePath);
+                break;
+            //case 'gif': $img = imagecreatefromgif($sFilePath);
+            //    break;
+            case 'jpg': $img = imagecreatefromjpeg($sFilePath);
+                break;
+            case 'png': $img = imagecreatefrompng($sFilePath);
+                break;
+            default :
+                return false;
+        }
+        //Suppression du fichier sinon problème de réouverture après si jpg et doublon si autre format
+        unlink($sFilePath);
+
+        if ($img === false) {
+            writeToErrorLog("ERROR : Vitis cannot open this file");
+            return false;
+        }
+        // création de l'image de sortie
+        $image_p = imagecreatetruecolor($width, $height);
+        $white = imagecolorallocate($image_p, 255, 255, 255);
+        imagefill($image_p, 0, 0, $white);
+        // resizer
+        if (!imagecopyresampled($image_p, $img, $iOffsetX, $iOffsetY, $iCropX, $iCropY, $width, $height, $iCurrentWidth, $iCurrentHeight)) {
+            writeToErrorLog("ERROR : Vitis cannot resampling the picture");
+            return false;
+        }
+        // transformation au format jpeg pour supprimer l'alpha et gagner en taille du fichier
+        $aPath = explode(".", $sFilePath);
+        $aPath[count($aPath) - 1] = "jpg";
+        $dst = implode(".", $aPath);
+        // Enregistrement du jpeg
+        if (!imagejpeg($image_p, $dst)) {
+            writeToErrorLog("ERROR : Vitis failed to write this picture");
+            return false;
+        }
+        // Libération espace mémoire
+        imagedestroy($image_p);
+        imagedestroy($img);
+        // retour du nouveau nom de fichier
+        return $dst;
+    }
+
+    function sizeCalculator($iCurrentWidth, $iCurrentHeight, $iTargetWidth, $iTargetHeight) {
+        $iWidth = $iTargetWidth;
+        $iHeight = $iTargetHeight;
+        // si image plus grande on retourne les cibles
+        if ($iCurrentWidth > $iTargetWidth && $iCurrentHeight > $iTargetHeight) {
+            return array($iTargetWidth, $iTargetHeight);
+        }
+        // On détermine si on conserve la largeur ou la hauteur
+        if ($iCurrentWidth > $iTargetWidth && $iCurrentHeight < $iTargetHeight) {
+            $iHeight = $iCurrentHeight * $iTargetWidth / $iCurrentWidth;
+            $iWidth = $iTargetWidth;
+        } else if ($iCurrentWidth < $iTargetWidth && $iCurrentHeight > $iTargetHeight) {
+            $iHeight = $iTargetHeight;
+            $iWidth = $iCurrentWidth * $iTargetHeight / $iCurrentHeight;
+        } else {
+            // dans ce cas les les deux distance sont plus petite que le but on
+            // calcul donc le delta pour déterminer quel coté est gardé
+            $fDeltaWidth = $iCurrentWidth / $iTargetWidth;
+            $fDeltaHeight = $iCurrentHeight / $iTargetHeight;
+            if ($iDeltaWidth < $iDeltaHeight) {
+                $iHeight = $iCurrentHeight;
+                $iWidth = $iCurrentHeight * $iTargetWidth / $iTargetHeight;
+            } else {
+                $iWidth = $iCurrentWidth;
+                $iHeight = $iCurrentWidth * $iTargetHeight / $iTargetWidth;
+            }
+        }
+
+        return array($iWidth, $iHeight);
+    }
+
+    /**
+     * Structure date in selectedField array
+     * @param string $sField
+     * @param string $sDateType
+     * \return selected structure
+     */
+    function getDateSelectedFields($sField, $sDateType){
+        if (!empty($this->oConnection->sTimeZone) && !empty($this->oConnection->sFormatDate) && !empty($sDateType))
+            return "to_char(".$sField." AT TIME ZONE '".$this->oConnection->sTimeZone."', '".getDatePattern($this->oConnection->sFormatDate, $sDateType)."') as ".$sField;
+        else
+            return $sField;
+    }
+}
+?>
diff --git a/vas/rest/ws/vitis/Vitis.class.sql.inc b/vas/rest/ws/vitis/Vitis.class.sql.inc
new file mode 100755
index 00000000..3a99fc0f
--- /dev/null
+++ b/vas/rest/ws/vitis/Vitis.class.sql.inc
@@ -0,0 +1,60 @@
+<?php
+
+//Définition des requêtes de l'api Vitis
+$aSql['checkIP'] = "SELECT user_id, ip_constraint, restriction FROM [sSchemaFramework].v_user WHERE lower(login) = [sLogin]";
+$aSql['updateLastConnection'] = "update [sSchemaFramework].v_user set last_connection = [date] where user_id = [user_id]";
+$aSql['getGroups'] = "SELECT v_user_group_by_rights.group_id, \"group\".name FROM [sSchemaFramework].v_user_group_by_rights LEFT JOIN [sSchemaFramework].group ON v_user_group_by_rights.group_id = \"group\".group_id WHERE v_user_group_by_rights.user_id = [user_id]";
+$aSql['loginUnique'] = 'SELECT UPPER("login") FROM [sSchemaFramework]."v_user" where UPPER("login")=UPPER([sLoginUser])';
+$aSql['getLoginbyId'] = 'SELECT "login" FROM [sSchemaFramework]."v_user" where user_id=[user_id]';
+$aSql['getTableColumn'] = 'SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS where table_schema = \'[sSchemaFramework]\' and table_name= \'[sTable]\'';
+$aSql['getUserPrivileges'] = 'SELECT groname FROM pg_user s LEFT OUTER JOIN pg_group g on (s.usesysid = any(g.grolist) )inner join [sSchemaFramework].v_user on "v_user".login = usename where user_id = [user_id]';
+$aSql['listDomain'] = 'SELECT distinct domain, alias FROM [sSchemaFramework].domain WHERE "type" = \'AD\'';
+$aSql['getAdId'] = 'SELECT domain_id FROM [sSchemaFramework].domain WHERE "domain" = [domain]';
+$aSql['createRolname'] = 'CREATE ROLE [sDomain] NOSUPERUSER INHERIT NOCREATEDB CREATEROLE;';
+$aSql['getInfoRolname'] = 'SELECT * FROM pg_catalog.pg_roles WHERE rolname = [sDomain]';
+// Groups
+$aSql['getGroupUsers'] = "SELECT v_user_group_by_rights.user_id, \"v_user\".login FROM [sSchemaFramework].v_user_group_by_rights LEFT JOIN [sSchemaFramework].v_user ON v_user_group_by_rights.user_id = \"v_user\".user_id WHERE v_user_group_by_rights.group_id = [group_id]";
+$aSql['insertGroupUsers'] = "INSERT INTO [sSchemaFramework].v_user_group_by_rights(user_id, group_id) VALUES([user_id], [group_id])";
+$aSql['getGroupId'] = "SELECT group_id FROM [sSchemaFramework].group WHERE lower(name) = [sName]";
+// Privileges
+$aSql['getUsersPrivileges'] = 'SELECT [sSchemaFramework].v_user.user_id, [sSchemaFramework].v_user.login FROM pg_group RIGHT JOIN pg_user ON pg_user.usesysid = any(pg_group.grolist) RIGHT JOIN [sSchemaFramework].v_user ON [sSchemaFramework].v_user.login = pg_user.usename WHERE groname = [vitis_user] AND [sSchemaFramework].v_user.login != [excludeLogin]';
+$aSql['getUsename'] = 'SELECT DISTINCT "usename" FROM pg_group RIGHT JOIN pg_user ON pg_user.usesysid = any(pg_group.grolist) RIGHT JOIN [sSchemaFramework].v_user ON [sSchemaFramework].v_user.login = pg_user.usename WHERE "groname" = [sId] AND [sSchemaFramework].v_user.login != [excludeLogin]';
+$aSql['getUsers'] = "SELECT login FROM [sSchemaFramework].v_user WHERE user_id IN([user_id])";
+// Users
+$aSql['insertUserGroups'] = "INSERT INTO [sSchemaFramework].v_user_group_by_rights(user_id, group_id) VALUES([user_id], [group_id])";
+$aSql['grantPrivilege'] = 'GRANT [sId] TO [sValue]';
+$aSql['grantCREATEROLE'] = 'ALTER USER [sValue] CREATEROLE';
+$aSql['revokePrivilege'] = 'REVOKE [sId] FROM [sValue]';
+$aSql['revokeCREATEROLE'] = 'ALTER USER [sValue] NOCREATEROLE';
+$aSql['deleteUserGroups'] = "DELETE FROM [sSchemaFramework].v_user_group_by_rights WHERE user_id=[user_id]";
+$aSql['userPrivileges'] = "SELECT pg_group.grosysid,pg_group.groname FROM pg_group,pg_user,[sSchemaFramework].v_user,[sSchemaFramework].privileges WHERE pg_user.usesysid = any(pg_group.grolist) AND [sSchemaFramework].v_user.login = pg_user.usename AND pg_group.groname=[sSchemaFramework].privileges.rolname AND [sSchemaFramework].v_user.login = [login] AND pg_group.groname NOT IN([sExcludePrivileges]) ORDER BY groname";
+$aSql['userCreateRole'] = 'ALTER ROLE [login] CREATEROLE';
+$aSql['userNoCreateRole'] = 'ALTER ROLE [login] NOCREATEROLE';
+$aSql['grantUser'] = 'GRANT [sLdapName] TO [sLogin]';
+$aSql['getLogin'] = 'SELECT login,user_id FROM [sSchemaName].[sName] WHERE lower(login) = [sLogin]';
+$aSql['userApplicationPrivileges'] = "SELECT pg_group.grosysid,pg_group.groname FROM pg_group,pg_user,[sSchemaFramework].v_user,[sSchemaFramework].privileges WHERE pg_user.usesysid = any(pg_group.grolist) AND [sSchemaFramework].v_user.login = pg_user.usename AND pg_group.groname=[sSchemaFramework].privileges.rolname AND [sSchemaFramework].v_user.login = [login] ORDER BY groname";
+$aSql['getAllUserPrivileges'] = "SELECT DISTINCT pg_group.grosysid,pg_group.groname FROM pg_group,pg_user,[sSchemaFramework].v_user,[sSchemaFramework].privileges WHERE pg_user.usesysid = any(pg_group.grolist) AND pg_user.usename = [login]";
+// Modes
+$aSql['updateModesIndex'] = "UPDATE [sSchemaName].vm_mode_rolname SET index=[index] WHERE mode_id=[mode_id]";
+// Columns
+$aSql['getTableColumns'] = 'SELECT vm_table_field.table_field_id, name, translation as field_label, sortable, resizeable, "index",  width, align, template FROM [sSchemaFramework].vm_table_field INNER JOIN [sSchemaFramework].vm_translation ON vm_table_field.label_id = vm_translation.translation_id WHERE ressource_id=[sRessource] and lang=[language] ORDER BY "index"';
+$aSql['getTableActions'] = 'SELECT button_class, table_button_id, translation as button_label, event FROM [sSchemaFramework].vm_table_button INNER JOIN [sSchemaFramework].vm_translation ON vm_table_button.label_id = vm_translation.translation_id WHERE ressource_id=[sRessource] and lang=[language] ORDER BY table_button_id';
+$aSql['getColumns'] = 'SELECT vm_table_field.table_field_id, name, translation as field_label, sortable, resizeable, "index",  width, align, table_name FROM [sSchemaFramework].vm_table_field INNER JOIN [sSchemaFramework].vm_translation ON vm_table_field.label_id = vm_translation.translation_id WHERE lang=\'[language]\' ORDER BY table_name, "index"';
+$aSql['getGeometryColumns'] = 'SELECT f_geometry_column FROM geometry_columns WHERE f_table_schema = \'[sSchemaFramework]\' AND f_table_name = \'[sTable]\'';
+// Tabs
+$aSql['getModeTabs'] = "SELECT vm_translation.translation as label, \"index\", event, replace(substring(event from '''[a-zA-Z_]+'''), '''', '') AS name FROM [sSchemaFramework].vm_tab LEFT JOIN [sSchemaFramework].vm_translation ON vm_tab.label_id = vm_translation.translation_id where mode_id='[mode_id]' and vm_translation.lang='[language]' order by \"index\"";
+$aSql['getTabs'] = "SELECT vm_translation.translation as label, \"index\", event, replace(substring(event from '''[a-zA-Z_]+'''), '''', '') AS name, mode_id FROM [sSchemaFramework].vm_tab LEFT JOIN [sSchemaFramework].vm_translation ON vm_tab.label_id = vm_translation.translation_id where vm_translation.lang='[language]' order by mode_id, \"index\"";
+// Sections
+$aSql['getTabSections'] = "SELECT table_name, link_table_name, name, vm_translation.translation as label, \"index\", event FROM [sSchemaFramework].vm_section LEFT JOIN [sSchemaFramework].vm_translation ON vm_section.label_id = vm_translation.translation_id WHERE table_name='[table_name]' AND vm_translation.lang='fr' ORDER BY \"index\"";
+$aSql['getSections'] = "SELECT table_name, link_table_name, name, vm_translation.translation as label, \"index\", event FROM [sSchemaFramework].vm_section LEFT JOIN [sSchemaFramework].vm_translation ON vm_section.label_id = vm_translation.translation_id WHERE vm_translation.lang='fr' ORDER BY table_name, \"index\"";
+// Logs
+$aSql['getApplicationModules'] = "SELECT module_name FROM [sSchemaFramework].vm_application_module WHERE application_name=[application_name];";
+// Domains
+$aSql['getUserGroups'] = 'SELECT [sSchemaFramework].v_user_group_by_rights."group_id", [sSchemaFramework].v_user_group_by_rights."user_id", [sSchemaFramework].group."name" FROM [sSchemaFramework].v_user_group_by_rights LEFT JOIN [sSchemaFramework].group ON [sSchemaFramework].v_user_group_by_rights."group_id"=[sSchemaFramework].group."group_id" WHERE [sSchemaFramework].v_user_group_by_rights."user_id" = [iUserId] ORDER BY "name"';
+$aSql['getUserLogin'] = 'SELECT login FROM [sSchemaFramework].v_user WHERE user_id = [iUserId]';
+
+$aSql['getTablePrivileges'] = 'SELECT grantee FROM information_schema.role_table_grants WHERE table_name=\'[sTable]\' and table_schema = \'[sSchema]\' and privilege_type = \'[sType]\'';
+// PrivateToken
+$aSql['getUserConnectionPrivileges'] = 'SELECT * FROM pg_group WHERE groname=\'vitis_user\' AND ((SELECT usesysid FROM pg_user WHERE usename=[sLogin]) = ANY (grolist));';
+$aSql['checkUser'] = 'SELECT user_id FROM [sSchemaFramework].v_user WHERE lower(login) = [sLogin]';
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/VitisSection.class.inc b/vas/rest/ws/vitis/VitisSection.class.inc
new file mode 100755
index 00000000..cd1e1840
--- /dev/null
+++ b/vas/rest/ws/vitis/VitisSection.class.inc
@@ -0,0 +1,112 @@
+<?php
+
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'Tab.class.inc';
+require_once 'Mode.class.inc';
+
+/**
+ * \file VitisSection.class.inc
+ * \class VitisSection
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the VitisSection php class
+ *
+ * This class defines operation for one VitisSection
+ * 
+ */
+class VitisSection extends Vitis {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("section_id", "tab_id", "event", "index", "label", "name", "link_table_name", "template", "ressource_id");
+    }
+
+    /**
+     * @SWG\Get(path="/vitissections/{section_id}", 
+     *   tags={"VitisSections"},
+     *   summary="Get VitisSection",
+     *   description="Request to get VitisSection by mode id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="section_id",
+     *     in="path",
+     *     description="section_id name",
+     *     required=true,
+     *     type="string",
+     *   ),
+     *   @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/vitissections")
+     *     )
+     *  )
+     */
+
+    /**
+     * get informations about table v_sections
+     */
+    function GET() {
+        require $this->sRessourcesFile;
+        $this->aFields = $this->getFields($this->aProperties['schema_framework'], "v_section", "section_id");
+
+        if (empty($this->aFields['ressource_id'])) {
+            if (!empty($this->aFields['tab_id'])) {
+
+                $aTabPath = array("vitis", "tabs", $this->aFields['tab_id']);
+                $aTabValues = $this->aValues;
+                $aTabValues['my_vitis_id'] = $this->aFields['tab_id'];
+
+                $oTab = new Tab($aTabPath, $aTabValues, $this->aProperties, $this->oConnection);
+                $oTab->GET();
+
+                $aTabFields = $oTab->aFields;
+
+                $this->aFields['ressource_id'] = $aTabFields['ressource_id'];
+                $this->aFields['mode_id'] = $aTabFields['mode_id'];
+                $this->aFields['tab_name'] = $aTabFields['name'];
+                $this->aFields['sorted_by'] = $aTabFields['sorted_by'];
+
+                $aModePath = array("vitis", "modes", $aTabFields['mode_id']);
+                $aModeValues = $this->aValues;
+                $aModeValues['my_vitis_id'] = $aTabFields['mode_id'];
+
+                $oMode = new Mode($aModePath, $aModeValues, $this->aProperties, $this->oConnection);
+                $oMode->GET();
+
+                $aModeFields = $oMode->aFields;
+                $this->aFields['module_name'] = $aModeFields['module_name'];
+                $this->aFields['application_name'] = $aModeFields['application_name'];
+            }
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/VitisSections.class.inc b/vas/rest/ws/vitis/VitisSections.class.inc
new file mode 100755
index 00000000..fb91cfe1
--- /dev/null
+++ b/vas/rest/ws/vitis/VitisSections.class.inc
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * \file VitisSections.class.inc
+ * \class VitisSections
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the VitisSections php class
+ *
+ * This class defines Rest Api to Vitis sections
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'VitisSection.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class VitisSections extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/VitisSections",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/VitisSections")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="VitisSections",
+     *   description="Operations about VitisSections"
+     * )
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/VitisSections")
+     *     )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array("section_id", "tab_id", "event", "index", "label", "name", "link_table_name", "template", "ressource_id", "tab_name", "mode_id");
+    }
+
+    /**
+     * @SWG\Get(path="/vitissections",
+     *   tags={"VitisSections"},
+     *   summary="Get VitisSections",
+     *   description="Request to get VitisSections",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/VitisSections")
+     *     )
+     *  )
+     */
+
+    /**
+     * get VitisSections
+     * @return VitisSections
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_framework'], "v_section", "section_id");
+        return $aReturn['sMessage'];
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/WebServices.class.inc b/vas/rest/ws/vitis/WebServices.class.inc
new file mode 100755
index 00000000..09331cbb
--- /dev/null
+++ b/vas/rest/ws/vitis/WebServices.class.inc
@@ -0,0 +1,452 @@
+<?php
+
+/**
+ * \file WebServices.class.inc
+ * \class WebServices
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ * \author Armand Bahi <armand.bahi@veremes.com>.
+ *
+ * 	\brief This file contains the WebServices php class
+ *
+ * This class defines Rest Api to Vitis WebServices
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class WebServices extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/WebServices",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/WebServices")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="WebServices",
+     *   description="Operations about WebServices"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+//        $this->aSelectedFields = Array("web_service", "module", "name", "description", "fields", "columns", "objects", "actions");
+        $this->aRessourceFields = Array("ressource_id", "module", "name", "description", "fields", "columns", "objects", "actions");
+    }
+
+    /**
+     * @SWG\Get(path="/webservices",
+     *   tags={"WebServices"},
+     *   summary="Get WebServices",
+     *   description="Request to get webservices",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x_vm_json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/webservices")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/webservices/{web_service}", 
+     *   tags={"WebServices"},
+     *   summary="Get WebService",
+     *   description="Request to get WebService by id",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x_vm_json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="web_service",
+     *     in="path",
+     *     description="webservice name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/webservices")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/webservices/{web_service}/ressources", 
+     *   tags={"WebServices"},
+     *   summary="Get ressources list",
+     *   description="Request to get ressources list",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x_vm_json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="web_service",
+     *     in="path",
+     *     description="webservice name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/webservices")
+     *     )
+     *  )
+     */
+    /**
+     * @SWG\Get(path="/webservices/{web_service}/ressources/{ressource}", 
+     *   tags={"WebServices"},
+     *   summary="Get ressources infos",
+     *   description="Request to get ressources infos",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x_vm_json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="web_service",
+     *     in="path",
+     *     description="webservice name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="ressource",
+     *     in="path",
+     *     description="ressource name",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/webservices")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Columns
+     * @return Columns
+     */
+    function GET() {
+        if ($this->oConnection->oError == null) {
+            require("../doc/vendor/autoload.php");
+
+            //$sWebServiceName = '';
+            if (!empty($this->aPath[2]))
+                $sWebServiceName = $this->aPath[2];
+            $sRessourceName = '';
+            if (!empty($this->aPath[4]))
+                $sRessourceName = $this->aPath[4];
+
+            if (!empty($sRessourceName)) {
+                // infos de la ressource
+                $this->getRessourceInfos($sWebServiceName, $sRessourceName);
+            } else if (!empty($this->aPath[3])) {
+                // liste des ressources
+                $this->getRessourceInfos($sWebServiceName, $sRessourceName);
+            } else if (!empty($sWebServiceName)) {
+                // infos du web service
+                $aAttributs = array();
+                if (!empty($this->aValues['attributs'])) {
+                    $aAttributs = explode("|", $this->aValues['attributs']);
+                }
+                $oWebService = $this->getWebServiceInfos($sWebServiceName, $aAttributs);
+                array_push($this->aObjects, $oWebService);
+            } else {
+                // liste des web services
+                // Tableau web services
+                $aWebServices = $this->getWebServicesList();
+
+                $aAttributs = array();
+                if (!empty($this->aValues['attributs'])) {
+                    $aAttributs = explode("|", $this->aValues['attributs']);
+                }
+                // Ajout dans l'output
+                for ($i = 0; $i < count($aWebServices); $i++) {
+                    $oWebService = $this->getWebServiceInfos($aWebServices[$i], $aAttributs);
+                    array_push($this->aObjects, $oWebService);
+                }
+            }
+
+
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        } else {
+            http_response_code(403);
+            $aXmlRacineAttribute['status'] = 0;
+            $this->aFields['error'] = "ERROR : invalid token";
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        return $sMessage;
+    }
+
+    /**
+     * Get the web services list
+     * @return array list of the web services
+     */
+    function getWebServicesList() {
+        $aWebServices = [];
+        if (is_dir("./ws")) {
+            $aDir = scandir("./ws");
+            foreach ($aDir as $sDir) {
+                if ($sDir != "." && $sDir != "..") {
+                    array_push($aWebServices, $sDir);
+                }
+            }
+        } else
+            writeToErrorLog('scandir(./ws): failed to open dir');
+        return $aWebServices;
+    }
+
+    /**
+     * Get the webservice infos
+     * @param string $sWebServiceName
+     * @param array $sAttributs
+     * @return \WebService object witch contains aFields = infos
+     */
+    function getWebServiceInfos($sWebServiceName, $aAttributs) {
+        $swagger = \Swagger\scan('./ws/' . $sWebServiceName . '/overview.phtml');
+        $aServer = explode("://", $this->aProperties["web_server_name"]);
+        $swagger = str_replace("[service_alias]", $this->aProperties["services_alias"], $swagger);
+        $swagger = str_replace("[protocol]", $aServer[0], $swagger);
+        $swagger = str_replace("[server]", $aServer[1], $swagger);
+        $oJson = json_decode($swagger)->info;
+        $oJson->name = $sWebServiceName;
+
+        if (count($aAttributs) > 0) {
+            foreach ($oJson as $key => $value) {
+                if (!in_array($key, $aAttributs)) {
+                    unset($oJson->$key);
+                }
+            }
+        }
+
+        $oWebService = new WebService($this->aPath, $this->aValues, $this->aProperties);
+        $oWebService->aFields = $oJson;
+
+        return $oWebService;
+    }
+
+    /**
+     * Get the ressources list
+     * @param string $sWebServiceName
+     * @return array list of the ressources
+     */
+    function getRessourcesList($sWebServiceName) {
+
+        $swagger = \Swagger\scan('./ws/' . $sWebServiceName);
+        $aServer = explode("://", $this->aProperties["web_server_name"]);
+        $swagger = str_replace("[service_alias]", $this->aProperties["services_alias"], $swagger);
+        $swagger = str_replace("[protocol]", $aServer[0], $swagger);
+        $swagger = str_replace("[server]", $aServer[1], $swagger);
+        $oJson = json_decode($swagger)->paths;
+
+        $aRessources = [];
+        foreach ($oJson as $key => $value) {
+            if (isset($value->get)) {
+                if (strpos($key, '{') === false) {
+                    array_push($aRessources, substr($key, 1));
+                }
+            }
+        }
+
+        return $aRessources;
+    }
+
+    /**
+     * Get the ressource infos, if sRessourceName is not provided, get the infos of all the ressources
+     * @param string $sWebServiceName
+     * @param string $sRessourceName
+     */
+    function getRessourceInfos($sWebServiceName, $sRessourceName) {
+
+        if (isset($this->aValues['attributs'])) {
+            $aAttributs = explode("|", $this->aValues['attributs']);
+            $aFields = array_intersect($aAttributs, $this->aRessourceFields);
+        } else {
+            $aFields = $this->aRessourceFields;
+        }
+
+        $swagger = \Swagger\scan('./ws/' . $sWebServiceName);
+        $aServer = explode("://", $this->aProperties["web_server_name"]);
+        $swagger = str_replace("[service_alias]", $this->aProperties["services_alias"], $swagger);
+        $swagger = str_replace("[protocol]", $aServer[0], $swagger);
+        $swagger = str_replace("[server]", $aServer[1], $swagger);
+        $oJson = json_decode($swagger);
+
+        foreach ($oJson->tags as $value) {
+            if (strtolower($sWebServiceName . '/' . $sRessourceName) == strtolower($sWebServiceName . "/" . $value->name) || $sRessourceName === "") {
+                if (file_exists("./ws/" . $sWebServiceName . "/" . $value->name . ".class.inc")) {
+                    require_once("./ws/" . $sWebServiceName . "/" . $value->name . ".class.inc");
+                    $sClassName = $value->name;
+                    $sClass = new ReflectionClass($value->name);
+                    // $sClass = new $sClassName($this->aPath, $this->aValues, $this->aProperties);
+                    if (in_array("ressource_id", $aFields)) {
+                        $sClass->aFields["ressource_id"] = strtolower($sWebServiceName . "/" . $value->name);
+                    }
+                    if (in_array("module", $aFields)) {
+                        $sClass->aFields["module"] = $sWebServiceName;
+                    }
+                    if (in_array("name", $aFields)) {
+                        $sClass->aFields["name"] = $value->name;
+                    }
+                    if (in_array("description", $aFields)) {
+                        $sClass->aFields["description"] = $value->description;
+                    }
+                    if (in_array("fields", $aFields)) {
+                        $sClass->aFields["fields"] = "";
+                        if (!empty($aRessourceFields)) {
+                            foreach ($sClass->aRessourceFields as $sFields) {
+                                if (strpos($sFields, " as ")) {
+                                    $field = explode(" as ", $sFields)[1];
+                                } else {
+                                    $field = $sFields;
+                                }
+                                if ($sClass->aFields["fields"] == "") {
+                                    $sClass->aFields["fields"] = $field;
+                                } else {
+                                    $sClass->aFields["fields"] .= ", " . $field;
+                                }
+                            }
+                        }
+                    }
+                    if (in_array("columns", $aFields)) {
+                        require_once 'Columns.class.inc';
+                        $oColumn = new Columns($this->aPath, array("ressource_id" => $sClass->aFields["ressource_id"], "module" => $sWebServiceName), $this->aProperties, $this->oConnection);
+                        $oColumn->GET();
+                        if (empty($sClass->aObjects)) {
+                            $sClass->aObjects = array();
+                        }
+                        array_push($sClass->aObjects, $oColumn);
+                    }
+                    if (in_array("actions", $aFields)) {
+                        require_once 'Actions.class.inc';
+                        $oActions = new Actions($this->aPath, array("ressource_id" => $sClass->aFields["ressource_id"], "module" => $sWebServiceName), $this->aProperties, $this->oConnection);
+                        $oActions->GET();
+                        array_push($sClass->aObjects, $oActions);
+                    }
+                    if (in_array("objects", $aFields)) {
+                        require_once'Tabs.class.inc';
+                        $aValues = array("filter" => '{"relation": "AND","operators":[{"column": "ressource_id","compare_operator": "=","value": "' . $sClass->aFields["ressource_id"] . '"}, {"column": "lang","compare_operator": "=","value": "' . $this->aProperties["language"] . '"}]}', "token" => $this->aValues['token'], 'order_by' => 'index');
+                        $oTabs = new Tabs($this->aPath, $aValues, $this->aProperties);
+                        $oTabs->GET();
+                        array_push($sClass->aObjects, $oTabs);
+                    }
+                    array_push($this->aObjects, $sClass);
+                    unset($oObject);
+                }
+            }
+        }
+    }
+
+}
+
+class WebService extends WebServices {
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     */
+    function __construct($aPath, $aValues, $properties) {
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+    }
+
+}
+
+class Ressource extends WebServices {
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     */
+    function __construct($aPath, $aValues, $properties) {
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+    }
+
+}
+
+class RessourceList extends WebServices {
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     */
+    function __construct($aPath, $aValues, $properties) {
+        $this->aValues = $aValues;
+        $this->aPath = $aPath;
+        $this->aProperties = $properties;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/overview.phtml b/vas/rest/ws/vitis/overview.phtml
new file mode 100755
index 00000000..cfb98b42
--- /dev/null
+++ b/vas/rest/ws/vitis/overview.phtml
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @SWG\Swagger(
+ *      basePath="/[service_alias]/vitis",
+ *     	host="[server]",
+ *    	schemes={"[protocol]"},
+ *   produces={ 
+ *          "application/json",
+            "application/xml",
+            "text/html"
+ * 		},
+ * consumes={"application/json"}, 
+ *     @SWG\Info(
+ *         version="1.0.0",
+ *         title="Vitis Test Rest",
+ *         description="All features to access server operation for vitis",
+ *     )
+ * 
+ * )
+ */
+?>
+
+<h1 class="titleOverview">Service Vitis</h1>
+<p>
+	<a class="linkOverview" href="javascript:sService='vitis';LoadApi()">Vitis :</a> this is the most comprehensive service which should be used as a preference when developing applications communicating with Vitis. Those services allow you to administrate vitis applications.
+</p>
\ No newline at end of file
diff --git a/vas/sql/sqlQueries.xml b/vas/sql/sqlQueries.xml
new file mode 100755
index 00000000..4e745ccc
--- /dev/null
+++ b/vas/sql/sqlQueries.xml
@@ -0,0 +1,948 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sqlQueries>
+	<title>Scripts d'installation et de mises à jour de la base du VAS</title>
+	<queriesCollection>
+		<query>
+			<type>init</type>
+			<version>2016.01.00</version>
+			<code>
+				<![CDATA[
+				CREATE SCHEMA s_vitis;
+				CREATE OR REPLACE FUNCTION s_vitis.create_role_if_not_exists(rolename NAME, rights text) RETURNS TEXT AS $$ BEGIN    IF NOT EXISTS (SELECT * FROM pg_roles WHERE rolname = rolename) THEN        EXECUTE 'CREATE ROLE ' || rolename|| ' ' || rights;        RETURN 'CREATE ROLE';    ELSE        RETURN format('ROLE ''%I'' ALREADY EXISTS', rolename);    END IF; END; $$ LANGUAGE plpgsql;
+				select s_vitis.create_role_if_not_exists('vitis_user', 'NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION');
+				GRANT vitis_user TO u_vitis;
+				select s_vitis.create_role_if_not_exists('vitis_admin', 'NOSUPERUSER INHERIT NOCREATEDB CREATEROLE NOREPLICATION');
+				GRANT vitis_user TO vitis_admin;
+				ALTER SCHEMA s_vitis OWNER TO u_vitis;
+				SET search_path = s_vitis, pg_catalog;
+				CREATE FUNCTION f_add_col(_tbl regclass, _col text, _type regtype, OUT success boolean) RETURNS boolean LANGUAGE plpgsql AS $$ BEGIN IF EXISTS (SELECT 1 FROM pg_attribute WHERE  attrelid = _tbl AND    attname = _col   AND    NOT attisdropped) THEN   success := FALSE; ELSE   EXECUTE 'ALTER TABLE ' || _tbl || ' ADD COLUMN ' || quote_ident(_col) || ' ' || _type; success := TRUE; END IF; END $$;
+				ALTER FUNCTION s_vitis.f_add_col(_tbl regclass, _col text, _type regtype, OUT success boolean) OWNER TO u_vitis;
+				CREATE FUNCTION f_add_unique_index(_schema text, _table text, _col text, _name text, OUT success boolean) RETURNS boolean LANGUAGE plpgsql AS $$ BEGIN IF EXISTS (SELECT 1 FROM pg_class c JOIN   pg_namespace n ON n.oid = c.relnamespace WHERE  c.relname  = _name  AND   n.nspname = _schema ) THEN  success := FALSE; ELSE EXECUTE ' CREATE UNIQUE INDEX ' || _name || ' ON ' || _schema || '.' || _table || ' (lower(' || _col || '));' ; success := TRUE; END IF; END $$;
+				ALTER FUNCTION s_vitis.f_add_unique_index(_schema text, _table text, _col text, _name text, OUT success boolean) OWNER TO u_vitis;
+				CREATE FUNCTION s2hms(integer) RETURNS character varying LANGUAGE plpgsql AS $_$ declare nDureeSeconde ALIAS for $1; sDureeChaine varchar(10) ; nHeures int ; nMinutes int ; nSecondes int ; nHeures2 varchar(2) ; nMinutes2 varchar(2) ; nSecondes2 varchar(2) ; BEGIN nHeures := nDureeSeconde / 3600 ; nMinutes := (nDureeSeconde %% 3600) / 60 ; nSecondes := nDureeSeconde %% 60 ; if nHeures < 10 then nHeures2:= 0 || cast(nHeures as text) ; else nHeures2:= cast(nHeures as text)  ; end if; if nMinutes < 10 then nMinutes2:= 0 || cast(nMinutes as text) ; else nMinutes2:= cast(nMinutes as text)  ; end if; if nSecondes < 10 then nSecondes2:= 0 || cast(nSecondes as text) ; else nSecondes2:= cast(nSecondes as text)  ; end if; sDureeChaine := nHeures2 || ':' || nMinutes2 || ':' || nSecondes2; RETURN sDureeChaine; END; $_$;
+				ALTER FUNCTION s_vitis.s2hms(integer) OWNER TO u_vitis;
+				CREATE TABLE "user" (user_id integer NOT NULL,login character varying(50),name character varying(80),ip_constraint character varying(255), email character varying(100), company character varying(80),department character varying(80),last_connection timestamp without time zone, domain_id integer,restriction text);
+				ALTER TABLE "user" OWNER TO u_vitis;
+				CREATE TABLE vm_translation (translation_id character varying(60) NOT NULL, lang character varying(2) NOT NULL, translation text);
+				ALTER TABLE vm_translation OWNER TO u_vitis;
+				CREATE TABLE "group" (group_id integer NOT NULL, name character varying(50));
+				ALTER TABLE "group" OWNER TO u_vitis;
+				COMMENT ON TABLE "group" IS 'User group having the same access rights to workspaces and inboxes';
+				CREATE TABLE user_group (user_id integer, group_id integer);
+				ALTER TABLE user_group OWNER TO u_vitis;
+				CREATE SEQUENCE seq_common   START WITH 1 INCREMENT BY 1  NO MINVALUE  NO MAXVALUE  CACHE 1;
+				ALTER TABLE seq_common OWNER TO u_vitis;
+				CREATE TABLE domain (domain_id integer NOT NULL, domain character varying(50), alias character varying(50), server character varying(100), port integer, dn_search_user character varying(255), filter_user character varying(100), dn_search_group character varying(255), filter_group character varying(100), login character varying(50), password character varying(50), type character varying(10), verify_rights boolean DEFAULT true);
+				ALTER TABLE domain OWNER TO u_vitis;
+				COMMENT ON TABLE domain IS 'Ms Active Directory domain';
+				COMMENT ON COLUMN domain.dn_search_user IS 'Distinguished Name for users root node ';
+				COMMENT ON COLUMN domain.dn_search_group IS 'Distinguished Name for groups root node ';
+				CREATE TABLE privileges (    rolname character varying(100) NOT NULL,    description text);
+				ALTER TABLE privileges OWNER TO u_vitis;
+				CREATE SEQUENCE seq_translation    START WITH 1    INCREMENT BY 1    NO MINVALUE    NO MAXVALUE    CACHE 1;
+				ALTER TABLE seq_translation OWNER TO u_vitis;
+				CREATE SEQUENCE seq_vm    START WITH 1    INCREMENT BY 1    NO MINVALUE    NO MAXVALUE    CACHE 1;
+				ALTER TABLE seq_vm OWNER TO u_vitis;
+				CREATE VIEW v_group AS SELECT        CASE            WHEN (user_group.nb_members IS NULL) THEN (0)::bigint            ELSE user_group.nb_members        END AS nb_members,    "group".group_id,    "group".name   FROM ("group"     LEFT JOIN ( SELECT count(*) AS nb_members,            user_group_1.group_id           FROM user_group user_group_1          GROUP BY user_group_1.group_id) user_group ON (("group".group_id = user_group.group_id)));
+				ALTER TABLE v_group OWNER TO u_vitis;
+				CREATE TABLE vm_application_module (    application_name character varying(100) NOT NULL,    module_name character varying(50) NOT NULL);
+				ALTER TABLE vm_application_module OWNER TO u_vitis;
+				CREATE TABLE vm_mode (    mode_id character varying(100) NOT NULL,    module_id character varying(50));
+				ALTER TABLE vm_mode OWNER TO u_vitis;
+				CREATE TABLE vm_mode_rolname ( index integer, mode_id character varying(100) NOT NULL,    rolname character varying(100) NOT NULL);
+				ALTER TABLE vm_mode_rolname OWNER TO u_vitis;
+				CREATE VIEW v_mode AS SELECT DISTINCT vm_mode.mode_id,    vm_application_module.application_name,    vm_mode_rolname.index,    vm_application_module.module_name   FROM ((((vm_mode     LEFT JOIN vm_application_module ON (((vm_mode.module_id)::text = (vm_application_module.module_name)::text)))     LEFT JOIN vm_mode_rolname ON (((vm_mode.mode_id)::text = (vm_mode_rolname.mode_id)::text)))     JOIN pg_group ON ((pg_group.groname = (vm_mode_rolname.rolname)::name)))     JOIN pg_user ON (((pg_user.usesysid = ANY (pg_group.grolist)) AND ((pg_user.usename)::text = ("current_user"())::text))));
+				ALTER TABLE v_mode OWNER TO u_vitis;
+				CREATE VIEW v_ra_members_group AS SELECT count(*) AS nb_members,    user_group.group_id   FROM user_group  GROUP BY user_group.group_id;
+				ALTER TABLE v_ra_members_group OWNER TO u_vitis;
+				CREATE TABLE vm_section (    section_id integer DEFAULT nextval('seq_vm'::regclass) NOT NULL,    label_id character varying(60),    name character varying(50),    index integer,    event text,    tab_id integer,    template character varying(100),    ressource_id character varying(100), module character varying(100));
+				ALTER TABLE vm_section OWNER TO u_vitis;
+				CREATE TABLE vm_tab (    tab_id integer DEFAULT nextval('seq_vm'::regclass) NOT NULL,    event character varying(255) NOT NULL,    index integer DEFAULT 0 NOT NULL,    mode_id character varying(100) NOT NULL,    label_id character varying(60) NOT NULL,    ressource_id character varying(100),    edit_column character varying(255),    show_column character varying(255),    sorted_by character varying(100),    sorted_dir character varying(4) DEFAULT 'ASC'::character varying,    name character varying(100));
+				ALTER TABLE vm_tab OWNER TO u_vitis;
+				CREATE VIEW v_section AS SELECT vm_section.tab_id, vm_section.section_id, vm_section.event, vm_section.index, vm_translation.translation AS label, vm_translation.lang, vm_section.name, vm_section.template, vm_section.ressource_id, vm_section.module AS module_name FROM s_vitis.vm_section LEFT JOIN s_vitis.vm_translation ON vm_section.label_id::text = vm_translation.translation_id::text LEFT JOIN s_vitis.vm_tab ON vm_section.tab_id::text = vm_tab.tab_id::text;
+				ALTER TABLE v_section OWNER TO u_vitis;
+				CREATE VIEW v_tab AS SELECT vm_tab.tab_id,    vm_tab.event,    vm_tab.index,    vm_tab.mode_id,    vm_translation.translation AS label,    vm_translation.lang,    vm_tab.ressource_id,    vm_tab.edit_column,    vm_tab.show_column,    vm_tab.sorted_by,    vm_tab.sorted_dir,    vm_tab.name   FROM (vm_tab     LEFT JOIN vm_translation ON (((vm_tab.label_id)::text = (vm_translation.translation_id)::text)));
+				ALTER TABLE v_tab OWNER TO u_vitis;
+				CREATE VIEW v_user AS SELECT "user".user_id,    "user".login,    "user".name,    "user".email,    "user".company,    "user".department,    "user".ip_constraint,    domain.domain,    "user".domain_id,    "user".last_connection,    "user".restriction,        CASE            WHEN ((array_to_string(ARRAY( SELECT pg_group.groname               FROM (pg_group                 JOIN pg_roles ON ((pg_roles.oid = ANY (pg_group.grolist))))              WHERE ((("user".login)::name = pg_roles.rolname) AND ((pg_group.groname = 'vitis_admin'::name) OR (pg_group.groname = 'vitis_user'::name)))), '|'::text) = 'vitis_user|vitis_admin'::text) OR (array_to_string(ARRAY( SELECT pg_group.groname               FROM (pg_group                 JOIN pg_roles ON ((pg_roles.oid = ANY (pg_group.grolist))))              WHERE ((("user".login)::name = pg_roles.rolname) AND ((pg_group.groname = 'vitis_admin'::name) OR (pg_group.groname = 'vitis_user'::name)))), '|'::text) = 'vitis_admin|vitis_user'::text)) THEN 'admin'::text            WHEN (array_to_string(ARRAY( SELECT pg_group.groname               FROM (pg_group                 JOIN pg_roles ON ((pg_roles.oid = ANY (pg_group.grolist))))              WHERE ((("user".login)::name = pg_roles.rolname) AND ((pg_group.groname = 'vitis_admin'::name) OR (pg_group.groname = 'vitis_user'::name)))), '|'::text) = 'vitis_user'::text) THEN 'user'::text            ELSE ''::text        END AS role   FROM ("user"     LEFT JOIN domain ON (("user".domain_id = domain.domain_id)));
+				ALTER TABLE v_user OWNER TO u_vitis;
+				CREATE VIEW v_user_group AS SELECT user_group.group_id,    user_group.user_id   FROM ((user_group     LEFT JOIN "user" ON ((user_group.user_id = "user".user_id)))     LEFT JOIN "group" ON (("group".group_id = user_group.group_id)))  WHERE ((("user".login)::name)::text = ("current_user"())::text);
+				ALTER TABLE v_user_group OWNER TO u_vitis;
+				CREATE TABLE version (    version character varying(10) NOT NULL,    build integer NOT NULL,    date timestamp with time zone NOT NULL,    active boolean);
+				ALTER TABLE version OWNER TO u_vitis;
+				CREATE TABLE vm_application (    name character varying(100) NOT NULL);
+				ALTER TABLE vm_application OWNER TO u_vitis;
+				CREATE TABLE vm_module (    module_id character varying(50) NOT NULL,    description text,    version character varying(50) NOT NULL,    label character varying(50),    type character varying(3));
+				ALTER TABLE vm_module OWNER TO u_vitis;
+				CREATE TABLE vm_string (    string text,    string_id character varying(60) NOT NULL);
+				ALTER TABLE vm_string OWNER TO u_vitis;
+				CREATE TABLE vm_table_button (    button_class character varying(50),    table_button_id integer DEFAULT nextval('seq_vm'::regclass) NOT NULL,    event character varying(100) NOT NULL,    label_id character varying(60),    ressource_id character varying(100),    tab_id integer);
+				ALTER TABLE vm_table_button OWNER TO u_vitis;
+				CREATE TABLE vm_table_field (    table_field_id integer DEFAULT nextval('seq_vm'::regclass) NOT NULL,    name character varying(200) NOT NULL,    sortable boolean DEFAULT true,    resizeable boolean DEFAULT false,    index integer,     width integer,    align character varying(6) DEFAULT 'left'::character varying NOT NULL,    label_id character varying(60),    module character varying(50),    ressource_id character varying(100),    template character varying(255),    tab_id integer);
+				ALTER TABLE vm_table_field OWNER TO u_vitis;
+				INSERT INTO privileges (rolname, description) VALUES ('vitis_admin', E'rôle administrateur de vitis\nPermet d''accéder aux modes :\n   - Utilisateur\n - Utilisateurs\n    - Configuration\n   - Logs');
+				INSERT INTO privileges (rolname, description) VALUES ('vitis_user', E'rôle utilisateur de vitis\n\nPermet de se connecter à l''application');
+				INSERT INTO vm_mode (mode_id, module_id) VALUES ('user', 'vitis');
+				INSERT INTO vm_mode (mode_id, module_id) VALUES ('users', 'vitis');
+				INSERT INTO vm_mode (mode_id, module_id) VALUES ('configuration', 'vitis');
+				INSERT INTO vm_mode (mode_id, module_id) VALUES ('logs', 'vitis');
+				INSERT INTO vm_mode (mode_id, module_id) VALUES ('help', 'vitis');
+				INSERT INTO vm_mode_rolname (index, mode_id, rolname) VALUES (20, 'users', 'vitis_admin');
+				INSERT INTO vm_mode_rolname (index, mode_id, rolname) VALUES (70, 'configuration', 'vitis_admin');
+				INSERT INTO vm_mode_rolname (index, mode_id, rolname) VALUES (80, 'logs', 'vitis_admin');
+				INSERT INTO vm_mode_rolname (index, mode_id, rolname) VALUES (10, 'user', 'vitis_user');
+				INSERT INTO vm_mode_rolname (index, mode_id, rolname) VALUES (90, 'help', 'vitis_admin');
+				INSERT INTO vm_module (module_id, description, version, label, type) VALUES ('vitis', 'module vitis veremes', '0.1', 'vitis', NULL);
+				INSERT INTO vm_string (string, string_id) VALUES ('Chaine de caractère nulle', 'vitis_1');
+				INSERT INTO vm_string (string, string_id) VALUES ('onglet 2 du mode  (Utilisateurs) utilisé dans la table vm_tab', 'vitis_2');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre de la list correspondant à le vm_table 3 (v_user)', 'vitis_3');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre Formulaire vm_table id 3 (v_user)', 'vitis_4');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button d''ajout de la table v_user table_button_id = 38', 'vitis_5');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button de suppression de la table v_user table_button_id =39', 'vitis_6');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button import AD de la table v_user table_button_id =40', 'vitis_7');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ user_id correspondant au table field_id 1', 'vitis_8');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ login correspondant au table field_id 11', 'vitis_9');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ name correspondant au table field_id 12', 'vitis_10');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ email correspondant au table field_id 13', 'vitis_11');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ ip correspondant au table field_id 14', 'vitis_12');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ company correspondant au table field_id 15', 'vitis_13');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ domain_id de la table domain correspondant au table field_id 146', 'vitis_14');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ Role de la table v_user pour connaitre si un utilisateur est administrateur ou pas', 'vitis_15');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ department correspondant au table field_id 18', 'vitis_16');
+				INSERT INTO vm_string (string, string_id) VALUES ('onglet 1 du mode administration (Annuaires) utilisé dans la table vm_tab', 'vitis_17');
+				INSERT INTO vm_string (string, string_id) VALUES ('onglet 3 du mode administration (Groupes) utilisé dans la table vm_tab', 'vitis_18');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre Formulaire vm_table id (group)', 'vitis_19');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre de la list correspondant à le vm_table 1 (group)', 'vitis_20');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button d''ajout de la table group table_button_id = 9', 'vitis_21');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button de suppression de la table group table_button_id =10', 'vitis_22');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button import AD de la table group table_button_id =50', 'vitis_23');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ id de la vue group correspondant au table field_id 154', 'vitis_24');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ nom de la vue group correspondant au table field_id 135', 'vitis_25');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ nb_members de la vue v_ra_members_group correspondant au champ Membres', 'vitis_26');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre de la list correspondant à le vm_table 19 (domain)', 'vitis_27');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre Formulaire vm_table domain', 'vitis_28');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button d''ajout de la table domain table_button_id = 7', 'vitis_29');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button de suppression de la table domain table_button_id =8', 'vitis_30');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ domain_id de la table domain correspondant au table field_id 145', 'vitis_31');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ domain de la table domain correspondant au table field_id 145', 'vitis_32');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ server de la table domain correspondant au table field_id 147', 'vitis_33');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ port de la table domain correspondant au table field_id 148', 'vitis_34');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ alias correspondant au table field_id 139', 'vitis_35');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ name de la vue update correspondant au table_field_id 41"', 'vitis_37');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ from de la vue update correspondant au table_field_id 42"', 'vitis_38');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ to de la vue update correspondant au table_field_id 43"', 'vitis_39');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ publishing_date de la vue update correspondant au table_field_id 44"', 'vitis_40');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ status de la vue update correspondant au table_field_id 45"', 'vitis_41');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ telechargement de la vue update correspondant au table_field_id 46"', 'vitis_42');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ installation de la vue update correspondant au table_field_id 47"', 'vitis_43');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ log de la vue update correspondant au table_field_id 48"', 'vitis_44');
+				INSERT INTO vm_string (string, string_id) VALUES ('"Champ error_log de la vue update correspondant au table_field_id 49"', 'vitis_45');
+				INSERT INTO vm_string (string, string_id) VALUES ('status disponible de la table rt_update_status', 'vitis_46');
+				INSERT INTO vm_string (string, string_id) VALUES ('status téléchargé de la table rt_update_status', 'vitis_47');
+				INSERT INTO vm_string (string, string_id) VALUES ('status installé de la table rt_update_status', 'vitis_48');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ update_id correspondant au table field_id 41', 'vitis_49');
+				INSERT INTO vm_string (string, string_id) VALUES ('status erreur de la table rt_update_status', 'vitis_50');
+				INSERT INTO vm_string (string, string_id) VALUES ('onglet 4 du mode administration (Privilèges) utilisé dans la table vm_tab', 'vitis_51');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre Formulaire vm_table id (privileges)', 'vitis_52');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre de la liste correspondant à le vm_table 1 (privileges)', 'vitis_53');
+				INSERT INTO vm_string (string, string_id) VALUES ('Groupe d''utilisateurs', 'vitis_54');
+				INSERT INTO vm_string (string, string_id) VALUES ('Description du groupe d''utilisateurs', 'vitis_55');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section general pour v_user', 'vitis_57');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section general pour group', 'vitis_58');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section general pour domain', 'vitis_59');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section general pour privileges', 'vitis_60');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ last_connection correspondant à la table v_user', 'vitis_61');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ alias correspondant à la table domain', 'vitis_62');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ type correspondant à la table domain', 'vitis_63');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ from de la vue update', 'vitis_64');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ to de la vue update', 'vitis_65');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ publishing_date de la vue update', 'vitis_66');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ status de la vue update', 'vitis_67');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ telechargement de la vue update', 'vitis_68');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ installation de la vue update', 'vitis_69');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ log de la vue update', 'vitis_70');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ error_log de la vue update', 'vitis_71');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ update_id de la vue update', 'vitis_72');
+				INSERT INTO vm_string (string, string_id) VALUES ('Button de suppression de la table update', 'vitis_73');
+				INSERT INTO vm_string (string, string_id) VALUES ('Champ name de la vue update', 'vitis_74');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section configuration pour configuration', 'vitis_75');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section version pour configuration', 'vitis_76');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section php info pour configuration', 'vitis_77');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section mises à jour pour configuration', 'vitis_78');
+				INSERT INTO vm_string (string, string_id) VALUES ('Titre section installation pour configuration', 'vitis_79');
+				INSERT INTO vm_string (string, string_id) VALUES ('Onglet Administration de l''objet vitis_help', 'vitis_291');
+				INSERT INTO vm_string (string, string_id) VALUES ('Onglet Web service de l''objet vitis_help', 'vitis_80');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadConfiguration()', 0, 'configuration', 'vitis_1', NULL, NULL, NULL, NULL, 'ASC', 'vitis_configuration');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadHelp()', 0, 'help', 'vitis_1', NULL, NULL, NULL, NULL, 'ASC', 'vitis_help');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadLogsJob()', 0, 'logs', 'vitis_1', NULL, NULL, NULL, NULL, 'ASC', 'vitis_log');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadUser();', 0, 'user', 'vitis_1', 'vitis/users', NULL, NULL, NULL, 'ASC', 'vitis_user');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadList()', 1, 'users', 'vitis_17', 'vitis/domains', 'editSectionForm', 'showSectionForm', 'domain_id', 'DESC', 'vitis_domain');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadList()', 2, 'users', 'vitis_18', 'vitis/groups', 'editSectionForm', 'showSectionForm', 'group_id', 'DESC', 'vitis_group');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadList()', 3, 'users', 'vitis_51', 'vitis/privileges', 'editSectionForm', 'showSectionForm', 'rolname', 'ASC', 'vitis_privilege');
+				INSERT INTO vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadList()', 0, 'users', 'vitis_2', 'vitis/users', 'editSectionForm', 'showSectionForm', 'user_id', 'DESC', 'vitis_users');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_57', 'general', 1, 'javascript:loadSection', (select tab_id from s_vitis.vm_tab where name = 'vitis_users'), 'workspaceListTpl.html', NULL, 'vitis');
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'nb_members', true, true, 3, 130, 'right', 'vitis_26', NULL, 'vitis/groups', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_group'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'domain_id', true, true, 1, 30, 'right', 'vitis_31', NULL, 'vitis/domains', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'type', true, true, 2, 100, 'left', 'vitis_63', NULL, 'vitis/domains', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'alias', true, true, 3, 300, 'left', 'vitis_62', NULL, 'vitis/domains', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'domain', true, true, 4, 300, 'left', 'vitis_32', NULL, 'vitis/domains', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'server', true, true, 5, 150, 'left', 'vitis_33', NULL, 'vitis/domains', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'port', true, true, 6, 50, 'right', 'vitis_34', NULL, 'vitis/domains', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'group_id', true, true, 1, 40, 'right', 'vitis_24', NULL, 'vitis/groups', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_group'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'rolname', true, true, 1, 200, 'left', 'vitis_54', NULL, 'vitis/privileges', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_privilege'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'description', true, true, 2, 800, 'left', 'vitis_55', NULL, 'vitis/privileges', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_privilege'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'name', true, true, 2, 200, 'left', 'vitis_25', NULL, 'vitis/groups', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_group'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'name', true, true, 3, 150, 'left', 'vitis_10', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'email', true, true, 6, 250, 'left', 'vitis_11', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'user_id', true, true, 1, 30, 'right', 'vitis_8', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'login', true, true, 2, 200, 'left', 'vitis_9', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'ip_constraint', true, true, 9, 150, 'left', 'vitis_12', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'company', true, true, 5, 130, 'left', 'vitis_13', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'domain', true, true, 8, 200, 'left', 'vitis_14', NULL, 'vitis/users', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'last_connection', true, true, 9, 170, 'left', 'vitis_61', NULL, 'vitis/users', '<div data-app-format-date-column="{{row.entity[col.field]}}"></div>', (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'role', true, true, 4, 40, 'center', 'vitis_15', NULL, 'vitis/users', '<div data-app-user-role-column="{{row.entity[col.field]}}"></div>', (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_59', 'general', 1, 'javascript:loadSection', (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'), 'workspaceListTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_60', 'general', 1, 'javascript:loadSection',  (select tab_id from s_vitis.vm_tab where name = 'vitis_privilege'), 'workspaceListTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_1', 'general', 1, 'Javascript:reloadSectionForm',  (select tab_id from s_vitis.vm_tab where name = 'vitis_user'), 'simpleFormTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_58', 'general', 1, 'javascript:loadSection',  (select tab_id from s_vitis.vm_tab where name = 'vitis_group'), 'workspaceListTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_1', 'general', 1, 'Javascript:reloadSectionForm',  (select tab_id from s_vitis.vm_tab where name = 'vitis_log'), 'doubleFormTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_76', 'version', 2, 'Javascript:reloadSectionForm', (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration'), 'modules/vitis/templates/versionConfigurationTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_77', 'phpinfo', 3, 'Javascript:reloadSectionForm', (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration'), 'modules/vitis/templates/phpInfoConfigurationTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_75', 'general', 1, 'setPropertiesFormValues', (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration'), 'simpleFormTpl.html', NULL, 'vitis');
+				INSERT INTO vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_80', 'webService', 2, 'Javascript:reloadSectionForm', (select tab_id from s_vitis.vm_tab where name = 'vitis_help'), 'modules/vitis/templates/webServiceHelpTpl.html', NULL, 'vitis');
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('add_smallFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'AddSectionForm', 'vitis_5', 'vitis/users', (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('deleteFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'deleteUsers()', 'vitis_6', 'vitis/users', (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('add_smallFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'AddSectionForm', 'vitis_29', 'vitis/domains', (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('deleteFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'DeleteSelection', 'vitis_30', 'vitis/domains', (select tab_id from s_vitis.vm_tab where name = 'vitis_domain'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('add_smallFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'AddSectionForm', 'vitis_21', 'vitis/groups', (select tab_id from s_vitis.vm_tab where name = 'vitis_group'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('deleteFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'DeleteSelection', 'vitis_22', 'vitis/groups', (select tab_id from s_vitis.vm_tab where name = 'vitis_group'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('adImport', (select nextval('s_vitis.seq_vm'::regclass)), 'ImportFromAd("group")', 'vitis_23', 'vitis/groups', (select tab_id from s_vitis.vm_tab where name = 'vitis_group'));
+				INSERT INTO vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('adImport', (select nextval('s_vitis.seq_vm'::regclass)), 'ImportFromAd("person")', 'vitis_7', 'vitis/users', (select tab_id from s_vitis.vm_tab where name = 'vitis_users'));
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_1', 'fr', NULL);
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_1', 'en', NULL);
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_2', 'fr', 'Utilisateurs');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_2', 'en', 'Users');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_3', 'fr', 'Utilisateurs');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_3', 'en', 'Users');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_4', 'fr', 'utilisateur');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_4', 'en', 'user');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_5', 'en', 'Add user');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_6', 'en', 'Delete users');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_6', 'fr', 'Supprimer les utilisateurs');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_7', 'fr', 'Importer de l''A.D.');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_7', 'en', 'Import from A.D.');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_8', 'fr', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_8', 'en', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_9', 'fr', 'Compte');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_9', 'en', 'Login');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_10', 'fr', 'Nom');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_10', 'en', 'Name');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_11', 'fr', 'Email');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_11', 'en', 'Email');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_12', 'en', 'Workstation IP');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_13', 'fr', 'Société');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_13', 'en', 'Company');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_14', 'fr', 'Domaine');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_14', 'en', 'Domain');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_15', 'fr', 'Rôle');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_15', 'en', 'Role');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_16', 'en', 'Department');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_16', 'fr', 'Service');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_17', 'fr', 'Domaines');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_17', 'en', 'Domains');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_18', 'fr', 'Groupes');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_18', 'en', 'Groups');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_19', 'fr', 'groupe');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_19', 'en', 'group');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_20', 'fr', 'Groupes');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_20', 'en', 'Groups');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_21', 'en', 'Add group');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_22', 'fr', 'Supprimer les groupes');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_22', 'en', 'Delete groups');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_23', 'fr', 'Importer de l''A.D.');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_23', 'en', 'Import from AD');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_24', 'fr', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_24', 'en', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_25', 'fr', 'Groupe');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_25', 'en', 'Group');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_28', 'en', 'domain');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_28', 'fr', 'domaine');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_27', 'en', 'Domains');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_27', 'fr', 'Domaines');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_29', 'en', 'Add domain');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_30', 'en', 'Delete domaines');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_30', 'fr', 'Supprimer les domaines');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_31', 'fr', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_31', 'en', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_32', 'fr', 'Domaine');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_32', 'en', 'Domain');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_33', 'fr', 'Serveur');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_33', 'en', 'Server');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_34', 'fr', 'Port');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_34', 'en', 'Port');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_35', 'fr', 'Supprimer mise à jour');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_35', 'en', 'Delete update');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_37', 'fr', 'Nom');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_37', 'en', 'Name');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_38', 'fr', 'De');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_38', 'en', 'From');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_39', 'fr', 'A');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_39', 'en', 'To');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_40', 'fr', 'Date de publication');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_40', 'en', 'Publishing date');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_41', 'fr', 'Statut');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_41', 'en', 'Status');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_42', 'fr', 'Téléchargement');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_42', 'en', 'Download');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_43', 'fr', 'Installation');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_43', 'en', 'Installation');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_44', 'fr', 'Log');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_44', 'en', 'Log');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_45', 'fr', 'Erreurs');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_45', 'en', 'Errors');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_46', 'fr', 'Disponible');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_46', 'en', 'Available');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_47', 'fr', 'Téléchargé');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_47', 'en', 'Downloaded');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_48', 'fr', 'Installé');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_48', 'en', 'Installed');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_49', 'fr', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_49', 'en', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_50', 'fr', 'Erreur');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_50', 'en', 'Error');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_51', 'fr', 'Privilèges');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_51', 'en', 'Privileges');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_52', 'fr', 'Privilèges');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_52', 'en', 'Privileges');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_53', 'fr', 'Privilèges');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_53', 'en', 'Privileges');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_54', 'fr', 'Groupes d''utilisateurs');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_54', 'en', 'User groups');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_55', 'fr', 'Description');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_55', 'en', 'Description');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_57', 'fr', 'Général');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_57', 'en', 'General');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_58', 'fr', 'Général');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_58', 'en', 'General');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_59', 'fr', 'Général');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_59', 'en', 'General');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_60', 'fr', 'Général');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_60', 'en', 'General');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_61', 'fr', 'Dernière connexion');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_61', 'en', 'Last connection');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_62', 'fr', 'Alias');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_62', 'en', 'Alias');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_63', 'fr', 'Type');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_63', 'en', 'Type');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_64', 'fr', 'De');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_64', 'en', 'From');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_65', 'fr', 'A');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_65', 'en', 'To');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_66', 'fr', 'Date de publication');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_26', 'fr', 'Nombre de membres');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_26', 'en', 'Number of members');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_66', 'en', 'Publishing date');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_67', 'fr', 'Statut');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_67', 'en', 'Status');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_68', 'fr', 'Téléchargement');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_68', 'en', 'Download');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_69', 'fr', 'Installation');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_69', 'en', 'Installation');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_70', 'fr', 'Log');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_70', 'en', 'Log');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_71', 'fr', 'Erreurs');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_71', 'en', 'Errors');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_72', 'fr', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_72', 'en', 'ID');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_73', 'fr', 'Supprimer mise à jour');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_73', 'en', 'Delete update');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_74', 'fr', 'Nom');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_74', 'en', 'Name');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_75', 'fr', 'Configuration');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_75', 'en', 'Configuration');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_76', 'fr', 'Version');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_76', 'en', 'Version');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_77', 'fr', 'Php info');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_77', 'en', 'Php info');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_78', 'fr', 'Mises à jour');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_78', 'en', 'Mises à jour');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_79', 'fr', 'Installation');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_79', 'en', 'Installation');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_80', 'fr', 'Service Web');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_80', 'en', 'Web Service');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_21', 'fr', 'Ajouter un groupe');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_29', 'fr', 'Ajouter un domaine');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_5', 'fr', 'Ajouter un utilisateur');
+				INSERT INTO vm_translation (translation_id, lang, translation) VALUES ('vitis_12', 'fr', 'IP du poste');
+				ALTER TABLE ONLY vm_application_module ADD CONSTRAINT fk_application_module_name PRIMARY KEY (application_name, module_name);
+				ALTER TABLE ONLY domain   ADD CONSTRAINT pk_domain_id PRIMARY KEY (domain_id);
+				ALTER TABLE ONLY "group" ADD CONSTRAINT pk_group_id PRIMARY KEY (group_id);
+				ALTER TABLE ONLY vm_application ADD CONSTRAINT pk_name PRIMARY KEY (name);
+				ALTER TABLE ONLY privileges   ADD CONSTRAINT pk_privileges PRIMARY KEY (rolname);
+				ALTER TABLE ONLY vm_string    ADD CONSTRAINT pk_string_id PRIMARY KEY (string_id);
+				ALTER TABLE ONLY vm_tab    ADD CONSTRAINT pk_tab_id PRIMARY KEY (tab_id);
+				ALTER TABLE ONLY vm_table_button    ADD CONSTRAINT pk_table_button_id PRIMARY KEY (table_button_id);
+				ALTER TABLE ONLY vm_table_field   ADD CONSTRAINT pk_table_field_id PRIMARY KEY (table_field_id);
+				ALTER TABLE ONLY user_group    ADD CONSTRAINT pk_user_group UNIQUE (group_id, user_id);
+				ALTER TABLE ONLY "user"    ADD CONSTRAINT pk_user_id PRIMARY KEY (user_id);
+				ALTER TABLE ONLY vm_mode    ADD CONSTRAINT pk_vm_mode PRIMARY KEY (mode_id);
+				ALTER TABLE ONLY vm_mode_rolname    ADD CONSTRAINT pk_vm_mode_rolname PRIMARY KEY (rolname, mode_id);
+				ALTER TABLE ONLY vm_module    ADD CONSTRAINT pk_vm_module PRIMARY KEY (module_id);
+				ALTER TABLE ONLY vm_section    ADD CONSTRAINT pk_vm_section PRIMARY KEY (section_id);
+				ALTER TABLE ONLY vm_translation    ADD CONSTRAINT pk_vm_translation PRIMARY KEY (translation_id, lang);
+				ALTER TABLE ONLY version    ADD CONSTRAINT pk_version PRIMARY KEY (version);
+				ALTER TABLE ONLY vm_module    ADD CONSTRAINT uk_label UNIQUE (label);
+				ALTER TABLE ONLY "user"    ADD CONSTRAINT uk_user_login UNIQUE (login);
+				CREATE INDEX fki_login ON "user" USING btree (login);
+				CREATE INDEX fki_user_restriction ON "user" USING btree (restriction);
+				CREATE UNIQUE INDEX uk_domain ON domain USING btree (lower((domain)::text));
+				CREATE UNIQUE INDEX uk_login ON "user" USING btree (lower((login)::text));
+				CREATE UNIQUE INDEX uk_mode_id ON vm_mode_rolname USING btree (rolname, lower((mode_id)::text));
+				CREATE UNIQUE INDEX uk_name_group ON "group" USING btree (lower((name)::text));
+				ALTER TABLE s_vitis.vm_tab  ADD CONSTRAINT uk_vm_tab_name UNIQUE (name);
+				CREATE RULE delete_v_group AS   ON DELETE TO v_group DO INSTEAD  DELETE FROM "group"  WHERE ("group".group_id = old.group_id);
+				CREATE RULE delete_v_user AS    ON DELETE TO v_user DO INSTEAD  DELETE FROM "user"  WHERE ("user".user_id = old.user_id);
+				CREATE RULE delete_v_user_group AS    ON DELETE TO v_user_group DO INSTEAD  DELETE FROM user_group  WHERE (user_group.group_id = old.group_id);
+				CREATE RULE insert_v_group AS    ON INSERT TO v_group DO INSTEAD  INSERT INTO "group" (group_id, name)  VALUES (new.group_id, new.name);
+				CREATE RULE insert_v_user AS    ON INSERT TO v_user DO INSTEAD  INSERT INTO "user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction)  VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction);
+				CREATE RULE update_v_group AS    ON UPDATE TO v_group DO INSTEAD  UPDATE "group" SET name = new.name  WHERE ("group".group_id = new.group_id);
+				CREATE RULE update_v_user AS    ON UPDATE TO v_user DO INSTEAD  UPDATE "user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, restriction = new.restriction  WHERE ("user".user_id = new.user_id);
+				ALTER TABLE ONLY vm_application_module    ADD CONSTRAINT fk_application_name FOREIGN KEY (application_name) REFERENCES vm_application(name) ON UPDATE CASCADE ON DELETE CASCADE;
+				ALTER TABLE ONLY "user"    ADD CONSTRAINT fk_domain_id FOREIGN KEY (domain_id) REFERENCES domain(domain_id) ON UPDATE CASCADE ON DELETE CASCADE;
+				ALTER TABLE ONLY user_group    ADD CONSTRAINT fk_group_id_user FOREIGN KEY (group_id) REFERENCES "group"(group_id) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_table_field    ADD CONSTRAINT fk_label_id FOREIGN KEY (label_id) REFERENCES vm_string(string_id);
+				ALTER TABLE ONLY vm_table_button    ADD CONSTRAINT fk_label_id_button FOREIGN KEY (label_id) REFERENCES vm_string(string_id);
+				ALTER TABLE ONLY vm_mode_rolname    ADD CONSTRAINT fk_mode_id FOREIGN KEY (mode_id) REFERENCES vm_mode(mode_id) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_tab    ADD CONSTRAINT fk_mode_id_tab FOREIGN KEY (mode_id) REFERENCES vm_mode(mode_id) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_mode    ADD CONSTRAINT fk_module_id FOREIGN KEY (module_id) REFERENCES vm_module(module_id) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_application_module    ADD CONSTRAINT fk_module_name FOREIGN KEY (module_name) REFERENCES vm_module(module_id) ON UPDATE CASCADE ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_mode_rolname    ADD CONSTRAINT fk_rolname FOREIGN KEY (rolname) REFERENCES privileges(rolname) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_tab    ADD CONSTRAINT fk_string_id_tab FOREIGN KEY (label_id) REFERENCES vm_string(string_id);
+				ALTER TABLE ONLY vm_translation    ADD CONSTRAINT fk_string_id_translation FOREIGN KEY (translation_id) REFERENCES vm_string(string_id) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_section    ADD CONSTRAINT fk_string_section FOREIGN KEY (label_id) REFERENCES vm_string(string_id);
+				ALTER TABLE ONLY user_group    ADD CONSTRAINT fk_user_id_group FOREIGN KEY (user_id) REFERENCES "user"(user_id) ON DELETE CASCADE;
+				ALTER TABLE ONLY vm_table_button    ADD CONSTRAINT fk_vm_tab_button FOREIGN KEY (tab_id) REFERENCES vm_tab(tab_id);
+				ALTER TABLE ONLY vm_table_field    ADD CONSTRAINT fk_vm_tab_button FOREIGN KEY (tab_id) REFERENCES vm_tab(tab_id);
+				ALTER TABLE ONLY vm_section    ADD CONSTRAINT fk_vm_tab_section FOREIGN KEY (tab_id) REFERENCES vm_tab(tab_id);
+				ALTER TABLE ONLY vm_section ADD CONSTRAINT fk_module_vm_section FOREIGN KEY (module) REFERENCES vm_module (module_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION;
+				REVOKE ALL ON SCHEMA s_vitis FROM PUBLIC;
+				REVOKE ALL ON SCHEMA s_vitis FROM u_vitis;
+				GRANT ALL ON SCHEMA s_vitis TO u_vitis;
+				GRANT USAGE ON SCHEMA s_vitis TO vitis_admin;
+				GRANT USAGE ON SCHEMA s_vitis TO vitis_user;
+				REVOKE ALL ON TABLE "user" FROM PUBLIC;
+				REVOKE ALL ON TABLE "user" FROM u_vitis;
+				GRANT ALL ON TABLE "user" TO u_vitis;
+				GRANT ALL ON TABLE "user" TO vitis_admin;
+				GRANT SELECT,UPDATE ON TABLE "user" TO vitis_user;
+				REVOKE ALL ON TABLE vm_translation FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_translation FROM u_vitis;
+				GRANT ALL ON TABLE vm_translation TO u_vitis;
+				GRANT SELECT ON TABLE vm_translation TO vitis_user;
+				GRANT ALL ON TABLE vm_translation TO vitis_admin;
+				REVOKE ALL ON TABLE "group" FROM PUBLIC;
+				REVOKE ALL ON TABLE "group" FROM u_vitis;
+				GRANT ALL ON TABLE "group" TO u_vitis;
+				GRANT ALL ON TABLE "group" TO vitis_admin;
+				GRANT SELECT ON TABLE "group" TO vitis_user;
+				REVOKE ALL ON TABLE user_group FROM PUBLIC;
+				REVOKE ALL ON TABLE user_group FROM u_vitis;
+				GRANT ALL ON TABLE user_group TO u_vitis;
+				GRANT ALL ON TABLE user_group TO vitis_admin;
+				GRANT SELECT ON TABLE user_group TO vitis_user;
+				REVOKE ALL ON SEQUENCE seq_common FROM PUBLIC;
+				REVOKE ALL ON SEQUENCE seq_common FROM u_vitis;
+				GRANT ALL ON SEQUENCE seq_common TO u_vitis;
+				GRANT ALL ON SEQUENCE seq_common TO vitis_admin;
+				GRANT SELECT,UPDATE ON SEQUENCE seq_common TO vitis_user;
+				REVOKE ALL ON TABLE domain FROM PUBLIC;
+				REVOKE ALL ON TABLE domain FROM u_vitis;
+				GRANT ALL ON TABLE domain TO u_vitis;
+				GRANT ALL ON TABLE domain TO vitis_admin;
+				GRANT SELECT ON TABLE domain TO vitis_user;
+				REVOKE ALL ON TABLE privileges FROM PUBLIC;
+				REVOKE ALL ON TABLE privileges FROM u_vitis;
+				GRANT ALL ON TABLE privileges TO u_vitis;
+				GRANT ALL ON TABLE privileges TO vitis_admin;
+				GRANT SELECT ON TABLE privileges TO vitis_user;
+				REVOKE ALL ON SEQUENCE seq_translation FROM PUBLIC;
+				REVOKE ALL ON SEQUENCE seq_translation FROM u_vitis;
+				GRANT ALL ON SEQUENCE seq_translation TO u_vitis;
+				GRANT ALL ON SEQUENCE seq_translation TO vitis_admin;
+				GRANT SELECT,UPDATE ON SEQUENCE seq_translation TO vitis_user;
+				REVOKE ALL ON SEQUENCE seq_vm FROM PUBLIC;
+				REVOKE ALL ON SEQUENCE seq_vm FROM u_vitis;
+				GRANT ALL ON SEQUENCE seq_vm TO u_vitis;
+				GRANT ALL ON SEQUENCE seq_vm TO vitis_admin;
+				GRANT SELECT,UPDATE ON SEQUENCE seq_vm TO vitis_user;
+				REVOKE ALL ON TABLE v_group FROM PUBLIC;
+				REVOKE ALL ON TABLE v_group FROM u_vitis;
+				GRANT ALL ON TABLE v_group TO u_vitis;
+				GRANT ALL ON TABLE v_group TO vitis_admin;
+				GRANT SELECT ON TABLE v_group TO vitis_user;
+				REVOKE ALL ON TABLE vm_application_module FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_application_module FROM u_vitis;
+				GRANT ALL ON TABLE vm_application_module TO u_vitis;
+				GRANT ALL ON TABLE vm_application_module TO vitis_admin;
+				GRANT SELECT ON TABLE vm_application_module TO vitis_user;
+				REVOKE ALL ON TABLE vm_mode FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_mode FROM u_vitis;
+				GRANT ALL ON TABLE vm_mode TO u_vitis;
+				GRANT ALL ON TABLE vm_mode TO vitis_admin;
+				GRANT SELECT ON TABLE vm_mode TO vitis_user;
+				REVOKE ALL ON TABLE vm_mode_rolname FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_mode_rolname FROM u_vitis;
+				GRANT ALL ON TABLE vm_mode_rolname TO u_vitis;
+				GRANT SELECT ON TABLE vm_mode_rolname TO vitis_user;
+				GRANT ALL ON TABLE vm_mode_rolname TO vitis_admin;
+				REVOKE ALL ON TABLE v_mode FROM PUBLIC;
+				REVOKE ALL ON TABLE v_mode FROM u_vitis;
+				GRANT ALL ON TABLE v_mode TO u_vitis;
+				GRANT ALL ON TABLE v_mode TO vitis_admin;
+				GRANT SELECT ON TABLE v_mode TO vitis_user;
+				REVOKE ALL ON TABLE v_ra_members_group FROM PUBLIC;
+				REVOKE ALL ON TABLE v_ra_members_group FROM u_vitis;
+				GRANT ALL ON TABLE v_ra_members_group TO u_vitis;
+				GRANT ALL ON TABLE v_ra_members_group TO vitis_admin;
+				GRANT SELECT ON TABLE v_ra_members_group TO vitis_user;
+				REVOKE ALL ON TABLE vm_section FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_section FROM u_vitis;
+				GRANT ALL ON TABLE vm_section TO u_vitis;
+				GRANT ALL ON TABLE vm_section TO vitis_admin;
+				GRANT SELECT ON TABLE vm_section TO vitis_user;
+				REVOKE ALL ON TABLE vm_tab FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_tab FROM u_vitis;
+				GRANT ALL ON TABLE vm_tab TO u_vitis;
+				GRANT SELECT ON TABLE vm_tab TO vitis_user;
+				GRANT ALL ON TABLE vm_tab TO vitis_admin;
+				REVOKE ALL ON TABLE v_section FROM PUBLIC;
+				REVOKE ALL ON TABLE v_section FROM u_vitis;
+				GRANT ALL ON TABLE v_section TO u_vitis;
+				GRANT ALL ON TABLE v_section TO vitis_admin;
+				GRANT SELECT ON TABLE v_section TO vitis_user;
+				REVOKE ALL ON TABLE v_tab FROM PUBLIC;
+				REVOKE ALL ON TABLE v_tab FROM u_vitis;
+				GRANT ALL ON TABLE v_tab TO u_vitis;
+				GRANT ALL ON TABLE v_tab TO vitis_admin;
+				GRANT SELECT ON TABLE v_tab TO vitis_user;
+				REVOKE ALL ON TABLE v_user FROM PUBLIC;
+				REVOKE ALL ON TABLE v_user FROM u_vitis;
+				GRANT ALL ON TABLE v_user TO u_vitis;
+				GRANT ALL ON TABLE v_user TO vitis_admin;
+				GRANT SELECT,UPDATE ON TABLE v_user TO vitis_user;
+				REVOKE ALL ON TABLE v_user_group FROM PUBLIC;
+				REVOKE ALL ON TABLE v_user_group FROM u_vitis;
+				GRANT ALL ON TABLE v_user_group TO u_vitis;
+				GRANT ALL ON TABLE v_user_group TO vitis_admin;
+				GRANT SELECT ON TABLE v_user_group TO vitis_user;
+				REVOKE ALL ON TABLE vm_application FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_application FROM u_vitis;
+				GRANT ALL ON TABLE vm_application TO u_vitis;
+				GRANT ALL ON TABLE vm_application TO vitis_admin;
+				GRANT SELECT ON TABLE vm_application TO vitis_user;
+				REVOKE ALL ON TABLE vm_module FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_module FROM u_vitis;
+				GRANT ALL ON TABLE vm_module TO u_vitis;
+				GRANT ALL ON TABLE vm_module TO vitis_admin;
+				GRANT SELECT ON TABLE vm_module TO vitis_user;
+				REVOKE ALL ON TABLE vm_string FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_string FROM u_vitis;
+				GRANT ALL ON TABLE vm_string TO u_vitis;
+				GRANT SELECT ON TABLE vm_string TO vitis_user;
+				GRANT ALL ON TABLE vm_string TO vitis_admin;
+				REVOKE ALL ON TABLE vm_table_button FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_table_button FROM u_vitis;
+				GRANT ALL ON TABLE vm_table_button TO u_vitis;
+				GRANT SELECT ON TABLE vm_table_button TO vitis_user;
+				GRANT ALL ON TABLE vm_table_button TO vitis_admin;
+				REVOKE ALL ON TABLE vm_table_field FROM PUBLIC;
+				REVOKE ALL ON TABLE vm_table_field FROM u_vitis;
+				GRANT ALL ON TABLE vm_table_field TO u_vitis;
+				GRANT ALL ON TABLE vm_table_field TO vitis_user;
+				GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE vm_table_field TO vitis_admin;
+				]]>
+			</code>
+
+		</query>
+		<query>
+			<type>update</type>
+			<version>2016.02.00</version>
+			<code>
+				<![CDATA[
+				-- Frédéric le 15/07/2016 15:21
+				UPDATE s_vitis.vm_table_button SET event = 'deleteUsers()' WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'vitis_users') AND label_id = 'vitis_6';
+				]]>
+			</code>
+
+		</query>
+		<query>
+			<type>update</type>
+			<version>2016.03.00</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+
+		</query>
+		<query>
+			<type>update</type>
+			<version>2016.04.00</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+
+		</query>
+		<query>
+			<type>update</type>
+			<version>2016.05.00</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.01.00</version>
+			<code>
+				<![CDATA[
+				-- Anthony le 24/01/2017 à 10:20
+				CREATE OR REPLACE FUNCTION s_vitis.insertJointure(arrayJointure text, value1 varchar(100), tableSchema varchar(255),jointureTable varchar(255), key1 varchar(255), key2 varchar(255)) RETURNS VOID AS $BODY$ DECLARE item varchar(255); request text; BEGIN FOREACH item IN ARRAY string_to_array(arrayJointure, '|') LOOP request = 'INSERT INTO '|| tableSchema ||'.'|| jointureTable ||' ('|| key1 ||', '|| key2 ||')VALUES('; IF pg_typeof(value1)::text = 'integer' THEN request = request || value1 || ', '; ELSE request = request || '''' || value1 || ''', '; END IF; IF pg_typeof(item)::text = 'integer' THEN request = request || item || ');'; ELSE request = request || '''' || item || ''');'; END IF; EXECUTE request; END LOOP; RETURN; END $BODY$ LANGUAGE 'plpgsql';
+				ALTER FUNCTION s_vitis.insertjointure(text, character varying, character varying, character varying, character varying, character varying) OWNER TO u_vitis;
+				CREATE OR REPLACE FUNCTION s_vitis.wabinsertstate(    schemametier character varying,    tablestatus character varying,    statusname character varying,    progress integer)  RETURNS void AS $BODY$ DECLARE request text; rowData integer; Id integer; BEGIN EXECUTE 'SELECT status_id FROM ' || schemaMetier || '.' || tableStatus || ' WHERE name = '''||statusName||''';' INTO rowData; IF rowData IS NOT NULL THEN RAISE NOTICE '%', rowData;request = 'UPDATE ' || schemaMetier || '.' || tableStatus || ' SET progress = '|| progress ||' WHERE name = '''||statusName||''';'; ELSE EXECUTE 'SELECT MAX(status_id) FROM  '||schemaMetier||'.'||tableStatus|| ';' INTO Id; IF Id IS NOT NULL THEN 	RAISE NOTICE '%',  Id;	Id:= Id + 1; else	Id:=1;	RAISE NOTICE '%',  Id;end if;request = 'INSERT INTO ' || schemaMetier || '.' || tableStatus || ' (status_id, name, progress) VALUES (' || Id || ',''' || statusName|| ''', ' || progress || ');'; END IF; RAISE NOTICE '%', request;EXECUTE request; RETURN; END $BODY$  LANGUAGE plpgsql VOLATILE  COST 100;
+				ALTER FUNCTION s_vitis.wabinsertstate(character varying, character varying, character varying, integer) OWNER TO u_vitis;
+				-- Armand le 30/01/2017 à 10:00
+				CREATE OR REPLACE VIEW s_vitis.v_section AS SELECT vm_section.tab_id, vm_section.section_id, vm_section.event, vm_section.index, vm_translation.translation AS label, vm_translation.lang, vm_section.name, vm_section.template, vm_section.ressource_id, vm_section.module AS module_name, vm_tab.name AS tab_name, vm_tab.mode_id FROM s_vitis.vm_section LEFT JOIN s_vitis.vm_translation ON vm_section.label_id::text = vm_translation.translation_id::text LEFT JOIN s_vitis.vm_tab ON vm_section.tab_id::text = vm_tab.tab_id::text;
+				ALTER TABLE s_vitis.v_section OWNER TO u_vitis;
+				REVOKE ALL ON TABLE s_vitis.v_section FROM PUBLIC;
+				REVOKE ALL ON TABLE s_vitis.v_section FROM u_vitis;
+				GRANT ALL ON TABLE s_vitis.v_section TO u_vitis;
+				GRANT ALL ON TABLE s_vitis.v_section TO vitis_admin;
+				GRANT SELECT ON TABLE s_vitis.v_section TO vitis_user;
+				-- Sébastien le 01/02/2017 à 12:33
+				INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Section Mode du mode Configuration', 'vitis_81');
+				INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_81', 'fr', 'Modes');
+				INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_81', 'en', 'Modes');
+				INSERT INTO s_vitis.vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_81', 'modes', 2, 'loadModes', (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration'), 'workspaceListTpl.html', 'vitis/modes', 'vitis');
+				UPDATE s_vitis.vm_section SET index = 3 WHERE name = 'version' and label_id = 'vitis_76' and tab_id = (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration');
+				UPDATE s_vitis.vm_section SET index = 4 WHERE name = 'phpinfo' and label_id = 'vitis_77' and tab_id = (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration');
+				-- Armand le 15/02/2017 à 11:40
+				INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Titre section websocket pour configuration', 'vitis_82');
+				INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_82', 'fr', 'Websocket');
+				INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_82', 'en', 'Websocket');
+				INSERT INTO s_vitis.vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_82', 'websocket', 4, 'Javascript:reloadWebsocketStatus', (select tab_id from s_vitis.vm_tab where name = 'vitis_configuration'), 'modules/vitis/templates/websocketConfigurationTpl.html', NULL, 'vitis');
+				-- Armand le 31/03/2017 à 11:40
+				REVOKE ALL ON TABLE s_vitis.vm_table_field FROM vitis_user;
+				REVOKE ALL ON TABLE s_vitis.vm_table_field FROM vitis_admin;
+				GRANT SELECT ON TABLE s_vitis.vm_table_field TO vitis_user;
+				GRANT ALL ON TABLE s_vitis.vm_table_field TO vitis_admin;
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.01.01</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.01.02</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.01.03</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.01.04</version>
+			<code>
+				<![CDATA[
+				-- Armand le 20/06/2017 à 18h ajout de la table feature_style
+				CREATE TABLE IF NOT EXISTS s_vitis.feature_style(feature_style_id SERIAL NOT NULL,draw_color VARCHAR(50),draw_outline_color VARCHAR(50),draw_size VARCHAR(50),draw_dash VARCHAR(50),draw_symbol VARCHAR(50),text_font VARCHAR(50),text_color VARCHAR(50),text_outline_color VARCHAR(50),text_size VARCHAR(50),text_outline_size VARCHAR(50),text_offset_x VARCHAR(50),text_offset_y VARCHAR(50),text_rotation VARCHAR(50),text_text VARCHAR(255),feature_type VARCHAR(255),PRIMARY KEY (feature_style_id));
+				ALTER TABLE s_vitis.feature_style owner TO u_vitis;
+				GRANT ALL ON table s_vitis.feature_style TO u_vitis;
+				GRANT SELECT ON TABLE s_vitis.feature_style TO vitis_user;
+				GRANT ALL ON table s_vitis.feature_style TO vitis_admin;
+				-- Armand le 27/07/2017 à 18h restriction des droits de vitis_user pour des raisons de sécurité
+				REVOKE ALL ON TABLE s_vitis."user" FROM vitis_user;
+				REVOKE ALL ON TABLE s_vitis."user_group" FROM vitis_user;
+				CREATE OR REPLACE FUNCTION s_vitis.is_vitis_admin() RETURNS boolean AS $total$ declare total boolean; BEGIN SELECT(SELECT count(*) FROM information_schema.applicable_roles WHERE role_name='vitis_admin') > 0 INTO total; RETURN total; END; $total$ LANGUAGE plpgsql;
+				CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id WHERE "user".login = "current_user"() OR s_vitis.is_vitis_admin();
+				CREATE OR REPLACE RULE delete_v_user AS ON DELETE TO s_vitis.v_user DO INSTEAD DELETE FROM s_vitis."user" WHERE "user".user_id = old.user_id;
+				CREATE OR REPLACE RULE insert_v_user AS ON INSERT TO s_vitis.v_user DO INSTEAD INSERT INTO s_vitis."user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction) VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction);
+				DROP RULE update_v_user ON s_vitis.v_user;
+				CREATE OR REPLACE RULE update_v_user_u AS ON UPDATE TO s_vitis.v_user DO INSTEAD UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department WHERE (new.name = "current_user"() or s_vitis.is_vitis_admin()) AND "user".user_id = new.user_id;
+				CREATE OR REPLACE RULE update_v_user_a AS ON UPDATE TO s_vitis.v_user WHERE s_vitis.is_vitis_admin() DO INSTEAD UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, restriction = new.restriction WHERE (new.name = "current_user"() or s_vitis.is_vitis_admin()) AND "user".user_id = new.user_id;
+				CREATE OR REPLACE VIEW s_vitis.v_user_group_by_rights AS SELECT user_group.user_id, user_group.group_id FROM s_vitis.user_group LEFT JOIN s_vitis."user" ON user_group.user_id = "user".user_id LEFT JOIN s_vitis."group" ON "group".group_id = user_group.group_id WHERE "user".login::name::text = "current_user"()::text OR s_vitis.is_vitis_admin();
+				ALTER TABLE s_vitis.v_user_group_by_rights OWNER TO u_vitis;
+				GRANT ALL ON TABLE s_vitis.v_user_group_by_rights TO u_vitis;
+				GRANT ALL ON TABLE s_vitis.v_user_group_by_rights TO vitis_admin;
+				GRANT SELECT ON TABLE s_vitis.v_user_group_by_rights TO vitis_user;
+				CREATE OR REPLACE RULE update_v_user_group_by_rights AS ON DELETE TO s_vitis.v_user_group_by_rights DO INSTEAD DELETE FROM s_vitis.user_group WHERE user_group.group_id = old.group_id;
+				CREATE OR REPLACE RULE insert_v_user_group_by_rights AS ON INSERT TO s_vitis.v_user_group_by_rights DO INSTEAD INSERT INTO s_vitis.user_group (user_id, group_id) VALUES (new.user_id, new.group_id);
+				DROP RULE IF EXISTS update_v_user_a ON s_vitis.v_user;
+				DROP RULE IF EXISTS update_v_user_u ON s_vitis.v_user;
+				CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD (UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = new.user_id; UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, restriction = new.restriction WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id);
+				-- Armand 02/08/2017: donne le droit d'édition sur last_connection
+				CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD (UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = new.user_id; UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id);
+				-- Armand 02/08/2017: correction bug: un utilisateur simple peut changer le nom, l'email la company, le departement et le last_connection d'un autre utilisateur si il passe un user_id dans les paramètres à changer
+				CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = (SELECT user_id FROM s_vitis."user" WHERE login = "current_user"()); UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id;);
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.02.00</version>
+			<code>
+				<![CDATA[
+				-- Laurent le 01/08/2017 à 12h Creation de fonction générique pour récupérer l'utilisateur qui créé ou met à jour un enregistrement
+				CREATE OR REPLACE FUNCTION s_vitis.insert_author_date() RETURNS trigger AS $BODY$ BEGIN NEW.author = current_user; NEW.create_date = now(); RETURN NEW;	END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;
+				ALTER FUNCTION s_vitis.insert_author_date() OWNER TO u_vitis;
+				CREATE OR REPLACE FUNCTION s_vitis.update_modifier_date()  RETURNS trigger AS $BODY$ BEGIN     NEW.modifier = current_user;	 NEW.update_date = now();    RETURN NEW;	END;$BODY$  LANGUAGE plpgsql VOLATILE  COST 100;
+				ALTER FUNCTION s_vitis.update_modifier_date()  OWNER TO u_vitis;
+				-- Armand 31/08/2017: correction bug: quand un administrateur met à jour les groupes d'un utilisateur, il pert lui même les groupes qu'il a enlevé à l'utilisateur
+				CREATE OR REPLACE RULE update_v_user_group_by_rights AS ON DELETE TO s_vitis.v_user_group_by_rights DO INSTEAD DELETE FROM s_vitis.user_group WHERE user_group.group_id = old.group_id AND user_group.user_id = old.user_id;
+				--Yoann 12/09/2017: attribution de la séquence s_vitis.seq_common aux champs user_id(table user) et group_id (table group)
+				ALTER TABLE s_vitis."user"    ALTER COLUMN user_id SET DEFAULT nextval('s_vitis.seq_common'::regclass);
+				ALTER TABLE s_vitis."group"    ALTER COLUMN group_id SET DEFAULT nextval('s_vitis.seq_common'::regclass);
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.02.01</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.02.02</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.02.03</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.02.04</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.03.00</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2017.04.00</version>
+			<code>
+				<![CDATA[
+					ALTER FUNCTION s_vitis.is_vitis_admin() OWNER TO u_vitis;
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.01.00</version>
+			<code>
+				<![CDATA[
+					ALTER TABLE s_vitis."user" ADD CONSTRAINT check_u_vitis CHECK (name::text != 'u_vitis'::text)
+					ALTER TABLE s_vitis."user" ADD CONSTRAINT check_postgres CHECK (name::text != 'postgres'::text)
+					-- Armand 06/02/2018 15:31
+					ALTER TABLE s_vitis.domain ALTER COLUMN password TYPE character varying(255);
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.02.00</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.02.01</version>
+			<code>
+				<![CDATA[
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.03.00</version>
+			<code>
+				<![CDATA[
+					--anthony 05/04/2018 10:36
+					DROP INDEX IF EXISTS s_vitis.index_vm_translation_lang;
+					CREATE INDEX index_vm_translation_lang ON s_vitis.vm_translation (lang);
+					DROP INDEX IF EXISTS s_vitis.index_vm_translation;
+					CREATE INDEX index_vm_translation ON s_vitis.vm_translation (translation_id);
+					-- Armand 13/06/2018 17h59 ajout de CREATEROLE à u_vitis pour que l'on puisse modifier les privilèges
+					ALTER USER u_vitis WITH CREATEROLE
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.04.00</version>
+			<code>
+				<![CDATA[
+					-- Frédéric 15/06/2018 09:15
+                    ALTER TABLE s_vitis.user ADD COLUMN dataencrypt boolean DEFAULT FALSE;
+                    ALTER TABLE s_vitis.user ADD COLUMN secretkey character varying(100);
+                    CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role, dataencrypt, secretkey FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+                    CREATE OR REPLACE RULE insert_v_user AS ON INSERT TO s_vitis.v_user DO INSTEAD INSERT INTO s_vitis."user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction, dataencrypt, secretkey) VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction, new.dataencrypt, new.secretkey);
+                    CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD ( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = (( SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"())); UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction, dataencrypt = new.dataencrypt, secretkey = new.secretkey WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id;);
+					-- Frédéric 21/06/2018 15:47
+                    CREATE TABLE s_vitis.billinggroup (billinggroup_id SERIAL NOT NULL, billinggroup character varying(50) NOT NULL, description text);
+                    ALTER TABLE ONLY s_vitis.billinggroup ADD CONSTRAINT pk_billinggroup_id PRIMARY KEY (billinggroup_id);
+                    ALTER TABLE s_vitis.billinggroup OWNER TO u_vitis;
+                    GRANT ALL ON TABLE s_vitis.billinggroup TO u_vitis;
+                    GRANT ALL ON TABLE s_vitis.billinggroup TO vitis_admin;
+                    ALTER TABLE s_vitis.user ADD COLUMN billinggroup_id integer;
+                    ALTER TABLE s_vitis."user" ALTER COLUMN billinggroup_id SET DEFAULT -1;
+                    ALTER TABLE s_vitis.user ADD CONSTRAINT fk_billinggroup_id FOREIGN KEY (billinggroup_id) REFERENCES s_vitis.billinggroup (billinggroup_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION;
+					-- Frédéric 21/06/2018 16:15
+					CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY (SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY (SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY (SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS ROLE, dataencrypt, secretkey, "user".billinggroup_id, billinggroup.billinggroup FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id LEFT JOIN s_vitis.billinggroup ON "user".billinggroup_id = billinggroup.billinggroup_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+                    CREATE OR REPLACE RULE insert_v_user AS ON INSERT TO s_vitis.v_user DO INSTEAD INSERT INTO s_vitis."user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction, dataencrypt, secretkey, billinggroup_id) VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction, new.dataencrypt, new.secretkey, new.billinggroup_id);
+                    CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD ( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = (( SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"())); UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction, dataencrypt = new.dataencrypt, secretkey = new.secretkey, billinggroup_id = new.billinggroup_id WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id;);
+					-- Frédéric 22/06/2018 11:32
+                    CREATE OR REPLACE VIEW s_vitis.v_billinggroup AS SELECT billinggroup.billinggroup_id, billinggroup.billinggroup, billinggroup.description FROM s_vitis."billinggroup";
+                    ALTER TABLE s_vitis.v_billinggroup OWNER TO u_vitis;
+                    GRANT ALL ON TABLE s_vitis.v_billinggroup TO vitis_admin;
+                    GRANT SELECT ON TABLE s_vitis.v_billinggroup TO vitis_user;
+                    CREATE OR REPLACE RULE delete_v_billinggroup AS ON DELETE TO s_vitis.v_billinggroup DO INSTEAD  DELETE FROM s_vitis."billinggroup" WHERE "billinggroup".billinggroup_id = old.billinggroup_id;
+                    CREATE OR REPLACE RULE insert_v_billinggroup AS ON INSERT TO s_vitis.v_billinggroup DO INSTEAD  INSERT INTO s_vitis."billinggroup" (billinggroup_id, billinggroup, description) VALUES (new.billinggroup_id, new.billinggroup, new.description);
+                    CREATE OR REPLACE RULE update_v_billinggroup AS ON UPDATE TO s_vitis.v_billinggroup DO INSTEAD  UPDATE s_vitis."billinggroup" SET billinggroup = new.billinggroup, description = new.description WHERE "billinggroup".billinggroup_id = new.billinggroup_id;
+					-- Frédéric 22/06/2018 14:20
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('onglet 4 du mode utilisateurs (users) utilisé dans la table vm_tab', 'vitis_83');
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Titre section general pour billinggroup', 'vitis_84');
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Champ billinggroup_id de la table billinggroup', 'vitis_85');
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Champ billinggroup de la table billinggroup', 'vitis_86');
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Champ description de la table billinggroup', 'vitis_87');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_83', 'fr', 'Groupes de facturation');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_83', 'en', 'Billing Groups');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_84', 'fr', 'Général');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_84', 'en', 'General');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_85', 'fr', 'ID');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_85', 'en', 'ID');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_86', 'fr', 'Groupe');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_86', 'en', 'Group');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_87', 'fr', 'Description');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_87', 'en', 'Description');
+                    INSERT INTO s_vitis.vm_tab (tab_id, event, index, mode_id, label_id, ressource_id, edit_column, show_column, sorted_by, sorted_dir, name) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'loadList()', 4, 'users', 'vitis_83', 'vitis/billinggroups', 'editSectionForm', 'showSectionForm', 'billinggroup_id', 'DESC', 'vitis_billinggroup');
+                    INSERT INTO s_vitis.vm_section (section_id, label_id, name, index, event, tab_id, template, ressource_id, module) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'vitis_84', 'general', 1, 'javascript:loadSection', (select tab_id from s_vitis.vm_tab where name = 'vitis_billinggroup'), 'workspaceListTpl.html', NULL, 'vitis');
+                    INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'billinggroup_id', true, true, 1, 30, 'right', 'vitis_85', NULL, 'vitis/billinggroups', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_billinggroup'));
+                    INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'billinggroup', true, true, 2, 200, 'left', 'vitis_86', 'vitis', 'vitis/billinggroups', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_billinggroup'));
+                    INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'description', true, true, 3, 800, 'left', 'vitis_87', 'vitis', 'vitis/billinggroups', NULL, (select tab_id from s_vitis.vm_tab where name = 'vitis_billinggroup'));
+					-- Frédéric 22/06/2018 16:39
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Button d''ajout de la table billing group', 'vitis_88');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_88', 'fr', 'Ajouter un groupe de facturation');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_88', 'en', 'Add a billing group');
+                    INSERT INTO s_vitis.vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('add_smallFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'AddSectionForm', 'vitis_88', 'vitis/billinggroups', (select tab_id from s_vitis.vm_tab where name = 'vitis_billinggroup'));
+                    INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Button de suppression de la table billing group', 'vitis_89');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_89', 'fr', 'Supprimer les groupes de facturation');
+                    INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('vitis_89', 'en', 'Delete billing groups');
+                    INSERT INTO s_vitis.vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('deleteFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'DeleteSelection', 'vitis_89', 'vitis/billinggroups', (select tab_id from s_vitis.vm_tab where name = 'vitis_billinggroup'));
+					-- Frédéric 25/06/2018 09:44
+                    CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role, dataencrypt, secretkey, "user".billinggroup_id,billinggroup.billinggroup FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id LEFT JOIN s_vitis.billinggroup ON "user".billinggroup_id = billinggroup.billinggroup_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+					-- Frédéric 25/06/2018 11:05
+                    INSERT INTO s_vitis.billinggroup (billinggroup_id, billinggroup, description) VALUES (-1, 'default', '');
+
+                    -- Frédéric le 20/07/2018 15:30
+                    ALTER TABLE s_vitis."user" ADD COLUMN timezone_id character varying(40) DEFAULT 'Europe/Paris' NOT NULL;
+                    DROP VIEW s_vitis.v_user;
+                    ALTER TABLE s_vitis.user ALTER COLUMN last_connection TYPE timestamp with time zone;
+                    CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role, dataencrypt, secretkey, "user".billinggroup_id,billinggroup.billinggroup FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id LEFT JOIN s_vitis.billinggroup ON "user".billinggroup_id = billinggroup.billinggroup_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+                    ALTER TABLE s_vitis.v_user OWNER TO u_vitis;
+                    GRANT ALL ON TABLE s_vitis.v_user TO vitis_admin;
+                    GRANT SELECT, UPDATE ON TABLE s_vitis.v_user TO vitis_user;
+                    CREATE OR REPLACE RULE delete_v_user AS ON DELETE TO s_vitis.v_user DO INSTEAD  DELETE FROM s_vitis."user" WHERE "user".user_id = old.user_id;
+                    CREATE OR REPLACE RULE insert_v_user AS ON INSERT TO s_vitis.v_user DO INSTEAD  INSERT INTO s_vitis."user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction, dataencrypt, secretkey, billinggroup_id) VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction, new.dataencrypt, new.secretkey, new.billinggroup_id);
+                    CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD ( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = (( SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"())); UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction, dataencrypt = new.dataencrypt, secretkey = new.secretkey, billinggroup_id = new.billinggroup_id WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id;);
+
+                    -- Frédéric le 20/07/2018 16:40
+                    CREATE TABLE s_vitis.rt_formatdate (formatdate_id character varying(11) NOT NULL, formatdate character varying(100));
+                    ALTER TABLE s_vitis.rt_formatdate OWNER TO u_vitis;
+                    GRANT ALL ON TABLE s_vitis.rt_formatdate TO vitis_admin;
+                    GRANT SELECT ON TABLE s_vitis.rt_formatdate TO vitis_user;
+                    ALTER TABLE ONLY s_vitis.rt_formatdate ADD CONSTRAINT pk_formatdate_id PRIMARY KEY (formatdate_id);
+                    INSERT INTO s_vitis.rt_formatdate (formatdate_id, formatdate) VALUES ('MM-DD-YYYY','Américain');
+                    INSERT INTO s_vitis.rt_formatdate (formatdate_id, formatdate) VALUES ('YYYY-MM-DDT','ISO 8601');
+                    INSERT INTO s_vitis.rt_formatdate (formatdate_id, formatdate) VALUES ('DD-MM-YYYY','Européen');
+
+                    ALTER TABLE s_vitis.user ADD COLUMN formatdate_id character varying(11) DEFAULT 'YYYY-MM-DDT';
+                    ALTER TABLE s_vitis.user ADD CONSTRAINT fk_formatdate_id FOREIGN KEY (formatdate_id) REFERENCES s_vitis.rt_formatdate (formatdate_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION;
+
+                    -- Anthony le 23/07/2018 09:20
+                    ALTER TABLE s_vitis.user ADD COLUMN phone varchar(50);
+					ALTER TABLE s_vitis.user ADD COLUMN acceptnotification boolean DEFAULT FALSE;
+					CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role, dataencrypt, secretkey, "user".billinggroup_id ,billinggroup.billinggroup, "user".phone, "user".acceptnotification FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id LEFT JOIN s_vitis.billinggroup ON "user".billinggroup_id = billinggroup.billinggroup_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+					CREATE OR REPLACE RULE insert_v_user AS ON INSERT TO s_vitis.v_user DO INSTEAD INSERT INTO s_vitis."user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction, dataencrypt, secretkey, billinggroup_id, phone, acceptnotification) VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction, new.dataencrypt, new.secretkey, new.billinggroup_id, new.phone, new.acceptnotification);
+					CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD ( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection, phone = new.phone, acceptnotification = new.acceptnotification WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = (( SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"())); UPDATE s_vitis."user" SET name = new.name, email = new.email, phone = new.phone, acceptnotification = new.acceptnotification, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction, dataencrypt = new.dataencrypt, secretkey = new.secretkey, billinggroup_id = new.billinggroup_id, phone = new.phone, acceptnotification = new.acceptnotification WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id; );
+
+                    -- Frédéric le 23/07/2018 10:43
+                    CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role, dataencrypt, secretkey, "user".billinggroup_id ,billinggroup.billinggroup, "user".phone, "user".acceptnotification, "user".timezone_id, "user".formatdate_id FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id LEFT JOIN s_vitis.billinggroup ON "user".billinggroup_id = billinggroup.billinggroup_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+                    CREATE OR REPLACE RULE insert_v_user AS ON INSERT TO s_vitis.v_user DO INSTEAD  INSERT INTO s_vitis."user" (user_id, login, domain_id, name, email, company, department, ip_constraint, restriction, dataencrypt, secretkey, billinggroup_id, phone, acceptnotification, timezone_id, formatdate_id)  VALUES (new.user_id, new.login, new.domain_id, new.name, new.email, new.company, new.department, new.ip_constraint, new.restriction, new.dataencrypt, new.secretkey, new.billinggroup_id, new.phone, new.acceptnotification, new.timezone_id, new.formatdate_id);
+                    CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD ( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection, phone = new.phone, acceptnotification = new.acceptnotification WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = (( SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"())); UPDATE s_vitis."user" SET name = new.name, email = new.email, phone = new.phone, acceptnotification = new.acceptnotification, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction, dataencrypt = new.dataencrypt, secretkey = new.secretkey, billinggroup_id = new.billinggroup_id, phone = new.phone, acceptnotification = new.acceptnotification, timezone_id = new.timezone_id, formatdate_id = new.formatdate_id WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id; );
+
+                    -- Frédéric le 23/07/2018 16:44
+                    UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'vitis_users') AND name = 'last_connection';
+
+                    -- Frédéric le 26/07/2018 10:25
+                    CREATE OR REPLACE VIEW s_vitis.v_user AS SELECT "user".user_id, "user".login, "user".name, "user".email, "user".company, "user".department, "user".ip_constraint, domain.domain, "user".domain_id, "user".last_connection, "user".restriction, CASE WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user|vitis_admin'::text OR array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_admin|vitis_user'::text THEN 'admin'::text WHEN array_to_string(ARRAY( SELECT pg_group.groname FROM pg_group JOIN pg_roles ON pg_roles.oid = ANY (pg_group.grolist) WHERE "user".login::name = pg_roles.rolname AND (pg_group.groname = 'vitis_admin'::name OR pg_group.groname = 'vitis_user'::name)), '|'::text) = 'vitis_user'::text THEN 'user'::text ELSE ''::text END AS role, "user".dataencrypt, "user".secretkey, "user".billinggroup_id, billinggroup.billinggroup, "user".phone, "user".acceptnotification, "user".timezone_id, "user".formatdate_id, rt_formatdate.formatdate FROM s_vitis."user" LEFT JOIN s_vitis.domain ON "user".domain_id = domain.domain_id LEFT JOIN s_vitis.billinggroup ON "user".billinggroup_id = billinggroup.billinggroup_id LEFT JOIN s_vitis.rt_formatdate ON "user".formatdate_id = rt_formatdate.formatdate_id WHERE "user".login::name = "current_user"() OR s_vitis.is_vitis_admin();
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.04.01</version>
+			<code>
+				<![CDATA[
+					-- Sofian le 30/08/2018 à 09:32
+					CREATE OR REPLACE RULE update_v_user AS ON UPDATE TO s_vitis.v_user DO INSTEAD ( UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, last_connection = new.last_connection, phone = new.phone, acceptnotification = new.acceptnotification WHERE NOT s_vitis.is_vitis_admin() AND new.login::name = "current_user"() AND "user".user_id = ( (SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"())); UPDATE s_vitis."user" SET name = new.name, email = new.email, company = new.company, department = new.department, ip_constraint = new.ip_constraint, domain_id = new.domain_id, last_connection = new.last_connection, restriction = new.restriction, dataencrypt = new.dataencrypt, secretkey = new.secretkey, billinggroup_id = new.billinggroup_id, phone = new.phone, acceptnotification = new.acceptnotification, timezone_id = new.timezone_id, formatdate_id = new.formatdate_id WHERE s_vitis.is_vitis_admin() AND "user".user_id = new.user_id; );
+				]]>
+			</code>
+		</query>
+		<query>
+			<type>update</type>
+			<version>2018.05.00</version>
+			<code>
+				<![CDATA[
+					-- Armand le 11/09/2018 à 11:35 création de la fonction s_vitis.format_date pour transformer un timestamp en fonction du format d'affichage des dates lié à l'utilisateur
+					CREATE OR REPLACE FUNCTION s_vitis.format_date(input_date TIMESTAMP) RETURNS TEXT AS $$ BEGIN RETURN to_char(input_date, (SELECT formatdate_id || ' HH24:MI:SS' as "formatdate" from s_vitis.user WHERE login = "current_user"())); END; $$ LANGUAGE PLPGSQL;
+					ALTER FUNCTION s_vitis.format_date(TIMESTAMP) OWNER TO u_vitis;
+				]]>
+			</code>
+		</query>
+	</queriesCollection>
+</sqlQueries>
-- 
GitLab