http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/img/ajax-loader.gif ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/img/ajax-loader.gif b/client/enduser/src/main/resources/META-INF/resources/app/img/ajax-loader.gif new file mode 100644 index 0000000..766cf24 Binary files /dev/null and b/client/enduser/src/main/resources/META-INF/resources/app/img/ajax-loader.gif differ
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/img/busy.gif ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/img/busy.gif b/client/enduser/src/main/resources/META-INF/resources/app/img/busy.gif new file mode 100644 index 0000000..e77264f Binary files /dev/null and b/client/enduser/src/main/resources/META-INF/resources/app/img/busy.gif differ http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/img/favicon.png ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/img/favicon.png b/client/enduser/src/main/resources/META-INF/resources/app/img/favicon.png new file mode 100644 index 0000000..aa2f3e2 Binary files /dev/null and b/client/enduser/src/main/resources/META-INF/resources/app/img/favicon.png differ http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/img/logo-green.png ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/img/logo-green.png b/client/enduser/src/main/resources/META-INF/resources/app/img/logo-green.png new file mode 100644 index 0000000..c57b86c Binary files /dev/null and b/client/enduser/src/main/resources/META-INF/resources/app/img/logo-green.png differ http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/img/logo.png ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/img/logo.png b/client/enduser/src/main/resources/META-INF/resources/app/img/logo.png new file mode 100644 index 0000000..f05105e Binary files /dev/null and b/client/enduser/src/main/resources/META-INF/resources/app/img/logo.png differ http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/index.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/index.html b/client/enduser/src/main/resources/META-INF/resources/app/index.html new file mode 100644 index 0000000..6cb7ae6 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html @@ -0,0 +1,116 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<!DOCTYPE html> +<!--[if lt IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> +<!--[if IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]--> +<!--[if IE 8]> <html lang="en" ng-app="myApp" class="no-js lt-ie9"> <![endif]--> +<!--[if gt IE 8]><!--> <html lang="en" ng-app="SyncopeEnduserApp" class="no-js"> <!--<![endif]--> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <title>SyncopeEnduserApp</title> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <!--<link rel="stylesheet" href="bower_components/html5-boilerplate/dist/css/normalize.css">--> + <!--<link rel="stylesheet" href="bower_components/html5-boilerplate/dist/css/main.css">--> + <link rel="stylesheet" href="css/app.css"> + <!--<script src="bower_components/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script>--> + </head> + <body ng-cloak > + <!--<button ng-click=""--> + + <!--[if lt IE 7]> + <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> + <![endif]--> + + <!--<div ng-view ng-cloak ng-controller="ApplicationController"></div>--> + <div ui-view ng-cloak ng-controller="ApplicationController"></div> + + <!-- <footer id="footer" class="hidden-print"> + <ul class="nav pull-right"> + <li> + Copyright © 2015, Apache Syncope + </li> + </ul> + </footer>--> + + <!--default global growl message--> + <!--<div growl></div>--> + + <!-- <div class="hidden-print" id="initialLoaderDiv"> + <img src="img/ajax-loader.gif" class="ajax-loader"/> + </div>--> + + <!-- In production use: + <script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script> + --> + <script type="text/javascript" src="../webjars/jquery/${jquery.version}/jquery.js"></script> + <script src="../webjars/angular/${angular.version}/angular.js"></script> + <script src="../webjars/angular-ui-router/${angular-ui-router.version}/angular-ui-router.js"></script> + <script src="../webjars/angular-animate/${angular-animate.version}/angular-animate.js"></script> + <script src="../webjars/angular-resource/${angular-resource.version}/angular-resource.js"></script> + <script src="../webjars/angular-cookies/${angular-cookies.version}/angular-cookies.js"></script> + <script src="../webjars/angular-sanitize/${angular-sanitize.version}/angular-sanitize.js"></script> + <script src="../webjars/angular-ui-bootstrap/${angular-ui-bootstrap.version}/ui-bootstrap-tpls.js"></script> + <script src="../webjars/angular-ui-select/${angular-ui-select.version}/select.js"></script> + <script src="../webjars/angular-growl-2/${angular-growl-2.version}/angular-growl.js"></script> + <script type="text/javascript" src="../webjars/bootstrap-select/${bootstrap-select.version}/js/bootstrap-select.min.js"></script> + <script src="../webjars/FileSaver.js/${FileSaver.version}/FileSaver.js" type="text/javascript"></script> + <!--main angular application--> + <script src="js/app.js"></script> + <!--services--> + <script src="js/services/authService.js"></script> + <script src="js/services/userSelfService.js"></script> + <script src="js/services/schemaService.js"></script> + <script src="js/services/realmService.js"></script> + <script src="js/services/securityQuestionService.js"></script> + <!--controllers--> + <script src="js/controllers/HomeController.js"></script> + <script src="js/controllers/LoginController.js"></script> + <script src="js/controllers/LanguageController.js"></script> + <script src="js/controllers/UserController.js"></script> + <!--directives--> + <script src="js/directives/dynamicAttribute.js"></script> + <script src="js/directives/dynamicPlainAttributes.js"></script> + <script src="js/directives/dynamicDerivedAttributes.js"></script> + <script src="js/directives/dynamicVirtualAttributes.js"></script> + <script src="js/directives/navigationButtons.js"></script> + <script src="js/directives/loader.js"></script> + <script src="js/directives/equals.js"></script> + <!--filters--> + <script src="js/filters/propsFilter.js"></script> + + + <link rel="shortcut icon" href="img/favicon.png" type="image/png"/> + <link href="css/login.css" rel="stylesheet" type="text/css" /> + <link href="../webjars/jquery-ui/${jquery-ui.version}/jquery-ui.css" rel="stylesheet" type="text/css" /> + <link href="../webjars/bootstrap/${bootstrap.version}/css/bootstrap.min.css" rel="stylesheet" type="text/css" /> + <link href="../webjars/bootstrap-select/${bootstrap-select.version}/css/bootstrap-select.min.css" rel="stylesheet" type="text/css" /> + <link href="../webjars/font-awesome/${font-awesome.version}/css/font-awesome.min.css" rel="stylesheet" type="text/css" /> + <link href="../webjars/ionicons/${ionicons.version}/css/ionicons.min.css" rel="stylesheet" type="text/css" /> + <link href="../webjars/angular-ui-select/${angular-ui-select.version}/select.css" rel="stylesheet" type="text/css"/> + <link href="../webjars/angular-growl-2/${angular-growl-2.version}/angular-growl.css" rel="stylesheet" type="text/css"/> + <link href="../webjars/select2/${select2.version}/select2.css" rel="stylesheet" type="text/css"/> + <link href="css/app.css" rel="stylesheet" type="text/css" /> + <link href="css/login.css" rel="stylesheet" type="text/css" /> + <link href="css/editUser.css" rel="stylesheet" type="text/css" /> + + </body> +</html> http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/app.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js new file mode 100644 index 0000000..1a53f00 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js @@ -0,0 +1,283 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + **/ + +'use strict'; + +angular.module('home', []); +angular.module('login', []); +angular.module('language', []); +angular.module('self', []); + +// Declare app level module which depends on views, and components +var app = angular.module('SyncopeEnduserApp', [ + 'ui.router', + 'ui.bootstrap', + 'ui.select', + 'ngSanitize', + 'ngAnimate', + 'ngResource', + 'ngCookies', + 'angular-growl', + 'home', + 'login', + 'language', + 'self' +]); + +app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', 'growlProvider', + function ($stateProvider, $urlRouterProvider, $httpProvider, growlProvider) { + // route configuration + $stateProvider + .state('home', { + url: '/', + templateUrl: 'views/self.html' + }) + .state('self', { + url: '/self', + templateUrl: 'views/self.html' + }) + .state('user-self-update', { + url: '/user-self-update', + templateUrl: 'views/home.html', + controller: 'HomeController', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + .state('create', { + url: '/self/create', + templateUrl: 'views/editUser.html' + }) + // nested states + // each of these sections will have their own view + // url will be nested (/self/create) + .state('create.credentials', { + url: '/credentials', + templateUrl: 'views/user-credentials.html' + }) + .state('create.plainSchemas', { + url: '/plainSchemas', + templateUrl: 'views/user-plain-schemas.html' + }) + .state('create.derivedSchemas', { + url: '/derivedSchemas', + templateUrl: 'views/user-derived-schemas.html' + }) + .state('create.virtualSchemas', { + url: '/virtualSchemas', + templateUrl: 'views/user-virtual-schemas.html' + }) + // url will be /self/create/schema + .state('create.groups', { + url: '/groups', + templateUrl: 'views/user-groups.html' + }) + .state('create.resources', { + url: '/resources', + templateUrl: 'views/user-resources.html' + }) + .state('update', { + url: '/self/update', + templateUrl: 'views/editUser.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + // nested states + // each of these sections will have their own view + // url will be nested (/self/create) + .state('update.credentials', { + url: '/credentials', + templateUrl: 'views/user-credentials.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + .state('update.plainSchemas', { + url: '/plainSchemas', + templateUrl: 'views/user-plain-schemas.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + .state('update.derivedSchemas', { + url: '/derivedSchemas', + templateUrl: 'views/user-derived-schemas.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + .state('update.virtualSchemas', { + url: '/virtualSchemas', + templateUrl: 'views/user-virtual-schemas.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + // url will be /self/create/schema + .state('update.groups', { + url: '/groups', + templateUrl: 'views/user-groups.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }) + .state('update.resources', { + url: '/resources', + templateUrl: 'views/user-resources.html', + resolve: { + 'authenticated': function (AuthenticationHelper) { + return AuthenticationHelper.authenticated(); + } + } + }); + + // catch all other routes + // send users to the home page + $urlRouterProvider.otherwise('/'); + + // HTTP service configuration + $httpProvider.defaults.withCredentials = true; + + $httpProvider.interceptors.push(function ($q, $rootScope, $location) { + var numLoadings = 0; + return { +// 'request': function (config) { +// numLoadings++; +// // Show loader +// if (config.url.indexOf("skipLoader=true") == -1) { +// $rootScope.$broadcast("loader_show"); +// } +// return config || $q.when(config); +// }, +// 'response': function (response) { +// if ((--numLoadings) === 0) { +// // Hide loader +// $rootScope.$broadcast("loader_hide"); +// } +// return response || $q.when(response); +// }, + 'responseError': function (response) { + if (response.config.url.indexOf("acceptError=true") == -1) { + var status = response.status; + if (status == 401) { + console.log("ERROR " + status); +// $location.path("/self"); + } + if (status == 403) { + console.log("UNAUTHORIZED " + status); +// $location.path("/self"); + } + if (status == 400 || status == 404 || status == 412 || status == 500) { +// if (response.data.validationErrors != undefined) { +// for (var i in response.data.validationErrors) { +// $rootScope.$broadcast('growlMessage', {text: response.data.validationErrors[i] || '', severity: 'error'}); +// } +// } else if (response.data.message != undefined) { +// $rootScope.$broadcast('growlMessage', {text: response.data.message || '', severity: 'error'}) +// } + console.log("GENERIC ERROR " + status); + } + } + return $q.reject(response); + } + }; + }); + + growlProvider.globalTimeToLive(10000); + growlProvider.globalPosition('bottom-left'); + growlProvider.globalInlineMessages(true); + growlProvider.globalDisableIcons(true); + //to enable html in growl +// growlProvider.globalEnableHtml(true); + }]); + +app.run(['$rootScope', '$location', '$cookies', '$state', + function ($rootScope, $location, $cookies, $state) { + // main program + // keep user logged in after page refresh + // check if user is logged or not + $rootScope.currentUser = $cookies.get('currentUser') || null; +//If the route change failed due to authentication error, redirect them out + $rootScope.$on('$routeChangeError', function (event, current, previous, rejection) { + if (rejection === 'Not Authenticated') { + $location.path('/self'); + } + }); + +// $rootScope.$on('success', function (event, args) { +// console.log("IN CONFIG EVENTO: ", event); +// $rootScope.$broadcast("error", "success"); +// }); + + $rootScope.$on('$stateChangeSuccess', function (event, toState) { + if (toState.name === 'create') { + $state.go('create.credentials'); + } else if (toState.name === 'update') { + $state.go('update.credentials'); + } + }); +// $rootScope.$on('$locationChangeStart', function (event, next, current) { +// // redirect to login page if not logged in +// if ($location.path() !== '/self' && !$rootScope.globals.currentUser) { +// $location.path('/self'); +// } +// }); + }]); + +app.controller('ApplicationController', function ($scope) { +// DO NOTHING +// $scope.$on('success', function (event, args) { +// console.log("IN CONFIG EVENTO: ", event) +// $scope.$broadcast("error", "success"); +// }); +}); + +app.factory('AuthenticationHelper', ['$q', '$rootScope', + function ($q, $rootScope) { + return { + authenticated: function () { + + var currentUser = $rootScope.currentUser; + + console.log("AuthenticationHelper, currentUser: ", currentUser); + + if (angular.isDefined(currentUser) && currentUser) { + return true; + } else { + console.log("NOT AUTHENTICATED, REDIRECT TO LOGIN PAGE"); + return $q.reject('Not Authenticated'); + } + } + }; + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/HomeController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/HomeController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/HomeController.js new file mode 100644 index 0000000..bf86413 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/HomeController.js @@ -0,0 +1,39 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + **/ + +'use strict'; + +angular.module("home").controller("HomeController", ['$scope', '$http', '$location', function ($scope, $http, $location) { + $scope.title = 'Hello world!'; + $scope.subtitle = 'Hello world SUBTITLE!'; + $scope.name = ""; + +// check if user is logged or not, check session variables: if user isn't logged redirect to login page + + console.log("SONO IN HomeController"); + +// var isLogged = false; +// if (!isLogged) { +// console.log("REDIRECT TO LOGIN PAGE"); +//// window.location = "./self.html"; +// $location.path("/self"); +// } + + + }]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LanguageController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LanguageController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LanguageController.js new file mode 100644 index 0000000..9e1fa6c --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LanguageController.js @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('language') + .controller('LanguageController', function ($scope) { + + $scope.languages = { + availableLanguages: [ + {id: '1', name: 'Italiano'}, + {id: '2', name: 'English'}, + {id: '3', name: 'Portugese'} + ], + selectedLanguage: {id: '2', name: 'English'} + }; + + $scope.init = function () { +// MainService.settings().then(function (response) { +// $scope.mainSettings = response; +// }); + + console.log("Init language controller"); + }; + + $scope.changeLanguage = function (language) { + + console.log("Language changed to: ", language); + + $scope.languages.selectedLanguage = language; + +// $translate.use(langKey); +// LanguageService.switchLocale.query({language: langKey}, {}, function (response) { +// $scope.selectedLanguage.locale = langKey; +// }); + }; + + this.retrieveLanguages = function () { +// LanguageService.language.query({}, function (response) { +// $scope.languages = response; +// }); + console.log("Retriebìving available languages"); + }; + + + this.retrieveLanguages(); + + + }); + http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js new file mode 100644 index 0000000..c962571 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module("login").controller("LoginController", ['$scope', '$rootScope', '$http', '$location', '$cookies', + 'AuthService', 'growl', function ($scope, $rootScope, $http, $location, $cookies, AuthService, growl) { + + $scope.credentials = { + username: '', + password: '', + errorMessage: '' + }; + + $scope.login = function (credentials) { + + console.log("CREDENTIALS FROM PAGE: ", credentials); + console.log("AUTHSERVICE: ", AuthService); + + AuthService.login($scope.credentials).then(function (user) { + console.log("LOGIN SUCCESS FOR: ", user); + console.log("DOPO AVER SETTATO CURRENT USER: ", $rootScope.currentUser); + console.log("COOKIE CURRENT USER: ", $cookies.get('currentUser')); + // reset error message + $scope.credentials.errorMessage = ''; + // got to update page + $location.path("/self/update"); + }, function (response) { + console.log("LOGIN FAILED: ", response); + $scope.credentials.errorMessage = "Login failed: " + response; + growl.error($scope.credentials.errorMessage, {referenceId: 1}); + }); + }; + + $scope.logout = function () { + + console.log("PERFORMING LOGOUT"); + + AuthService.logout().then(function (response) { + console.log("LOGOUT SUCCESS: ", response); + }, function () { + console.log("LOGOUT FAILED"); + }); + }; + + $scope.isLogged = function () { + return angular.isDefined($rootScope.currentUser) && $rootScope.currentUser; + }; + + $scope.selfCreate = function () { + $location.path("/self/create"); + }; + + $scope.passwordReset = function () { + // TODO + console.log("NOT YET IMPLEMENTED") + }; + + $scope.errorAPI = function () { + $http.get("/syncope-enduser/api/error").success(function (data) { + console.log("errorAPI response: ", data); + }); + }; + + $scope.sampleAPI = function () { + $http.get("/syncope-enduser/api/user-self").success(function (data) { + console.log("sampleAPI response: ", data); + }); + }; + + $scope.schemaAPI = function () { + $http.get("/syncope-enduser/api/schema").success(function (data) { + console.log("schemaAPI response: ", data); + }); + }; + + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js new file mode 100644 index 0000000..892de21 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module("self").controller("UserController", ['$scope', '$rootScope', '$location', 'AuthService', + 'UserSelfService', 'SchemaService', 'RealmService', 'SecurityQuestionService', 'growl', function ($scope, $rootScope, + $location, AuthService, UserSelfService, SchemaService, RealmService, SecurityQuestionService, growl) { + + $scope.user = {}; + $scope.confirmPassword = { + value: '' + }; + $scope.userFormValid = false; + $scope.createMode = $location.path().indexOf("/self/create") > -1; + + $scope.availableRealms = []; + $scope.availableSecurityQuestions = []; + + $scope.initialSecurityQuestion = undefined; + + $scope.initUser = function () { + + $scope.dynamicForm = { + plainSchemas: [], + derSchemas: [], + virSchemas: [], + selectedDerSchemas: [], + selectedVirSchemas: [], + errorMessage: '', + attributeTable: {} + }; + + + var initSchemas = function () { + // initialization is done here synchronously to have all schema fields populated correctly + SchemaService.getUserSchemas().then(function (schemas) { + $scope.dynamicForm.plainSchemas = schemas.plainSchemas; + $scope.dynamicForm.derSchemas = schemas.derSchemas; + $scope.dynamicForm.virSchemas = schemas.virSchemas; + + // initialize plain attributes + for (var i = 0; i < schemas.plainSchemas.length; i++) { + + var plainSchemaKey = schemas.plainSchemas[i].key; + + if (!$scope.user.plainAttrs[plainSchemaKey]) { + + $scope.user.plainAttrs[plainSchemaKey] = { + schema: plainSchemaKey, + values: [], + readonly: schemas.plainSchemas[i].readonly + }; + + // initialize multivalue schema and support table: create mode, only first value + if (schemas.plainSchemas[i].multivalue) { + $scope.dynamicForm.attributeTable[schemas.plainSchemas[i].key] = { + fields: [schemas.plainSchemas[i].key + "_" + 0] + }; + } + } else { + // initialize multivalue schema and support table: update mode, all provided values + if (schemas.plainSchemas[i].multivalue) { + $scope.dynamicForm.attributeTable[schemas.plainSchemas[i].key] = { + fields: [schemas.plainSchemas[i].key + "_" + 0] + }; + // add other values + for (var j = 1; j < $scope.user.plainAttrs[plainSchemaKey].values.length; j++) { + $scope.dynamicForm.attributeTable[schemas.plainSchemas[i].key].fields.push(schemas.plainSchemas[i].key + "_" + j); + } + } + } + } + + // initialize derived attributes + for (var i = 0; i < schemas.derSchemas.length; i++) { + + var derSchemaKey = schemas.derSchemas[i].key; + + if ($scope.user.derAttrs[derSchemaKey]) { + $scope.dynamicForm.selectedDerSchemas.push(schemas.derSchemas[i]); + } + } + + // initialize virtual attributes + for (var i = 0; i < schemas.virSchemas.length; i++) { + + var virSchemaKey = schemas.virSchemas[i].key; + + if ($scope.user.virAttrs[virSchemaKey]) { + $scope.dynamicForm.selectedVirSchemas.push(schemas.virSchemas[i]); + } + } + + }, function () { + console.log("Error retrieving user schemas"); + }); + console.log("USER WITH ATTRTO: ", $scope.user); + + }; + + var initSecurityQuestions = function () { + SecurityQuestionService.getAvailableSecurityQuestions().then(function (response) { + $scope.availableSecurityQuestions = response; + }, function () { + console.log("Error"); + }); + }; + + var initRealms = function () { + $scope.availableRealms = RealmService.getAvailableRealmsStub(); + }; + + var initUserRealm = function () { + $scope.user.realm = RealmService.getUserRealm(); + }; + + + var readUser = function () { + UserSelfService.read().then(function (response) { + $scope.user = response; + $scope.user.password = undefined; + $scope.initialSecurityQuestion = $scope.user.securityQuestion; + }, function () { + console.log("Error"); + }); + }; + + if ($scope.createMode) { + + $scope.user = { + username: '', + password: '', + realm: '', + securityQuestion: undefined, + securityAnswer: '', + plainAttrs: {}, + derAttrs: {}, + virAttrs: {} + }; + + // retrieve user realm or all available realms + initUserRealm(); + + } else { + + // read user from syncope core + readUser(); + // read user security question + + } + + initRealms(); + //retrieve security available questions + initSecurityQuestions(); + // initialize user attributes starting from any object schemas + initSchemas(); + + }; + + $scope.saveUser = function (user) { + console.log("Save user: ", user); + + if ($scope.createMode) { + + UserSelfService.create(user).then(function (response) { + console.log("Created user: ", response); + growl.success("User " + $scope.user.username + " successfully created", {referenceId: 1}); + $location.path('/self'); + }, function (response) { + console.log("Error during user creation: ", response); + growl.error("Error: " + response, {referenceId: 2}); + }); + + } else { + + UserSelfService.update(user).then(function (response) { + console.log("Updated user: ", response); + growl.success("User " + $scope.user.username + " successfully updated", {referenceId: 1}); + $location.path('/self'); + }, function (response) { + console.log("Error during user update: ", response); + growl.error("Error: " + response, {referenceId: 2}); + }); + } + }; + + + + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicAttribute.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicAttribute.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicAttribute.js new file mode 100644 index 0000000..6a00507 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicAttribute.js @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +'use strict'; + +angular.module('self') + .directive('dynamicAttribute', function ($filter) { + return { + restrict: 'E', + templateUrl: 'views/dynamicAttribute.html', + scope: { + schema: "=", + index: "=", + user: "=" + }, + controller: function ($scope, $element, $window) { + $scope.initAttribute = function (schema, index) { + + switch (schema.type) { + case "Long": + case "Double": + $scope.user.plainAttrs[schema.key].values[index] = Number($scope.user.plainAttrs[schema.key].values[index]) + || undefined; + break; + case "Enum": + $scope.enumerationValues = []; + var enumerationValuesSplitted = schema.enumerationValues.toString().split(";"); + for (var i = 0; i < enumerationValuesSplitted.length; i++) { + $scope.enumerationValues.push(enumerationValuesSplitted[i]); + } + $scope.user.plainAttrs[schema.key].values[index] = $scope.user.plainAttrs[schema.key].values[index] + || $scope.enumerationValues[0]; + break; + case "Binary": + + $scope.userFile = $scope.userFile || ''; + //for multivalue fields +// $scope.fileInputId = "fileInputId_" + index; + + $element.bind("change", function (changeEvent) { + $scope.$apply(function () { + var reader = new FileReader(); + var file = changeEvent.target.files[0]; + $scope.userFile = file.name; + reader.onload = function (readerEvt) { + var binaryString = readerEvt.target.result; + $scope.user.plainAttrs[schema.key].values[index] = btoa(binaryString); + }; + reader.readAsBinaryString(file); + }); + }); + + $scope.download = function () { + var byteString = atob($scope.user.plainAttrs[schema.key].values[index]); + + var ab = new ArrayBuffer(byteString.length); + var ia = new Uint8Array(ab); + for (var i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + + var blob = new Blob([ia], {type: schema.mimeType}); + + saveAs(blob, schema.key); + }; + $scope.remove = function () { + $scope.user.plainAttrs[schema.key].values.splice(index, 1); + $scope.userFile = ''; + $("#fileInput").replaceWith($("#fileInput").clone(true)); + }; + break; + case "Date": + + $scope.selectedDate = $scope.user.plainAttrs[schema.key].values[index]; + $scope.format = $scope.schema.conversionPattern; + $scope.includeTimezone = false; + if ($scope.schema.conversionPattern.indexOf(".SSS") > -1) { + $scope.format = $scope.format.replace(".SSS", ".sss"); + } + if ($scope.schema.conversionPattern.indexOf("Z") > -1) { + $scope.includeTimezone = true; + $scope.format = $scope.format.replace("Z", ""); + } + if ($scope.schema.conversionPattern.indexOf("\'") > -1) { + $scope.format = $scope.format.replace(new RegExp("\'", "g"), ""); + } + + $scope.bindDateToModel = function (selectedDate, format) { + var newFormat = $scope.includeTimezone ? format.concat(" Z") : format; + if (selectedDate) { + selectedDate = $filter('date')(selectedDate, newFormat); + var dateGood = selectedDate.toString(); + $scope.user.plainAttrs[schema.key].values[index] = dateGood; + } else { + $scope.user.plainAttrs[schema.key].values[index] = selectedDate; + } + }; + + $scope.clear = function () { + $scope.user.plainAttrs[schema.key].values[index] = null; + }; + + // Disable weekend selection + $scope.disabled = function (date, mode) { + // example if you want to disable weekends + // return (mode === 'day' && (date.getDay() === 0 || date.getDay() === 6)); + return false; + }; + + $scope.toggleMin = function () { + $scope.minDate = $scope.minDate ? null : new Date(); + }; + + $scope.maxDate = new Date(2050, 5, 22); + + $scope.open = function ($event) { + $scope.status.opened = true; + }; + + $scope.setDate = function (year, month, day) { + $scope.user.plainAttrs[schema.key].values[index] = new Date(year, month, day); + }; + + $scope.dateOptions = { + startingDay: 1 + }; + + $scope.status = { + opened: false + }; + + var tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + var afterTomorrow = new Date(); + afterTomorrow.setDate(tomorrow.getDate() + 2); + $scope.events = + [ + { + date: tomorrow, + status: 'full' + }, + { + date: afterTomorrow, + status: 'partially' + } + ]; + + $scope.getDayClass = function (date, mode) { + if (mode === 'day') { + var dayToCheck = new Date(date).setHours(0, 0, 0, 0); + + for (var i = 0; i < $scope.events.length; i++) { + var currentDay = new Date($scope.events[i].date).setHours(0, 0, 0, 0); + + if (dayToCheck === currentDay) { + return $scope.events[i].status; + } + } + } + + }; + break; + + case "Boolean": + $scope.user.plainAttrs[schema.key].values[index] = + Boolean($scope.user.plainAttrs[schema.key].values[index]) || false; + break; + + } + } + ; + }, + replace: true + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicDerivedAttributes.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicDerivedAttributes.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicDerivedAttributes.js new file mode 100644 index 0000000..887b5c6 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicDerivedAttributes.js @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +'use strict'; + +angular.module('self') + .directive('dynamicDerivedAttributes', function () { + return { + restrict: 'E', + templateUrl: 'views/dynamicDerivedAttributes.html', + scope: { + dynamicForm: "=form", + user: "=" + }, + controller: function ($scope) { + + $scope.addDerivedAttribute = function (item, model) { + var derSchemaKey = item.key; + console.log("ADDING DERIVED item: ", derSchemaKey); + $scope.user.derAttrs[derSchemaKey] = { + schema: derSchemaKey, + values: [], + readonly: false + }; + + }; + + $scope.removeDerivedAttribute = function (item, model) { + var derSchemaKey = item.key; + console.log("REMOVING DERIVED item: ", derSchemaKey); + delete $scope.user.derAttrs[derSchemaKey]; + + }; + + } + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttributes.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttributes.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttributes.js new file mode 100644 index 0000000..1a0a4c3 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttributes.js @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +'use strict'; + +angular.module('self') + .directive('dynamicPlainAttributes', function (SchemaService) { + return { + restrict: 'E', + templateUrl: 'views/dynamicPlainAttributes.html', + scope: { + dynamicForm: "=form", + user: "=" + }, + controller: function ($scope) { + + $scope.addAttributeField = function (plainSchemaKey) { + console.log("ADDING: ", plainSchemaKey + "_" + ($scope.dynamicForm.attributeTable[plainSchemaKey].fields.length)); + $scope.dynamicForm.attributeTable[plainSchemaKey].fields.push(plainSchemaKey + "_" + ($scope.dynamicForm.attributeTable[plainSchemaKey].fields.length)); + }; + + $scope.removeAttributeField = function (plainSchemaKey, index) { + console.log("REMOVING FROM: " + plainSchemaKey + " ATTRIBUTE INDEX: " + index); + $scope.dynamicForm.attributeTable[plainSchemaKey].fields.splice(index, 1); + // clean user model + $scope.user.plainAttrs[plainSchemaKey].values.splice(index, 1); + }; + } + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js new file mode 100644 index 0000000..62c1591 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +'use strict'; + +angular.module('self') + .directive('dynamicVirtualAttributes', function () { + return { + restrict: 'E', + templateUrl: 'views/dynamicVirtualAttributes.html', + scope: { + dynamicForm: "=form", + user: "=" + }, + controller: function ($scope) { + + $scope.addVirtualAttribute = function (item, model) { + var virSchemaKey = item.key; + console.log("ADDING VIRTUAL item: ", virSchemaKey); + $scope.user.virAttrs[virSchemaKey] = { + schema: virSchemaKey, + values: [], + readonly: false + }; + + }; + + $scope.removeVirtualAttribute = function (item, model) { + var virSchemaKey = item.key; + console.log("REMOVING VIRTUAL item: ", virSchemaKey); + delete $scope.user.virAttrs[virSchemaKey]; + + }; + + } + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/equals.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/equals.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/equals.js new file mode 100644 index 0000000..54c2022 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/equals.js @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +angular.module('self') + .directive('equals', function () { + return { + restrict: 'A', + require: '?ngModel', + link: function (scope, elem, attrs, ngModel) { + if (!ngModel) + return; // do nothing if no ng-model + + // watch own value and re-validate on change + scope.$watch(attrs.ngModel, function () { + validate(); + }); + + // observe the other value and re-validate on change + attrs.$observe('equals', function (val) { + validate(); + }); + + var validate = function () { + // values + var val1 = ngModel.$viewValue; + var val2 = attrs.equals; + + // set validity + ngModel.$setValidity('equals', !val1 || !val2 || val1 === val2); + }; + } + }; + }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/loader.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/loader.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/loader.js new file mode 100644 index 0000000..603fb34 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/loader.js @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('SyncopeEnduserApp') + .directive("loader", function ($rootScope) { + return function ($scope, element, attrs) { + $scope.$on("loader_show", function () { + return element.show(); + }); + return $scope.$on("loader_hide", function () { + return element.hide(); + }); + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js new file mode 100644 index 0000000..ff3eebf --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +'use strict'; + +angular.module('self') + .directive('navigationButtons', function () { + return { + restrict: 'E', + templateUrl: 'views/navigationButtons.html', + scope: { + next: "@", + previous: "@" + } + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/directives/passwordStrengthEstimator.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/passwordStrengthEstimator.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/passwordStrengthEstimator.js new file mode 100644 index 0000000..4bf52b2 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/passwordStrengthEstimator.js @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict' + +angular.module('self', []) + .directive('checkStrength', function () { + return { + replace: false, + restrict: 'EACM', + link: function (scope, iElement, iAttrs) { + + var strength = { + colors: ['#F00', '#F90', '#FF0', '#9F0', '#0F0'], + mesureStrength: function (p) { + + var _force = 0; + var _regex = /[$-/:-?{-~!"^_`\[\]]/g; + + var _lowerLetters = /[a-z]+/.test(p); + var _upperLetters = /[A-Z]+/.test(p); + var _numbers = /[0-9]+/.test(p); + var _symbols = _regex.test(p); + + var _flags = [_lowerLetters, _upperLetters, _numbers, _symbols]; + var _passedMatches = $.grep(_flags, function (el) { + return el === true; + }).length; + + _force += 2 * p.length + ((p.length >= 10) ? 1 : 0); + _force += _passedMatches * 10; + + // penality (short password) + _force = (p.length <= 6) ? Math.min(_force, 10) : _force; + + // penality (poor variety of characters) + _force = (_passedMatches == 1) ? Math.min(_force, 10) : _force; + _force = (_passedMatches == 2) ? Math.min(_force, 20) : _force; + _force = (_passedMatches == 3) ? Math.min(_force, 40) : _force; + + return _force; + + }, + getColor: function (s) { + + var idx = 0; + if (s <= 10) { + idx = 0; + } + else if (s <= 20) { + idx = 1; + } + else if (s <= 30) { + idx = 2; + } + else if (s <= 40) { + idx = 3; + } + else { + idx = 4; + } + + return {idx: idx + 1, col: this.colors[idx]}; + + } + }; + + scope.$watch(iAttrs.checkStrength, function () { + if (scope.pw === '') { + iElement.css({"display": "none"}); + } else { + var strength = strength.mesureStrength(scope.pw); + var c = strength.getColor(strength); + iElement.css({"display": "inline"}); + iElement.children('li') + .css({"background": "#DDD"}) + .slice(0, c.idx) + .css({"background": c.col}); + } + }); + + }, + template: '' + }; + }); + http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js b/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js new file mode 100644 index 0000000..a092d0c --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict' + +angular.module("self") + .filter('propsFilter', function () { + return function (items, props) { + var out = []; + + if (angular.isArray(items)) { + items.forEach(function (item) { + var itemMatches = false; + + var keys = Object.keys(props); + for (var i = 0; i < keys.length; i++) { + var prop = keys[i]; + var text = props[prop].toLowerCase(); + if (item[prop].toString().toLowerCase().indexOf(text) !== -1) { + itemMatches = true; + break; + } + } + + if (itemMatches) { + out.push(item); + } + }); + } else { + // Let the output be the input untouched + out = items; + } + + return out; + }; + }); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/services/authService.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/authService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/authService.js new file mode 100644 index 0000000..3c3f7af --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/authService.js @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('login') + .factory('AuthService', ['$rootScope', '$resource', '$q', '$http', '$cookies', + function ($rootScope, $resource, $q, $http, $cookies) { + + var authService = {}; + + var clearUserCookie = function () { + $rootScope.currentUser = null; + $cookies.remove('currentUser'); + }; + + authService.login = function (credentials) { + return $http + .post('/syncope-enduser/api/login', credentials) + .then(function (response) { + var username = response.data; + $cookies.put('currentUser', username); + $rootScope.currentUser = username; + return username; + }, function (response) { + clearUserCookie(); + console.log("Something went wrong during login, exit with status: ", response); + return $q.reject(response.data || response.statusText); + }); + }; + + authService.logout = function () { + return $http + .get('/syncope-enduser/api/logout') + .then(function (response) { + clearUserCookie(); + return response; + }, function (response) { + clearUserCookie(); + console.log("Something went wrong during logout, exit with status: ", response); + }); + }; + + return authService; +// return { +// login: $resource('/syncope-enduser/api/login', {}, { +// do: {method: 'POST', params: {}, isArray: false} +// }) +// }; +// return { +// logout: $resource('/cradleDashboard/api/logout', {}, { +// query: {method: 'GET', params: {}, isArray: false} +// }) +// }; + + }]); + + http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/services/realmService.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/realmService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/realmService.js new file mode 100644 index 0000000..356dc87 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/realmService.js @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('self') + .factory('RealmService', ['$resource', '$q', '$http', + function ($resource, $q, $http) { + + var realmService = {}; + + realmService.getAvailableRealmsStub = function () { + return ["/"]; + }; + + realmService.getAvailableRealms = function () { + return $http.get("/syncope-enduser/api/realms") + .then(function (response) { + console.log("realms response: ", response); + return response.data; + }, function (response) { + console.log("Something went wrong during realms retrieval, exit with status: ", response); + return $q.reject(response.data || response.statusText); + }); + }; + + realmService.getUserRealm = function () { + return "/"; + }; + return realmService; + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/services/schemaService.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/schemaService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/schemaService.js new file mode 100644 index 0000000..be9f510 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/schemaService.js @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('self') + .factory('SchemaService', ['$resource', '$q', '$http', + function ($resource, $q, $http) { + + var schemaService = {}; + + schemaService.getUserSchemas = function () { + + return $http.get("/syncope-enduser/api/schemas") + .then(function (response) { + console.log("schemaAPI response: ", response); + return response.data; + }, function (response) { + console.log("Something went wrong during schema retrieval, exit with status: ", response); + return $q.reject(response.data || response.statusText); + }); + }; + return schemaService; + }]); + + http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/services/securityQuestionService.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/securityQuestionService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/securityQuestionService.js new file mode 100644 index 0000000..ff91f18 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/securityQuestionService.js @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('self') + .factory('SecurityQuestionService', ['$resource', '$q', '$http', + function ($resource, $q, $http) { + + var securityQuestionService = {}; + + securityQuestionService.getAvailableSecurityQuestions = function () { + return $http.get("/syncope-enduser/api/securityQuestions") + .then(function (response) { + console.log("security questions response: ", response); + return response.data; + }, function (response) { + console.log("Something went wrong during security questions retrieval, exit with status: ", + response); + return $q.reject(response.data || response.statusText); + }); + }; + + return securityQuestionService; + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/js/services/userSelfService.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/userSelfService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/userSelfService.js new file mode 100644 index 0000000..3a99e7f --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/userSelfService.js @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +'use strict'; + +angular.module('login') + .factory('UserSelfService', ['$resource', '$q', '$http', + function ($resource, $q, $http) { + + var userSelfService = {}; + + userSelfService.read = function () { + return $http + .get('/syncope-enduser/api/self/read') + .then(function (response) { + console.log("response read: ", response.data); + return response.data; + }, function (response) { + console.log("Something went wrong during user self read, exit with status: ", response); + return $q.reject(response.data || response.statusText); + }); + }; + + userSelfService.create = function (user) { + return $http + .post('/syncope-enduser/api/self/create', user) + .then(function (response) { + console.log("response save: ", response) + var username = response; + }, function (response) { + console.log("Something went wrong during user self creation, exit with status: ", response); + return $q.reject(response.data || response.statusText); + }); + }; + + userSelfService.update = function (user) { + return $http + .post('/syncope-enduser/api/self/update', user) + .then(function (response) { + var username = response; + }, function (response) { + console.log("Something went wrong during user self update, exit with status: ", response); + return $q.reject(response.data || response.statusText); + }); + }; + + userSelfService.passwordReset = function () { + }; + + return userSelfService; + }]); + + http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicAttribute.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicAttribute.html b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicAttribute.html new file mode 100644 index 0000000..9c6b1d9 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicAttribute.html @@ -0,0 +1,58 @@ +<div ng-switch="schema.type" > + <input ng-switch-when="String" class="form-control" type="text" + ng-model="user.plainAttrs[schema.key].values[index]" + ng-required="schema.mandatoryCondition" + ng-disabled="schema.readonly" ng-init="initAttribute(schema, index)"/> + <input ng-switch-when="Encrypted" class="form-control" type="text" + ng-model="user.plainAttrs[schema.key].values[index]" + ng-required="schema.mandatoryCondition" + ng-disabled="schema.readonly" ng-init="initAttribute(schema, index)"/> + <div ng-switch-when="Boolean"> + <input type="checkbox" ng-model="user.plainAttrs[schema.key].values[index]" ng-required="schema.mandatoryCondition" + ng-init="initAttribute(schema, index)" /> + </div> + <input ng-switch-when="Long" class="form-control" type="number" ng-model="user.plainAttrs[schema.key].values[index]" ng-required="schema.mandatoryCondition" + ng-init="initAttribute(schema, index)" /> + <input ng-switch-when="Double" class="form-control" type="number" ng-model="user.plainAttrs[schema.key].values[index]" ng-required="schema.mandatoryCondition" + ng-init="initAttribute(schema, index)" /> + <p ng-switch-when="Date" class="input-group" > + <input type="text" class="form-control" + uib-datepicker-popup="{{format}}" + ng-model="selectedDate" + ng-change="bindDateToModel(selectedDate, format)" + min-date="minDate" max-date="maxDate" + is-open="status.opened" datepicker-options="dateOptions" + ng-required="schema.mandatoryCondition" close-text="Close" ng-init="initAttribute(schema, index)"/> + <span class="input-group-btn"> + <button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button> + </span> + </p> + + <div ng-switch-when="Enum" ng-init="initAttribute(schema, index)"> + <select class="form-control" + ng-model="user.plainAttrs[schema.key].values[index]" + ng-required="schema.mandatoryCondition"> + <option ng-repeat="value in enumerationValues" value="{{value}}">{{schema.enumerationKeys[$index] || value}}</option> + </select> + </div> + + <div ng-switch-when="Binary" ng-init="initAttribute(schema, index)"> + <div enctype="multipart/form-data" accept-charset="UTF-8"> + <input id="fileInput" type="file" ng-required="schema.mandatoryCondition"/> + <button type="button" title="Download file" class="fileButton btn btn-default btn-sm" ng-click="download()"> + <i class="glyphicon glyphicon-download" ></i> + </button> + <button type="button" class="fileButton btn btn-default btn-sm" title="Remove file" ng-click="remove()"> + <i class="glyphicon glyphicon-remove-sign" ></i> + </button> + <h4><span class="label label-primary" ng-model="userFile">{{userFile}}</span></h4> + </div> + + </div> + + <input ng-switch-default class="form-control" type="text" + ng-model="user.plainAttrs[schema.key].values[index]" + ng-required="schema.mandatoryCondition" + ng-disabled="schema.readonly" ng-init="initAttribute(schema, index)"/> + +</div> http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicDerivedAttributes.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicDerivedAttributes.html b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicDerivedAttributes.html new file mode 100644 index 0000000..9400877 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicDerivedAttributes.html @@ -0,0 +1,21 @@ +<ui-select on-select="addDerivedAttribute($item, $model)" on-remove="removeDerivedAttribute($item, $model)" multiple + ng-model="dynamicForm.selectedDerSchemas" theme="select2" class="attribute-ui-select"> + <ui-select-match placeholder="Select derived attribute...">{{$item.key}}</ui-select-match> + <ui-select-choices repeat="derSchema in dynamicForm.derSchemas | propsFilter: {key: $select.search}"> + <div ng-bind-html="derSchema.key | highlight: $select.search"></div> + <small> + name: {{derSchema.key}} + expression: {{derSchema.expression}} + </small> + </ui-select-choices> +</ui-select> + +<ul class="attribute-virtual-value-container"> + <li class="attribute-virtual-value-field" ng-repeat="selectedDerSchema in dynamicForm.selectedDerSchemas| filter:q as results"> + {{selectedDerSchema.key}} + <input style="font-weight: normal" class="form-control" type="text" ng-disabled="true" ng-model="user.derAttrs[selectedDerSchema.key].values[0]"/> + </li> + <li class="attribute-virtual-value-field" ng-if="results.length == 0"> + <strong>No derived attributes selected...</strong> + </li> +</ul> http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicPlainAttributes.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicPlainAttributes.html b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicPlainAttributes.html new file mode 100644 index 0000000..074abbd --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicPlainAttributes.html @@ -0,0 +1,22 @@ +<div id="attribute" class="form-group" ng-repeat="plainSchema in dynamicForm.plainSchemas"> + <label for="plainSchema.key">{{plainSchema.key}} <span ng-if="Boolean(plainSchema.mandatoryCondition)">*</span></label> + <div ng-if="!plainSchema.multivalue"> + <dynamic-attribute schema="plainSchema" user="user" index="0"></dynamic-attribute> + </div> + + <div ng-if="plainSchema.multivalue"> + <div ng-repeat="field in dynamicForm.attributeTable[plainSchema.key].fields track by $index" ng-model='dynamicForm.attributeTable[plainSchema.key].fields[$index]'> + <dynamic-attribute schema="plainSchema" user="user" index="$index"></dynamic-attribute> + <span> + <button class="btn btn-default btn-sm minus" ng-if="$index > 0" type="button" ng-click="removeAttributeField(plainSchema.key, $index)"> + <i class="glyphicon glyphicon-minus" title="Remove value"></i> + </button> + </span> + </div> + <span> + <button class="btn btn-default btn-sm" type="button" ng-click="addAttributeField(plainSchema.key)"> + <i class="glyphicon glyphicon-plus" title="Add value"></i> + </button> + </span> + </div> +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicVirtualAttributes.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicVirtualAttributes.html b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicVirtualAttributes.html new file mode 100644 index 0000000..897eb2c --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/views/dynamicVirtualAttributes.html @@ -0,0 +1,18 @@ +<ui-select on-select="addVirtualAttribute($item, $model)" on-remove="removeVirtualAttribute($item, $model)" multiple + ng-model="dynamicForm.selectedVirSchemas" theme="select2" ng-disabled="false" class="attribute-ui-select"> + <ui-select-match placeholder="Select virtual attribute...">{{$item.key}}</ui-select-match> + <ui-select-choices repeat="virSchema in dynamicForm.virSchemas | propsFilter: {key: $select.search}"> + <div ng-bind-html="virSchema.key | highlight: $select.search"></div> + </ui-select-choices> +</ui-select> + +<ul class="attribute-virtual-value-container"> + <li class="attribute-virtual-value-field" ng-repeat="selectedVirSchema in dynamicForm.selectedVirSchemas| filter:q as results"> + {{selectedVirSchema.key}} + <input style="font-weight: normal" class="form-control" type="text" ng-disabled="selectedVirSchema.readonly" + ng-model="user.virAttrs[selectedVirSchema.key].values[0]"/> + </li> + <li class="attribute-virtual-value-field" ng-if="results.length == 0"> + <strong>No virtual attributes selected...</strong> + </li> +</ul> \ No newline at end of file