diff --git a/development.ini.in b/development.ini.in index 1e838fe14..61aa1d4bc 100644 --- a/development.ini.in +++ b/development.ini.in @@ -11,6 +11,8 @@ mako.directories = geoportailv3:templates app.cfg = %(here)s/.build/config.yaml elastic.servers = ${search_host} elastic.index = ${search_index} +authtkt_secret = ${authtkt_secret} +authtkt_cookie_name = ${authtkt_cookie_name} # pyramid_closure configuration pyramid_closure.roots = diff --git a/geoportailv3.mk b/geoportailv3.mk index 7613ec96c..62d56ac7c 100644 --- a/geoportailv3.mk +++ b/geoportailv3.mk @@ -16,6 +16,8 @@ PRINT3 = FALSE DISABLE_BUILD_RULES = test-packages test-packages-ngeo +CONFIG_VARS += ldap + include CONST_Makefile DEV_REQUIREMENTS += git+https://github.com/transifex/transifex-client.git@fix-proxies#egg=transifex-client-proxies diff --git a/geoportailv3/__init__.py b/geoportailv3/__init__.py index 92f579351..bbcb44fe0 100644 --- a/geoportailv3/__init__.py +++ b/geoportailv3/__init__.py @@ -3,10 +3,14 @@ from pyramid.config import Configurator from pyramid.settings import asbool from c2cgeoportal import locale_negotiator, \ - add_interface, INTERFACE_TYPE_NGEO_CATALOGUE + add_interface, INTERFACE_TYPE_NGEO_CATALOGUE, \ + set_user_validator from c2cgeoportal.resources import FAModels from c2cgeoportal.lib.authentication import create_authentication from geoportailv3.resources import Root +from geoportailv3.views.authentication import ldap_user_validator, \ + get_user_from_request +import ldap def main(global_config, **settings): @@ -22,6 +26,27 @@ def main(global_config, **settings): config.include('c2cgeoportal') config.include('pyramid_closure') + config.include('pyramid_ldap') + + """Config the ldap connection. + """ + ldap_settings = config.get_settings()['ldap'] + + config.ldap_setup( + ldap_settings['url'], + ldap_settings['bind'], + ldap_settings['passwd'], + ) + + config.ldap_set_login_query( + ldap_settings['base_dn'], + filter_tmpl='(login=%(login)s)', + scope=ldap.SCOPE_SUBTREE, + ) + + config.set_request_property(get_user_from_request, name='user', reify=True) + + set_user_validator(config, ldap_user_validator) config.add_translation_dirs('geoportailv3:locale/') @@ -50,5 +75,6 @@ def main(global_config, **settings): config.add_static_view('node_modules', settings.get('node_modules_path')) config.add_static_view('closure', settings.get('closure_library_path')) + config.add_route('getuserinfo', '/getuserinfo') config.add_route('wms', '/wms') return config.make_wsgi_app() diff --git a/geoportailv3/static/js/main.js b/geoportailv3/static/js/main.js index 9d656debc..6cc0c2072 100644 --- a/geoportailv3/static/js/main.js +++ b/geoportailv3/static/js/main.js @@ -10,10 +10,11 @@ goog.provide('app_main'); goog.require('app.MainController'); +goog.require('app.UserController'); goog.require('app.backgroundlayerDirective'); goog.require('app.catalogDirective'); -goog.require('app.layermanagerDirective'); goog.require('app.layerinfoDirective'); +goog.require('app.layermanagerDirective'); goog.require('app.scalelineDirective'); goog.require('ngeo.btngroupDirective'); goog.require('ngeo.resizemapDirective'); diff --git a/geoportailv3/static/js/maincontroller.js b/geoportailv3/static/js/maincontroller.js index 9174b54e8..0a225356b 100644 --- a/geoportailv3/static/js/maincontroller.js +++ b/geoportailv3/static/js/maincontroller.js @@ -93,6 +93,11 @@ app.MainController = function($scope, gettextCatalog, langUrlTemplate, */ this['shareOpen'] = false; + /** + * @type {Boolean} + */ + this['userOpen'] = false; + /** * @type {Array} */ @@ -113,7 +118,8 @@ app.MainController.prototype.setMap_ = function() { this['map'] = new ol.Map({ controls: [ new ol.control.Zoom({zoomInLabel: '\ue031', zoomOutLabel: '\ue025'}), - new ol.control.ZoomToExtent({label: '\ue01b', extent: this.defaultExtent_}), + new ol.control.ZoomToExtent({label: '\ue01b', + extent: this.defaultExtent_}), new ol.control.FullScreen({label: '\ue01c', labelActive: '\ue02b'}) ], view: new ol.View({ @@ -186,5 +192,4 @@ app.MainController.prototype.showTab = function(selector) { $(selector).tab('show'); }; - app.module.controller('MainController', app.MainController); diff --git a/geoportailv3/static/js/usercontroller.js b/geoportailv3/static/js/usercontroller.js new file mode 100644 index 000000000..f5c6719f7 --- /dev/null +++ b/geoportailv3/static/js/usercontroller.js @@ -0,0 +1,191 @@ +/** + * @fileoverview This file defines the controller class for the application's + * user controller. + * + */ +goog.provide('app.UserController'); + +goog.require('app'); + + + +/** + * @param {angular.$http} $http Htpp. + * @constructor + * @export + * @ngInject + */ +app.UserController = function($http) { + + /** + * @type {object} + * @private + */ + this['credentials'] = { + 'login' : null, + 'password' : null + }; + + /** + * @type {angular.$http} + * @private + */ + this['http_'] = $http; + + /** + * @type {string} + */ + this['login'] = null; + + + /** + * @type {string} + */ + this['email'] = null; + + + /** + * @type {string} + */ + this['role'] = null; + + /** + * @type {number} + */ + this['role_id'] = 0; + + /** + * @type {string} + */ + this['name'] = null; + + /** + * @type {boolean} + */ + this['isError'] = false; + + this.getUserInfo(); +}; + + +/** + * @param {Object} credentials Credentials. + * @export + */ +app.UserController.prototype.authenticate = function(credentials) { + + var that = this; + this['http_']({ + method: 'POST', + url: 'login', + data: $.param({ + 'login': credentials['login'], + 'password': credentials['password'] + }), + headers: {'Content-Type': 'application/x-www-form-urlencoded'} + }).success(function(data, status, headers, config) { + + if (status == 200) { + that.getUserInfo(); + that['isError'] = false; + }else { + that['isError'] = true; + } + + }). error(function(data, status, headers, config) { + that['isError'] = true; + }); +}; + + +/** + * @export + */ +app.UserController.prototype.logout = function() { + var that = this; + this['http_']({ + method: 'POST', + url: 'logout', + headers: {'Content-Type': 'application/x-www-form-urlencoded'} + }).success(function(data, status, headers, config) { + if (status == 200) { + that.getUserInfo(); + that['isError'] = false; + }else { + that.getUserInfo(); + that['isError'] = true; + } + }). error(function(data, status, headers, config) { + that.getUserInfo(); + that['isError'] = true; + }); +}; + + +/** + * @export + */ +app.UserController.prototype.getUserInfo = function() { + var that = this; + this['http_']({ + method: 'POST', + url: 'getuserinfo' + }).success(function(data, status, headers, config) { + + if (status == 200) { + that.setUserInfo( + data['login'], + data['role'], + data['role_id'], + data['mail'], + data['sn'] + ); + }else { + that.setUserInfo(null, null, null, null, null); + } + + }).error(function(data, status, headers, config) { + that.setUserInfo(null, null, null, null, null); + }); +}; + + +/** + * @return {boolean} + * @export + */ +app.UserController.prototype.isAuthenticated = function() { + if (this['login'] != null && this['login'].length > 0) { + return true; + } + return false; +}; + + +/** + * @return {boolean} + * @export + */ +app.UserController.prototype.hasError = function() { + return this['isError']; +}; + + +/** + * @param {?string} login Login. + * @param {?string} role Role. + * @param {?number} role_id Role id. + * @param {?string} mail Mail. + * @param {?string} name Name. + */ +app.UserController.prototype.setUserInfo = function( + login, role, role_id, mail, name) { + this['login'] = login; + this['role'] = role; + this['role_id'] = role_id; + this['mail'] = mail; + this['name'] = name; +}; + + +app.module.controller('UserController', app.UserController); diff --git a/geoportailv3/static/less/icons.less b/geoportailv3/static/less/icons.less index a6abcbeec..da438ee50 100644 --- a/geoportailv3/static/less/icons.less +++ b/geoportailv3/static/less/icons.less @@ -28,7 +28,7 @@ li.icon a { } &:after { - font-family: "geoportail-icons" !important; + font-family: "geoportail-icons" !important; position: absolute; top: 8px; left: 0; @@ -40,8 +40,8 @@ li.icon a { top: 10px; } } - } + button.icon:after { top: -10px; } @@ -80,13 +80,18 @@ button.icon.search:after, .icon.share a:after { content: '\e02a'; } -.icon.user a:after { +.icon.user > a:after { content: '\e02d'; } .icon.lang > a:after { content: '\e012'; } +.icon.active > a:after { + content:'\e02b'; +} + + #catalog, #mylayers { .fa-info { diff --git a/geoportailv3/static/less/layout.less b/geoportailv3/static/less/layout.less index 03ae7ab7b..b2a2a59ec 100644 --- a/geoportailv3/static/less/layout.less +++ b/geoportailv3/static/less/layout.less @@ -144,3 +144,142 @@ div.ol-full-screen > button { div.ol-zoom-extent > button { text-indent: 4px; } + +.user { + display: inline-block; + float: right; + margin: 0; + padding: 0; + & ul { + margin: 0; + padding: 0; + } + & li { + display: inline-block; + float: left; + background-repeat: no-repeat; + background-position: 1px top; + } +} + +& .second-level { + display: none; + position: absolute; + right: 0px; + text-align: left; + z-index: 10; + width: 320px; + & .open { + display:block; + } +} + +.user .menu-title { + margin: 18px 0px; + padding-left: 10px; + text-transform: uppercase; + font-size: 40px; + color: white; + padding: 0px 20px; +} + +.account-content { + padding: 10px; + clear:both; + & input { + color: white; + height: 43px; + border: none; + font-size: 16px; + &[type=password], + &[type=text] { + float:left; + width:100%; + margin-bottom: 10px; + padding: 17px 10px 10px; + background-color: rgba(46,65,78, 0.2); + -webkit-box-shadow: inset 0px 2px 4px -1px rgba(0, 57, 79, 0.25); + box-shadow: inset 0px 2px 4px -1px rgba(0, 57, 79, 0.25); + } + &[type=submit]{ + float: right; + width: 91px; + height:44px; + line-height:44px; + text-align:center; + text-transform: uppercase; + } + } +} + +.navigation-account .tab{ + padding: 10px 0px 0px; + margin:0px; + float:left; + text-indent:-999em; + position:relative; + width: 41px; + height:41px; + line-height: 41px; + padding: 0px 10px 0px 20px; + margin-left:1px; + font-size:24px; + color: #fff; + cursor:pointer; + width:82px; +} + +.navigation-account p { + margin: 0px; +} +.navigation-account .tab:after { + font-family: "geoportail-icons"; + font-size:28px; + line-height:41px; + color:#fff; + position:absolute; + width:100%; + text-align:center; + text-indent:0; + position:absolute; + top:0; + left:0; + content:'\e02d'; +} + +.account-content > ul li { + float: none; + display: block; + height: auto; + line-height: 31px; + margin-bottom: 1px; + position:relative; + & p, & a { + display: block; + height: auto; + line-height: 31px; + padding: 0px 50px 0px 10px; + color: #fff; + text-decoration: none; + } + & a{ + cursor: pointer; + width: 100%; + text-align: left; + } +} + +.navigation-account fieldset { + border: 0; + margin: 0; + padding: 0; +} +.navigation-account .account-content p { + white-space: normal; +} + +.navigation-account legend { + border: 0 none; + padding: 0; + white-space: normal; +} diff --git a/geoportailv3/static/less/navbars.less b/geoportailv3/static/less/navbars.less index 18ce8c0b8..67107c143 100644 --- a/geoportailv3/static/less/navbars.less +++ b/geoportailv3/static/less/navbars.less @@ -52,7 +52,7 @@ header { bottom: auto; right: 0px; - li { + > li { display: block; float: right; > a { diff --git a/geoportailv3/static/less/theme.less b/geoportailv3/static/less/theme.less index 983b18a1a..c3d7663b2 100644 --- a/geoportailv3/static/less/theme.less +++ b/geoportailv3/static/less/theme.less @@ -43,14 +43,14 @@ } } .nav { - li > a { + & > li > a { background-color: white; &:hover { color: white; background-color: @primary-color; } } - li.active > a { + & > li.active > a { color: white; background-color: @primary-color; } @@ -115,6 +115,40 @@ color: white; } + .navigation-account { + background-color: @secondary-color; + .account-content { + background-color: @primary-color; + } + input[type=submit] { + background-color: @secondary-color; + } + input[type=submit]:hover { + color: @tertiary-color; + } + .tab { + background-color: @primary-color; + } + } + .account-content > ul li a { + background-color: @tertiary-color; + &:hover { + background-color: @secondary-color; + } + } + .account-content > ul li p { + background-color: @secondary-color; + } + .navbar-default .navbar-nav > .active > a { + &:focus, & { + background-color: @primary-color; + color: white; + } + &:hover { + background-color: white; + color: @primary-color; + } + } } } diff --git a/geoportailv3/templates/index.html b/geoportailv3/templates/index.html index b7a8d209b..c5f36abf6 100644 --- a/geoportailv3/templates/index.html +++ b/geoportailv3/templates/index.html @@ -28,9 +28,46 @@