You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2015/10/30 10:34:03 UTC
[3/4] syncope git commit: SYNCOPE-701 first working implementation
SYNCOPE-701 first working implementation
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/223a64e2
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/223a64e2
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/223a64e2
Branch: refs/heads/master
Commit: 223a64e26deff69a4ed8275d0f1348ca4e130a01
Parents: 764fa2e
Author: Andrea Patricelli <an...@tirasa.net>
Authored: Mon Oct 5 15:12:55 2015 +0200
Committer: Andrea Patricelli <an...@tirasa.net>
Committed: Fri Oct 30 10:26:17 2015 +0100
----------------------------------------------------------------------
client/enduser/pom.xml | 194 +++++++++
.../enduser/SyncopeEnduserApplication.java | 157 +++++++
.../client/enduser/SyncopeEnduserSession.java | 279 +++++++++++++
.../client/enduser/adapters/UserTOAdapter.java | 78 ++++
.../client/enduser/model/Credentials.java | 65 +++
.../client/enduser/model/SchemaResponse.java | 79 ++++
.../client/enduser/model/UserTORequest.java | 174 ++++++++
.../syncope/client/enduser/pages/HomePage.java | 35 ++
.../enduser/resources/AbstractBaseResource.java | 58 +++
.../client/enduser/resources/ErrorResource.java | 50 +++
.../client/enduser/resources/LoginResource.java | 84 ++++
.../enduser/resources/LogoutResource.java | 43 ++
.../enduser/resources/SchemaResource.java | 116 ++++++
.../resources/SecurityQuestionResource.java | 73 ++++
.../resources/UserSelfCreateResource.java | 97 +++++
.../enduser/resources/UserSelfReadResource.java | 66 +++
.../resources/UserSelfUpdateResource.java | 96 +++++
.../META-INF/resources/app/css/app.css | 28 ++
.../META-INF/resources/app/css/editUser.css | 253 ++++++++++++
.../META-INF/resources/app/css/login.css | 103 +++++
.../META-INF/resources/app/img/ajax-loader.gif | Bin 0 -> 1924 bytes
.../META-INF/resources/app/img/busy.gif | Bin 0 -> 2834 bytes
.../META-INF/resources/app/img/favicon.png | Bin 0 -> 641 bytes
.../META-INF/resources/app/img/logo-green.png | Bin 0 -> 12178 bytes
.../META-INF/resources/app/img/logo.png | Bin 0 -> 8913 bytes
.../resources/META-INF/resources/app/index.html | 116 ++++++
.../resources/META-INF/resources/app/js/app.js | 283 +++++++++++++
.../app/js/controllers/HomeController.js | 39 ++
.../app/js/controllers/LanguageController.js | 66 +++
.../app/js/controllers/LoginController.js | 93 +++++
.../app/js/controllers/UserController.js | 206 +++++++++
.../app/js/directives/dynamicAttribute.js | 190 +++++++++
.../js/directives/dynamicDerivedAttributes.js | 52 +++
.../app/js/directives/dynamicPlainAttributes.js | 45 ++
.../js/directives/dynamicVirtualAttributes.js | 52 +++
.../resources/app/js/directives/equals.js | 49 +++
.../resources/app/js/directives/loader.js | 32 ++
.../app/js/directives/navigationButtons.js | 31 ++
.../js/directives/passwordStrengthEstimator.js | 102 +++++
.../resources/app/js/filters/propsFilter.js | 52 +++
.../resources/app/js/services/authService.js | 74 ++++
.../resources/app/js/services/realmService.js | 47 +++
.../resources/app/js/services/schemaService.js | 42 ++
.../app/js/services/securityQuestionService.js | 41 ++
.../app/js/services/userSelfService.js | 69 ++++
.../resources/app/views/dynamicAttribute.html | 58 +++
.../app/views/dynamicDerivedAttributes.html | 21 +
.../app/views/dynamicPlainAttributes.html | 22 +
.../app/views/dynamicVirtualAttributes.html | 18 +
.../META-INF/resources/app/views/editUser.html | 73 ++++
.../resources/app/views/generic-error.html | 24 ++
.../META-INF/resources/app/views/home.html | 34 ++
.../resources/app/views/navigationButtons.html | 8 +
.../META-INF/resources/app/views/self.html | 131 ++++++
.../resources/app/views/user-credentials.html | 60 +++
.../app/views/user-derived-schemas.html | 37 ++
.../resources/app/views/user-groups.html | 37 ++
.../resources/app/views/user-plain-schemas.html | 37 ++
.../resources/app/views/user-resources.html | 28 ++
.../app/views/user-virtual-schemas.html | 37 ++
.../main/resources/META-INF/web-fragment.xml | 72 ++++
.../src/main/resources/enduser.properties | 30 ++
.../syncope/client/enduser/pages/HomePage.html | 22 +
.../enduser/SyncopeEnduserApplicationTest.java | 69 ++++
client/pom.xml | 1 +
.../syncope/common/lib/types/Entitlement.java | 10 -
.../syncope/core/logic/AnyTypeClassLogic.java | 4 +-
.../apache/syncope/core/logic/AnyTypeLogic.java | 4 +-
.../apache/syncope/core/logic/SchemaLogic.java | 2 +-
.../core/reference/AuthenticationITCase.java | 11 -
fit/enduser-reference/pom.xml | 413 +++++++++++++++++++
.../src/main/resources/context.xml | 23 ++
.../src/main/resources/enduser.properties | 30 ++
.../src/main/resources/log4j2.xml | 58 +++
.../src/main/webapp/WEB-INF/glassfish-web.xml | 25 ++
.../WEB-INF/jboss-deployment-structure.xml | 37 ++
.../src/main/webapp/WEB-INF/weblogic.xml | 35 ++
fit/pom.xml | 1 +
pom.xml | 89 +++-
79 files changed, 5343 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/pom.xml
----------------------------------------------------------------------
diff --git a/client/enduser/pom.xml b/client/enduser/pom.xml
new file mode 100644
index 0000000..a9dc260
--- /dev/null
+++ b/client/enduser/pom.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope</groupId>
+ <artifactId>syncope-client</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Client Enduser</name>
+ <description>Apache Syncope Client Enduser</description>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-enduser</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-misc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket</artifactId>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-extensions</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-datetime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-auth-roles</artifactId>
+ </dependency>
+
+ <!--AngularJS-->
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>angular</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>angular-route</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>angular-resource</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>angular-ui-router</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>angular-animate</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>angular-cookies</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>angular-growl-2</artifactId>
+ </dependency>
+ <!--Bootstrap-->
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>font-awesome</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>bootstrap-select</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>bootstrap</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>ionicons</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>angular-ui-bootstrap</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>angular-ui-select</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>angular-sanitize</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>select2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars.bower</groupId>
+ <artifactId>FileSaver.js</artifactId>
+ </dependency>
+
+ <!--Jquery-->
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>jquery</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>jquery-cookie</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>jquery-ui</artifactId>
+ </dependency>
+
+ <!--Logging-->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- TEST -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+
+ </build>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
new file mode 100644
index 0000000..4acc756
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser;
+
+import java.io.Serializable;
+import org.apache.syncope.client.enduser.pages.HomePage;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import org.apache.syncope.client.enduser.resources.ErrorResource;
+import org.apache.syncope.client.enduser.resources.LoginResource;
+import org.apache.syncope.client.enduser.resources.LogoutResource;
+import org.apache.syncope.client.enduser.resources.SchemaResource;
+import org.apache.syncope.client.enduser.resources.SecurityQuestionResource;
+import org.apache.syncope.client.enduser.resources.UserSelfCreateResource;
+import org.apache.syncope.client.enduser.resources.UserSelfReadResource;
+import org.apache.syncope.client.enduser.resources.UserSelfUpdateResource;
+import org.apache.wicket.Page;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.request.resource.IResource;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SyncopeEnduserApplication extends WebApplication implements Serializable {
+
+ private static final long serialVersionUID = -6445919351044845120L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncopeEnduserApplication.class);
+
+ public static final List<Locale> SUPPORTED_LOCALES = Collections.unmodifiableList(Arrays.asList(
+ new Locale[] {
+ Locale.ENGLISH, Locale.ITALIAN, new Locale("pt", "BR")
+ }));
+
+ @Override
+ protected void init() {
+ super.init();
+
+ LOG.debug("init SyncopeEnduserApplication");
+
+ // resource to provide login functionality managed by wicket
+ mountResource("/api/login", new ResourceReference("login") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new LoginResource();
+ }
+ });
+
+ // resource to provide logout functionality managed by wicket
+ mountResource("/api/logout", new ResourceReference("logout") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new LogoutResource();
+ }
+ });
+
+ // resource to retrieve info about logged user
+ mountResource("/api/self/read", new ResourceReference("userSelfRead") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new UserSelfReadResource();
+ }
+ });
+
+ // resource to provide user self create functionality managed by wicket
+ mountResource("/api/self/create", new ResourceReference("userSelfCreate") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new UserSelfCreateResource();
+ }
+ });
+
+ // resource to provide user self update functionality managed by wicket
+ mountResource("/api/self/update", new ResourceReference("userSelfUpdate") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new UserSelfUpdateResource();
+ }
+ });
+
+ mountResource("/api/schemas", new ResourceReference("schemas") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new SchemaResource();
+ }
+ });
+
+ mountResource("/api/securityQuestions", new ResourceReference("securityQuestions") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new SecurityQuestionResource();
+ }
+ });
+
+ mountResource("/api/error", new ResourceReference("error") {
+
+ private static final long serialVersionUID = -128426276529456602L;
+
+ @Override
+ public IResource getResource() {
+ return new ErrorResource();
+ }
+ });
+ }
+
+ @Override
+ public Class<? extends Page> getHomePage() {
+ return HomePage.class;
+ }
+
+ @Override
+ public Session newSession(final Request request, final Response response) {
+ return new SyncopeEnduserSession(request);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
new file mode 100644
index 0000000..c5abc1d
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
@@ -0,0 +1,279 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser;
+
+import java.io.File;
+import java.text.DateFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.SyncopeTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebSession;
+import org.apache.wicket.request.Request;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Custom Syncope Enduser Session class.
+ */
+public class SyncopeEnduserSession extends WebSession {
+
+ private static final long serialVersionUID = 1284946129513378647L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncopeEnduserSession.class);
+
+ public static final List<Locale> SUPPORTED_LOCALES = Arrays.asList(new Locale[] {
+ Locale.ENGLISH, Locale.ITALIAN, new Locale("pt", "BR") });
+
+ protected static final String ENDUSER_PROPERTIES = "enduser.properties";
+
+ private String username;
+
+ private String password;
+
+ private String scheme;
+
+ private String host;
+
+ private String port;
+
+ private String rootPath;
+
+ private String anonymousUser;
+
+ private String anonymousKey;
+
+ private Boolean storePassword;
+
+ private String version;
+
+ private String license;
+
+ private final SyncopeClientFactoryBean clientFactory;
+
+ private SyncopeClient client;
+
+ private final SyncopeClient anonymousClient;
+
+ private final SyncopeTO syncopeTO;
+
+ private UserTO selfTO;
+
+ private final Map<Class<?>, Object> services = Collections.synchronizedMap(new HashMap<Class<?>, Object>());
+
+ public static SyncopeEnduserSession get() {
+ return (SyncopeEnduserSession) Session.get();
+ }
+
+ public SyncopeEnduserSession(final Request request) {
+ super(request);
+
+ // load properties from classpath file
+ loadProperties();
+
+ clientFactory = new SyncopeClientFactoryBean();
+ clientFactory.setAddress(new StringBuilder(scheme)
+ .append("://")
+ .append(host)
+ .append(":")
+ .append(port)
+ .append("/")
+ .append(rootPath)
+ .toString());
+ clientFactory.setContentType(SyncopeClientFactoryBean.ContentType.JSON);
+
+ anonymousClient = clientFactory.create(anonymousUser, anonymousKey);
+ syncopeTO = anonymousClient.getService(SyncopeService.class).info();
+
+ }
+
+ public boolean authenticate(final String username, final String password) {
+ boolean authenticated = false;
+
+ try {
+ client = clientFactory.setDomain(SyncopeConstants.MASTER_DOMAIN).create(username, password);
+
+ Pair<Map<String, Set<String>>, UserTO> self = client.self();
+ selfTO = self.getValue();
+
+ this.username = username;
+ this.password = password;
+ // bind explicitly this session to have a stateful behavior during http requests, unless session will expire
+ // for every request
+ this.bind();
+ authenticated = true;
+ } catch (Exception e) {
+ LOG.error("Authentication failed", e);
+ }
+
+ return authenticated;
+ }
+
+ public <T> void resetClient(final Class<T> service) {
+ T serviceInstance = getCachedService(service);
+ WebClient.client(serviceInstance).reset();
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T getCachedService(final Class<T> serviceClass) {
+ T service;
+ if (services.containsKey(serviceClass)) {
+ service = (T) services.get(serviceClass);
+ } else {
+ service = client == null ? anonymousClient.getService(serviceClass) : client.getService(serviceClass);
+ services.put(serviceClass, service);
+ }
+
+ return service;
+ }
+
+ public <T> T getService(final Class<T> serviceClass) {
+ return getCachedService(serviceClass);
+ }
+
+ public <T> T getService(final String etag, final Class<T> serviceClass) {
+ T serviceInstance = getCachedService(serviceClass);
+ WebClient.client(serviceInstance).match(new EntityTag(etag), false).
+ type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
+
+ return serviceInstance;
+ }
+
+ public <T> T getService(final MediaType mediaType, final Class<T> serviceClass) {
+ T service;
+
+ synchronized (clientFactory) {
+ SyncopeClientFactoryBean.ContentType preType = clientFactory.getContentType();
+
+ clientFactory.setContentType(SyncopeClientFactoryBean.ContentType.fromString(mediaType.toString()));
+ service = clientFactory.create(username, password).getService(serviceClass);
+ clientFactory.setContentType(preType);
+ }
+
+ return service;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getScheme() {
+ return scheme;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public String getRootPath() {
+ return rootPath;
+ }
+
+ public String getAnonymousUser() {
+ return anonymousUser;
+ }
+
+ public String getAnonymousKey() {
+ return anonymousKey;
+ }
+
+ public Boolean storePassword() {
+ return this.storePassword;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getLicense() {
+ return license;
+ }
+
+ public SyncopeTO getSyncopeTO() {
+ return syncopeTO;
+ }
+
+ public UserTO getSelfTO() {
+ return selfTO;
+ }
+
+ public boolean isAuthenticated() {
+ return getUsername() != null;
+ }
+
+ public DateFormat getDateFormat() {
+ final Locale locale = getLocale() == null ? Locale.ENGLISH : getLocale();
+
+ return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
+ }
+
+ private void loadProperties() {
+ Properties properties = new Properties();
+
+ try {
+ properties.load(getClass().getResourceAsStream("/" + ENDUSER_PROPERTIES));
+ File enduserDir = new File(properties.getProperty("enduser.directory"));
+ if (enduserDir.exists() && enduserDir.canRead() && enduserDir.isDirectory()) {
+ File enduserDirProps = FileUtils.getFile(enduserDir, ENDUSER_PROPERTIES);
+ if (enduserDirProps.exists() && enduserDirProps.canRead() && enduserDirProps.isFile()) {
+ properties.clear();
+ properties.load(FileUtils.openInputStream(enduserDir));
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Error loading {} file", ENDUSER_PROPERTIES, e);
+// throw new WicketRuntimeException("Could not read " + ENDUSER_PROPERTIES, e);
+ }
+
+ this.scheme = properties.getProperty("scheme");
+ this.host = properties.getProperty("host");
+ this.port = properties.getProperty("port");
+ this.rootPath = properties.getProperty("rootPath");
+ this.anonymousUser = properties.getProperty("anonymousUser");
+ this.anonymousKey = properties.getProperty("anonymousKey");
+ this.storePassword = Boolean.valueOf(properties.getProperty("storePassword"));
+ version = properties.getProperty("version");
+ license = properties.getProperty("license");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
new file mode 100644
index 0000000..551555f
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.adapters;
+
+import org.apache.syncope.client.enduser.model.UserTORequest;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserTOAdapter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UserTOAdapter.class);
+
+ public UserTO fromUserTORequest(final UserTORequest userTORequest, final String oldSelfPassword) {
+
+ // adapter code, to be moved in a new utility class
+ final UserTO userTO = new UserTO();
+ // set key if in update mode
+ final Long key = userTORequest.getKey();
+ if (key != null) {
+ userTO.setKey(key);
+ }
+ // set username...
+ userTO.setUsername(userTORequest.getUsername());
+ // ...and password
+ String requestPassword = userTORequest.getPassword();
+ if (requestPassword == null || requestPassword.isEmpty()) {
+ userTO.setPassword(oldSelfPassword == null ? null : oldSelfPassword);
+ } else {
+ userTO.setPassword(requestPassword);
+ }
+
+ //set security question and answer
+ userTO.setSecurityQuestion(userTORequest.getSecurityQuestion());
+ userTO.setSecurityAnswer(userTORequest.getSecurityAnswer());
+ //set realm
+ userTO.setRealm(userTORequest.getRealm());
+ // add attributes
+ userTO.getPlainAttrs().addAll(userTORequest.getPlainAttrs().values());
+ userTO.getDerAttrs().addAll(userTORequest.getDerAttrs().values());
+ userTO.getVirAttrs().addAll(userTORequest.getVirAttrs().values());
+
+ return userTO;
+ }
+
+ public UserTORequest toUserTORequest(final UserTO userTO) {
+
+ final UserTORequest userTORequest = new UserTORequest().
+ key(userTO.getKey()).
+ username(userTO.getUsername()).
+ securityQuestion(userTO.getSecurityQuestion()).
+ securityAnswer(userTO.getSecurityAnswer()).
+ realm(userTO.getRealm());
+
+ userTORequest.getPlainAttrs().putAll(userTO.getPlainAttrMap());
+ userTORequest.getDerAttrs().putAll(userTO.getDerAttrMap());
+ userTORequest.getVirAttrs().putAll(userTO.getVirAttrMap());
+
+ return userTORequest;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/Credentials.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/Credentials.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/Credentials.java
new file mode 100644
index 0000000..68e3106
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/Credentials.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Credentials {
+
+ private String username;
+
+ private String password;
+
+ public Credentials() {
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(final String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(final String password) {
+ this.password = password;
+ }
+
+ public Credentials username(final String username) {
+ this.username = username;
+ return this;
+ }
+
+ public Credentials password(final String password) {
+ this.password = password;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/SchemaResponse.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/SchemaResponse.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/SchemaResponse.java
new file mode 100644
index 0000000..912f287
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/SchemaResponse.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.to.DerSchemaTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.VirSchemaTO;
+
+public class SchemaResponse implements Serializable {
+
+ private static final long serialVersionUID = -8896862106241712829L;
+
+ private List<PlainSchemaTO> plainSchemas = new ArrayList<>();
+
+ private List<DerSchemaTO> derSchemas = new ArrayList<>();
+
+ private List<VirSchemaTO> virSchemas = new ArrayList<>();
+
+ public SchemaResponse() {
+ }
+
+ public List<PlainSchemaTO> getPlainSchemas() {
+ return plainSchemas;
+ }
+
+ public void setPlainSchemas(final List<PlainSchemaTO> plainSchemas) {
+ this.plainSchemas = plainSchemas;
+ }
+
+ public List<DerSchemaTO> getDerSchemas() {
+ return derSchemas;
+ }
+
+ public void setDerSchemas(final List<DerSchemaTO> derSchemas) {
+ this.derSchemas = derSchemas;
+ }
+
+ public List<VirSchemaTO> getVirSchemas() {
+ return virSchemas;
+ }
+
+ public void setVirSchemas(final List<VirSchemaTO> virSchemas) {
+ this.virSchemas = virSchemas;
+ }
+
+ public SchemaResponse plainSchemas(final List<PlainSchemaTO> value) {
+ this.plainSchemas = value;
+ return this;
+ }
+
+ public SchemaResponse derSchemas(final List<DerSchemaTO> value) {
+ this.derSchemas = value;
+ return this;
+ }
+
+ public SchemaResponse virSchemas(final List<VirSchemaTO> value) {
+ this.virSchemas = value;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
new file mode 100644
index 0000000..09bc219
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.model;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.syncope.common.lib.to.AttrTO;
+
+public class UserTORequest implements Serializable {
+
+ private static final long serialVersionUID = -6763020920564016374L;
+
+ private Long key;
+
+ private String username;
+
+ private String password;
+
+ private Long securityQuestion;
+
+ private String securityAnswer;
+
+ private String realm;
+
+ private Map<String, AttrTO> plainAttrs = new HashMap<>();
+
+ private Map<String, AttrTO> derAttrs = new HashMap<>();
+
+ private Map<String, AttrTO> virAttrs = new HashMap<>();
+
+ public UserTORequest() {
+ }
+
+ public Long getKey() {
+ return key;
+ }
+
+ public void setKey(final Long key) {
+ this.key = key;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(final String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(final String password) {
+ this.password = password;
+ }
+
+ public Long getSecurityQuestion() {
+ return securityQuestion;
+ }
+
+ public void setSecurityQuestion(final Long securityQuestion) {
+ this.securityQuestion = securityQuestion;
+ }
+
+ public String getSecurityAnswer() {
+ return securityAnswer;
+ }
+
+ public void setSecurityAnswer(final String securityAnswer) {
+ this.securityAnswer = securityAnswer;
+ }
+
+ public String getRealm() {
+ return realm;
+ }
+
+ public void setRealm(final String realm) {
+ this.realm = realm;
+ }
+
+ public Map<String, AttrTO> getPlainAttrs() {
+ return plainAttrs;
+ }
+
+ public void setPlainAttrs(final Map<String, AttrTO> plainAttrs) {
+ this.plainAttrs = plainAttrs;
+ }
+
+ public Map<String, AttrTO> getDerAttrs() {
+ return derAttrs;
+ }
+
+ public void setDerAttrs(final Map<String, AttrTO> derAttrs) {
+ this.derAttrs = derAttrs;
+ }
+
+ public Map<String, AttrTO> getVirAttrs() {
+ return virAttrs;
+ }
+
+ public void setVirAttrs(final Map<String, AttrTO> virAttrs) {
+ this.virAttrs = virAttrs;
+ }
+
+ public UserTORequest key(final Long value) {
+ this.key = value;
+ return this;
+ }
+
+ public UserTORequest username(final String value) {
+ this.username = value;
+ return this;
+ }
+
+ public UserTORequest password(final String value) {
+ this.password = value;
+ return this;
+ }
+
+ public UserTORequest securityQuestion(final Long value) {
+ this.securityQuestion = value;
+ return this;
+ }
+
+ public UserTORequest securityAnswer(final String value) {
+ this.securityAnswer = value;
+ return this;
+ }
+
+ public UserTORequest realm(final String value) {
+ this.realm = value;
+ return this;
+ }
+
+ public UserTORequest plainAttrs(final Map<String, AttrTO> value) {
+ this.plainAttrs = value;
+ return this;
+ }
+
+ public UserTORequest derAttrs(final Map<String, AttrTO> value) {
+ this.derAttrs = value;
+ return this;
+ }
+
+ public UserTORequest virAttrs(final Map<String, AttrTO> value) {
+ this.virAttrs = value;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
new file mode 100644
index 0000000..4c5c07e
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.pages;
+
+import org.apache.wicket.NonResettingRestartException;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class HomePage extends WebPage {
+
+ private static final long serialVersionUID = -3422492668689122688L;
+
+ public HomePage(final PageParameters parameters) {
+ super(parameters);
+// throw new RedirectToUrlException("/app/");
+ throw new NonResettingRestartException("/app/");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
new file mode 100644
index 0000000..a3aedfc
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractBaseResource extends AbstractResource {
+
+ private static final long serialVersionUID = -7875801358718612782L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractBaseResource.class);
+
+ protected <T> T getService(final Class<T> serviceClass) {
+ return SyncopeEnduserSession.get().getService(serviceClass);
+ }
+
+ protected <T> T getService(final String etag, final Class<T> serviceClass) {
+ return SyncopeEnduserSession.get().getService(etag, serviceClass);
+ }
+
+ protected <T> void resetClient(final Class<T> serviceClass) {
+ SyncopeEnduserSession.get().resetClient(serviceClass);
+ }
+
+ protected boolean isSelfRegistrationAllowed() {
+ Boolean result = null;
+ try {
+ result = SyncopeEnduserSession.get().getSyncopeTO().isSelfRegAllowed();
+ } catch (SyncopeClientException e) {
+ LOG.error("While seeking if self registration is allowed", e);
+ }
+
+ return result == null
+ ? false
+ : result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/ErrorResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/ErrorResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/ErrorResource.java
new file mode 100644
index 0000000..bfceeab
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/ErrorResource.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import javax.ws.rs.core.MediaType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Mirror REST resource for obtaining user self operations.
+ *
+ * @see org.apache.syncope.common.rest.api
+ */
+public class ErrorResource extends AbstractBaseResource {
+
+ private static final long serialVersionUID = -9184809392631523912L;
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(ErrorResource.class);
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+ ResourceResponse response = new ResourceResponse();
+ response.disableCaching();
+ response.setContentType(MediaType.APPLICATION_JSON);
+
+ response.setStatusCode(403);
+
+ return response;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
new file mode 100644
index 0000000..fa6fa8c
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.model.Credentials;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.util.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LoginResource extends AbstractBaseResource {
+
+ private static final long serialVersionUID = -7720997467070461915L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(LoginResource.class);
+
+ public LoginResource() {
+ }
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+ int responseStatus;
+ final String responseMessage;
+ ResourceResponse response = new ResourceResponse();
+
+ try {
+ HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+ Credentials credentials = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
+ Credentials.class);
+ final String username = credentials.getUsername();
+ final String password = credentials.getPassword().isEmpty() ? null : credentials.getPassword();
+
+ LOG.debug("Enduser login, user: {}", username);
+
+ if (StringUtils.isBlank(username)) {
+ LOG.error("Could not read credentials from request: username is blank!");
+ responseMessage = "Could not read credentials from request: username is blank!";
+ responseStatus = 400;
+ } else {
+ // authenticate user
+ final boolean authenticated = SyncopeEnduserSession.get().authenticate(username, password);
+ responseStatus = authenticated ? 200 : 401;
+ responseMessage = username;
+ }
+
+ response.setWriteCallback(new WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(responseMessage);
+ }
+ });
+
+ } catch (Exception e) {
+ responseStatus = 400;
+ LOG.error("Could not read credentials from request", e);
+ }
+
+ response.setStatusCode(responseStatus);
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
new file mode 100644
index 0000000..545b44d
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LogoutResource extends AbstractBaseResource {
+
+ private static final long serialVersionUID = -648841355644985051L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(LogoutResource.class);
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+ LOG.debug("Enduser logout");
+
+ SyncopeEnduserSession.get().invalidate();
+
+ ResourceResponse response = new ResourceResponse();
+ response.setStatusCode(204);
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
new file mode 100644
index 0000000..544138b
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
@@ -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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.enduser.model.SchemaResponse;
+import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.DerSchemaTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.VirSchemaTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
+import org.apache.syncope.common.rest.api.service.AnyTypeService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SchemaResource extends AbstractBaseResource {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SchemaResource.class);
+
+ private static final long serialVersionUID = 6453101466981543020L;
+
+ private final AnyTypeService anyTypeService;
+
+ private final AnyTypeClassService anyTypeClassService;
+
+ private final SchemaService schemaService;
+
+ public SchemaResource() {
+ anyTypeService = getService(AnyTypeService.class);
+ anyTypeClassService = getService(AnyTypeClassService.class);
+ schemaService = getService(SchemaService.class);
+ }
+
+ @Override
+ protected AbstractResource.ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
+
+ AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
+
+ int responseStatus = 200;
+
+ try {
+
+ final AnyTypeTO anyTypeUserTO = anyTypeService.read(AnyTypeKind.USER.name());
+
+ final List<PlainSchemaTO> plainSchemas = new ArrayList<>();
+ final List<DerSchemaTO> derSchemas = new ArrayList<>();
+ final List<VirSchemaTO> virSchemas = new ArrayList<>();
+
+ // read all USER type schemas
+ for (String clazz : anyTypeUserTO.getClasses()) {
+ plainSchemas.addAll(getSchemaTOs(anyTypeClassService.read(clazz).getPlainSchemas(), SchemaType.PLAIN,
+ PlainSchemaTO.class));
+ derSchemas.addAll(getSchemaTOs(anyTypeClassService.read(clazz).getDerSchemas(), SchemaType.DERIVED,
+ DerSchemaTO.class));
+ virSchemas.addAll(getSchemaTOs(anyTypeClassService.read(clazz).getVirSchemas(), SchemaType.VIRTUAL,
+ VirSchemaTO.class));
+ }
+
+ response.setWriteCallback(new AbstractResource.WriteCallback() {
+
+ @Override
+ public void writeData(final IResource.Attributes attributes) throws IOException {
+ attributes.getResponse().write(POJOHelper.serialize(new SchemaResponse().
+ plainSchemas(plainSchemas).
+ derSchemas(derSchemas).
+ virSchemas(virSchemas)));
+ }
+ });
+
+ } catch (Exception e) {
+ LOG.error("Error retrieving " + AnyTypeKind.USER.name() + " class schemas", e);
+ responseStatus = 400;
+ }
+
+ response.setStatusCode(responseStatus);
+ return response;
+ }
+
+ private <T extends AbstractSchemaTO> List<T> getSchemaTOs(final List<String> schemaNames,
+ final SchemaType schemaType, final Class<T> type) {
+
+ List<T> schemaTOs = new ArrayList<>();
+
+ for (String schemaName : schemaNames) {
+ schemaTOs.add(type.cast(schemaService.read(schemaType, schemaName)));
+ }
+
+ return schemaTOs;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
new file mode 100644
index 0000000..f1ab6c8
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SecurityQuestionResource extends AbstractBaseResource {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SecurityQuestionResource.class);
+
+ private static final long serialVersionUID = 6453101466981543020L;
+
+ private final SecurityQuestionService securityQuestionService;
+
+ public SecurityQuestionResource() {
+ securityQuestionService = getService(SecurityQuestionService.class);
+ }
+
+ @Override
+ protected AbstractResource.ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
+
+ AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
+
+ int responseStatus = 200;
+
+ try {
+
+ LOG.debug("List available security questions");
+
+ final List<SecurityQuestionTO> securityQuestionTOs = securityQuestionService.list();
+
+ response.setWriteCallback(new AbstractResource.WriteCallback() {
+
+ @Override
+ public void writeData(final IResource.Attributes attributes) throws IOException {
+ attributes.getResponse().write(POJOHelper.serialize(securityQuestionTOs));
+ }
+ });
+
+ } catch (Exception e) {
+ LOG.error("Error retrieving security questions", e);
+ responseStatus = 400;
+ }
+
+ response.setStatusCode(responseStatus);
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
new file mode 100644
index 0000000..61734a7
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.adapters.UserTOAdapter;
+import org.apache.syncope.client.enduser.model.UserTORequest;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.util.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserSelfCreateResource extends AbstractBaseResource {
+
+ private static final long serialVersionUID = -2721621682300247583L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(UserSelfCreateResource.class);
+
+ private final UserSelfService userSelfService;
+
+ private final UserTOAdapter userTOAdapter;
+
+ public UserSelfCreateResource() {
+ userTOAdapter = new UserTOAdapter();
+ userSelfService = getService(UserSelfService.class);
+ }
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+ int responseStatus = 200;
+ final StringBuilder responseMessage = new StringBuilder();
+ ResourceResponse response = new ResourceResponse();
+
+ try {
+ HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+
+ final UserTORequest userTORequest = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
+ UserTORequest.class);
+
+ if (isSelfRegistrationAllowed() && userTORequest != null) {
+ LOG.debug("Received user self registration request for user: [{}]", userTORequest.getUsername());
+ LOG.trace("Received user self registration request is: [{}]", userTORequest);
+ // adapt request and create user
+ userSelfService.create(userTOAdapter.fromUserTORequest(userTORequest, null),
+ SyncopeEnduserSession.get().storePassword());
+ responseMessage.append("User").append(userTORequest.getUsername()).append("created successfully");
+ } else {
+ responseMessage.append(userTORequest == null
+ ? "Request received is not valid"
+ : "Self registration not allowed");
+ responseStatus = 403;
+ }
+ response.setWriteCallback(new WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(responseMessage);
+ }
+ });
+
+ } catch (final Exception e) {
+ responseStatus = 400;
+ response.setWriteCallback(new WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(e.getMessage());
+ }
+ });
+ LOG.error("Could not read userTO from request", e);
+ }
+
+ response.setStatusCode(responseStatus);
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
new file mode 100644
index 0000000..3519e78
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
@@ -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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.adapters.UserTOAdapter;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Mirror REST resource for obtaining user self operations.
+ *
+ * @see org.apache.syncope.common.rest.api
+ */
+public class UserSelfReadResource extends AbstractResource {
+
+ private static final long serialVersionUID = -9184809392631523912L;
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(UserSelfReadResource.class);
+
+ private final UserTOAdapter userTOAdapter;
+
+ public UserSelfReadResource() {
+ userTOAdapter = new UserTOAdapter();
+ }
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+ ResourceResponse response = new ResourceResponse();
+ final String selfTOJson = POJOHelper.serialize(userTOAdapter.toUserTORequest(SyncopeEnduserSession.get().
+ getSelfTO()));
+
+ response.setWriteCallback(new WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(selfTOJson);
+ }
+ });
+
+ return response;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
new file mode 100644
index 0000000..5fc9c82
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.adapters.UserTOAdapter;
+import org.apache.syncope.client.enduser.model.UserTORequest;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.util.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserSelfUpdateResource extends AbstractBaseResource {
+
+ private static final long serialVersionUID = -2721621682300247583L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(UserSelfUpdateResource.class);
+
+ private final UserSelfService userSelfService;
+
+ private final UserTOAdapter userTOAdapter;
+
+ public UserSelfUpdateResource() {
+ userTOAdapter = new UserTOAdapter();
+ userSelfService = getService(UserSelfService.class);
+ }
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+ int responseStatus = 200;
+ final String responseMessage;
+ ResourceResponse response = new ResourceResponse();
+
+ try {
+ HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+
+ final UserTORequest userTOResponse = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
+ UserTORequest.class);
+
+ LOG.debug("userTOResponse: {}", userTOResponse);
+
+ // adapt user, change self password only value passed is not null and has changed
+ UserTO userTO = userTOAdapter.fromUserTORequest(userTOResponse, SyncopeEnduserSession.get().getPassword());
+
+ LOG.debug("Enduser user self update, user: {}", userTO.toString());
+
+ // update user
+ userSelfService.update(userTO);
+ responseMessage = "User updated successfully";
+
+ response.setWriteCallback(new WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(responseMessage);
+ }
+ });
+
+ } catch (final Exception e) {
+ responseStatus = 400;
+ response.setWriteCallback(new WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(e.getMessage());
+ }
+ });
+ LOG.error("Could not read userTO from request", e);
+ }
+
+ response.setStatusCode(responseStatus);
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/app.css b/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
new file mode 100644
index 0000000..e5ae8e5
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
@@ -0,0 +1,28 @@
+/*
+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.
+*/
+
+/* app general css stylesheet */
+
+.growl-container > .growl-item.ng-enter,
+.growl-container > .growl-item.ng-leave {
+ -webkit-transition:1s linear all;
+ -moz-transition:1s linear all;
+ -o-transition:1s linear all;
+ transition:1s linear all;
+}
\ 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/css/editUser.css
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css b/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
new file mode 100644
index 0000000..ee13bd0
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
@@ -0,0 +1,253 @@
+/*
+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.
+*/
+
+#form-container {
+ position: relative;
+ width: 100%;
+ margin: 0 auto;
+ text-align: center;
+}
+
+#form-container .page-header { background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */
+ margin: 1% 16%;
+ width: 72%; padding:10px;
+ /* shadows and rounded borders */
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+ -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+ box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
+}
+#form-container .breadcrumb-header {
+ margin: 1% 16%;
+ width: 72%; padding:10px;
+}
+
+.signup-form {
+ text-align: left;
+ padding: 2%;
+}
+
+#attribute {
+ padding: 0 255px;
+}
+
+#attribute-derived,
+#attribute-virtual {
+ padding: 0 155px;
+}
+
+.attribute-virtual-value-container {
+ margin-top: 2%;
+ list-style: none;
+ padding-right: 5%;
+}
+
+.attribute-virtual-value-field {
+ font-weight: 700;
+ padding: 6px 12px;
+ margin-bottom: 2%;
+}
+
+.minus{
+ margin-bottom: 2%;
+}
+
+.fileButton{
+ margin-top: 2%;
+}
+
+.upper-select {
+ padding-right: 71%;
+ padding-left: 18%;
+}
+
+.attribute-ui-select {
+ width: 100%;
+ padding-right: 7%;
+ padding-left: 7%;
+}
+
+#previous {
+ background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */
+ float: left;
+ color: black;
+ width: 30%;
+}
+#previous:hover {
+ background: #658D5D;
+}
+
+#next{
+ background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */
+ margin-top: 5px;
+ float: right;
+ color: black;
+ width: 30%;
+}
+#next:hover {
+ background: #658D5D;
+}
+
+#save{
+ background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */
+ color: black;
+ margin-top: 5%;
+ width: 15%;
+}
+#save:hover {
+ background: #658D5D;
+}
+#cancel {
+ margin-top: 5%;
+ width: 15%;
+}
+
+#form-views { width:auto; }
+
+/* basic styling for entering and leaving */
+/* left and right to add to ensure full width: position:absolute; left:30px; right:30px; */
+#form-views.ng-enter,
+#form-views.ng-leave {
+ transition:0.5s all ease; -moz-transition:0.5s all ease; -webkit-transition:0.5s all ease;
+}
+
+/* enter animation */
+#form-views.ng-enter {
+ -webkit-animation:slideInRight 0.5s both ease;
+ -moz-animation:slideInRight 0.5s both ease;
+ animation:slideInRight 0.5s both ease;
+}
+
+/* leave animation */
+#form-views.ng-leave {
+ -webkit-animation:slideOutLeft 0.5s both ease;
+ -moz-animation:slideOutLeft 0.5s both ease;
+ animation:slideOutLeft 0.5s both ease;
+}
+
+/** Button breadcrumb **/
+.btn-breadcrumb .btn:not(:last-child):after {
+ content: " ";
+ display: block;
+ width: 0;
+ height: 0;
+ border-top: 17px solid transparent;
+ border-bottom: 17px solid transparent;
+ border-left: 10px solid white;
+ position: absolute;
+ top: 50%;
+ margin-top: -17px;
+ left: 100%;
+ z-index: 3;
+}
+.btn-breadcrumb .btn:not(:last-child):before {
+ content: " ";
+ display: block;
+ width: 0;
+ height: 0;
+ border-top: 17px solid transparent;
+ border-bottom: 17px solid transparent;
+ border-left: 10px solid rgb(173, 173, 173);
+ position: absolute;
+ top: 50%;
+ margin-top: -17px;
+ margin-left: 1px;
+ left: 100%;
+ z-index: 3;
+}
+
+/** The Spacing **/
+.btn-breadcrumb .btn {
+ padding:6px 12px 6px 24px;
+}
+.btn-breadcrumb .btn:first-child {
+ padding:6px 6px 6px 10px;
+}
+.btn-breadcrumb .btn:last-child {
+ padding:6px 18px 6px 24px;
+}
+
+/** Default button **/
+.btn-breadcrumb .btn.btn-default:not(:last-child):after {
+ border-left: 10px solid #fff;
+}
+.btn-breadcrumb .btn.btn-default:not(:last-child):before {
+ border-left: 10px solid #ccc;
+}
+.btn-breadcrumb .btn.btn-default:hover:not(:last-child):after {
+ border-left: 10px solid #ebebeb;
+}
+.btn-breadcrumb .btn.btn-default:hover:not(:last-child):before {
+ border-left: 10px solid #adadad;
+}
+
+.breadcrumb-disabled-link {
+ pointer-events: none;
+ cursor: default;
+}
+
+.text-validation-error{
+ color: #dd301b;
+ font-weight: 600;
+}
+/* ANIMATIONS
+============================================================================= */
+/* slide out to the left */
+@keyframes slideOutLeft {
+ to { transform: translateX(-200%); }
+}
+@-moz-keyframes slideOutLeft {
+ to { -moz-transform: translateX(-200%); }
+}
+@-webkit-keyframes slideOutLeft {
+ to { -webkit-transform: translateX(-200%); }
+}
+
+/* slide in from the right */
+@keyframes slideInRight {
+ from { transform:translateX(200%); }
+ to { transform: translateX(0); }
+}
+@-moz-keyframes slideInRight {
+ from { -moz-transform:translateX(200%); }
+ to { -moz-transform: translateX(0); }
+}
+@-webkit-keyframes slideInRight {
+ from { -webkit-transform:translateX(200%); }
+ to { -webkit-transform: translateX(0); }
+}
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/223a64e2/client/enduser/src/main/resources/META-INF/resources/app/css/login.css
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/login.css b/client/enduser/src/main/resources/META-INF/resources/app/css/login.css
new file mode 100644
index 0000000..fdc9e3e
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/css/login.css
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+body, html {
+ margin: 45px 0;
+ height: 100%;
+ background-repeat: no-repeat;
+ /*background-image: linear-gradient(rgb(104, 145, 162), #00a65a);*/
+ background-color: #EEEEEE;
+}
+#login-container {
+ position: relative;
+ width: 100%;
+ margin: 0 auto;
+ text-align: center;
+ background-color: #FFF;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.65);
+ box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.65);
+}
+#login-container .row > div {
+ margin-bottom: 1em;
+}
+#login-container .row > div:last-child {
+ margin-bottom: 0;
+}
+#login-container #logo {
+ position: relative;
+ float: left;
+ margin-left: 15%;
+ border-top-right-radius: 100px;
+ border-top-left-radius: 100px;
+ border-bottom-right-radius: 100px;
+ border-bottom-left-radius: 100px;
+}
+
+#login-container #language{
+ padding: 0px;
+ height: 40px;
+}
+
+#login-container #signup-btn {
+ padding-top: 15px;
+ padding-bottom: 15px;
+}
+#login-container #signup-btn:hover {
+ background-color: #1d1d1d;
+ border-color: #181818;
+}
+
+.login-btn {
+ background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */
+ margin-top: 5px;
+ color: black;
+}
+.login-btn:hover {
+ background: #658D5D;
+}
+
+#login {
+ position: relative;
+ padding: 25px 25px 50px 25px;
+ margin-bottom: 1em;
+}
+#login #login-form {
+ margin-top: 2em;
+ margin-bottom: 2em;
+ text-align: left;
+}
+#login-form{
+ padding: 0 195px;
+ margin: 7%;
+}
+#languageContainer {
+ padding: 0 25px;
+}
+
+.logout{
+ float: right;
+}
\ No newline at end of file