Merge remote-tracking branch 'keycloak/master' into french-i18n
This commit is contained in:
commit
fe9b5a6588
33 changed files with 120 additions and 622 deletions
16
dependencies/server-all/pom.xml
vendored
16
dependencies/server-all/pom.xml
vendored
|
@ -141,22 +141,6 @@
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
<artifactId>mongo-java-driver</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- export/import -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-export-import-zip</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>de.idyl</groupId>
|
|
||||||
<artifactId>winzipaes</artifactId>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcprov-jdk16</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.liquibase</groupId>
|
<groupId>org.liquibase</groupId>
|
||||||
<artifactId>liquibase-core</artifactId>
|
<artifactId>liquibase-core</artifactId>
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.3" name="de.idyl.winzipaes">
|
|
||||||
<resources>
|
|
||||||
<artifact name="${de.idyl:winzipaes}"/>
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="javax.api"/>
|
|
||||||
<module name="org.bouncycastle"/>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</module>
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-export-import-zip">
|
|
||||||
<resources>
|
|
||||||
<artifact name="${org.keycloak:keycloak-export-import-zip}"/>
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="org.keycloak.keycloak-common"/>
|
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
|
||||||
<module name="org.keycloak.keycloak-model-api"/>
|
|
||||||
<module name="org.keycloak.keycloak-invalidation-cache-model"/>
|
|
||||||
<module name="org.keycloak.keycloak-export-import-api"/>
|
|
||||||
<module name="javax.ws.rs.api"/>
|
|
||||||
<module name="org.codehaus.jackson.jackson-core-asl"/>
|
|
||||||
<module name="org.codehaus.jackson.jackson-mapper-asl"/>
|
|
||||||
<module name="org.codehaus.jackson.jackson-xc"/>
|
|
||||||
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
|
|
||||||
<module name="org.jboss.logging"/>
|
|
||||||
<module name="org.bouncycastle" />
|
|
||||||
<module name="de.idyl.winzipaes"/>
|
|
||||||
<module name="javax.api"/>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</module>
|
|
|
@ -21,7 +21,6 @@
|
||||||
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-zip" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-zip" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
||||||
|
|
|
@ -278,15 +278,6 @@
|
||||||
<maven-resource group="org.mongodb" artifact="mongo-java-driver"/>
|
<maven-resource group="org.mongodb" artifact="mongo-java-driver"/>
|
||||||
</module-def>
|
</module-def>
|
||||||
|
|
||||||
<!-- export/import -->
|
|
||||||
|
|
||||||
<module-def name="org.keycloak.keycloak-export-import-zip">
|
|
||||||
<maven-resource group="org.keycloak" artifact="keycloak-export-import-zip"/>
|
|
||||||
</module-def>
|
|
||||||
<module-def name="de.idyl.winzipaes">
|
|
||||||
<maven-resource group="de.idyl" artifact="winzipaes"/>
|
|
||||||
</module-def>
|
|
||||||
|
|
||||||
<module-def name="org.liquibase">
|
<module-def name="org.liquibase">
|
||||||
<maven-resource group="org.liquibase" artifact="liquibase-core"/>
|
<maven-resource group="org.liquibase" artifact="liquibase-core"/>
|
||||||
</module-def>
|
</module-def>
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.1" name="de.idyl.winzipaes">
|
|
||||||
<resources>
|
|
||||||
<!-- Insert resources here -->
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="javax.api"/>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</module>
|
|
|
@ -21,7 +21,6 @@
|
||||||
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-zip" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-export-import-zip">
|
|
||||||
<resources>
|
|
||||||
<!-- Insert resources here -->
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="org.keycloak.keycloak-common"/>
|
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
|
||||||
<module name="org.keycloak.keycloak-model-api"/>
|
|
||||||
<module name="org.keycloak.keycloak-invalidation-cache-model"/>
|
|
||||||
<module name="org.keycloak.keycloak-export-import-api"/>
|
|
||||||
<module name="javax.ws.rs.api"/>
|
|
||||||
<module name="org.codehaus.jackson.jackson-core-asl"/>
|
|
||||||
<module name="org.codehaus.jackson.jackson-mapper-asl"/>
|
|
||||||
<module name="org.codehaus.jackson.jackson-xc"/>
|
|
||||||
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
|
|
||||||
<module name="org.jboss.logging"/>
|
|
||||||
<module name="org.bouncycastle" />
|
|
||||||
<module name="de.idyl.winzipaes"/>
|
|
||||||
<module name="javax.api"/>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</module>
|
|
|
@ -31,7 +31,6 @@
|
||||||
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-api" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-dir" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
<module name="org.keycloak.keycloak-export-import-single-file" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-export-import-zip" services="import"/>
|
|
||||||
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-freemarker" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
<module name="org.keycloak.keycloak-forms-common-themes" services="import"/>
|
||||||
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<outputDirectory>modules/system/layers/base</outputDirectory>
|
<outputDirectory>modules/system/layers/base</outputDirectory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>com/google/zxing/**</include>
|
<include>com/google/zxing/**</include>
|
||||||
<include>de/idyl/winzipaes/**</include>
|
|
||||||
<include>org/freemarker/**</include>
|
<include>org/freemarker/**</include>
|
||||||
<include>org/keycloak/**</include>
|
<include>org/keycloak/**</include>
|
||||||
<include>org/liquibase/**</include>
|
<include>org/liquibase/**</include>
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
<para>
|
<para>
|
||||||
You can export/import your database either to:
|
You can export/import your database either to:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>Encrypted ZIP file on local filesystem</listitem>
|
|
||||||
<listitem>Directory on local filesystem</listitem>
|
<listitem>Directory on local filesystem</listitem>
|
||||||
<listitem>Single JSON file on your filesystem</listitem>
|
<listitem>Single JSON file on your filesystem</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
When importing using the "dir" or "zip" strategies, note that the files need to follow the naming convention specified below.
|
When importing using the "dir" strategy, note that the files need to follow the naming convention specified below.
|
||||||
If you are importing files which were previously exported, the files already follow this convention.
|
If you are importing files which were previously exported, the files already follow this convention.
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>{REALM_NAME}-realm.json, such as "acme-roadrunner-affairs-realm.json" for the realm named "acme-roadrunner-affairs"</listitem>
|
<listitem>{REALM_NAME}-realm.json, such as "acme-roadrunner-affairs-realm.json" for the realm named "acme-roadrunner-affairs"</listitem>
|
||||||
|
@ -21,26 +20,10 @@
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Encrypted ZIP is recommended as export contains many sensitive informations like passwords of your users (even if they are hashed),
|
If you import to Directory, you can specify also the number of users to be stored in each JSON file. So if you have
|
||||||
but also their email addresses, and especially private keys of the realms. Directory and Single JSON file are useful especially
|
|
||||||
for testing as data in the files are not protected. On the other hand, it's useful if you want to look at all your data in JSON
|
|
||||||
files directly.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you import to ZIP or Directory, you can specify also the number of users to be stored in each JSON file. So if you have
|
|
||||||
very large amount of users in your database, you likely don't want to import them into single file as the file might be very big.
|
very large amount of users in your database, you likely don't want to import them into single file as the file might be very big.
|
||||||
Processing of each file is done in separate transaction as exporting/importing all users at once could also lead to memory issues.
|
Processing of each file is done in separate transaction as exporting/importing all users at once could also lead to memory issues.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
So to export the content of your Keycloak database into encrypted ZIP, you can execute Keycloak server with the System properties like:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
bin/standalone.sh -Dkeycloak.migration.action=export
|
|
||||||
-Dkeycloak.migration.provider=zip -Dkeycloak.migration.zipFile=<FILE TO EXPORT TO>
|
|
||||||
-Dkeycloak.migration.zipPassword=<PASSWORD TO DECRYPT EXPORT>
|
|
||||||
]]></programlisting>
|
|
||||||
Then you can move or copy the encrypted ZIP file into second environment and you can trigger import from it into Keycloak server with the same command but use
|
|
||||||
<literal>-Dkeycloak.migration.action=import</literal> instead of <literal>export</literal> .
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
To export into unencrypted directory you can use:
|
To export into unencrypted directory you can use:
|
||||||
<programlisting><![CDATA[
|
<programlisting><![CDATA[
|
||||||
|
@ -80,7 +63,7 @@ bin/standalone.sh -Dkeycloak.migration.action=import
|
||||||
<term>-Dkeycloak.migration.usersExportStrategy</term>
|
<term>-Dkeycloak.migration.usersExportStrategy</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
can be used to specify for ZIP or Directory providers to specify where to import users.
|
can be used to specify for Directory providers to specify where to import users.
|
||||||
Possible values are:
|
Possible values are:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>DIFFERENT_FILES - Users will be exported into more different files according to maximum number of users per file. This is default value</listitem>
|
<listitem>DIFFERENT_FILES - Users will be exported into more different files according to maximum number of users per file. This is default value</listitem>
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<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/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>keycloak-export-import-parent</artifactId>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<version>1.6.0.Final-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-export-import-zip</artifactId>
|
|
||||||
<name>Keycloak Export Import To Encrypted ZIP</name>
|
|
||||||
<description/>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-core</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-export-import-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
|
||||||
<artifactId>jackson-core-asl</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
|
||||||
<artifactId>jackson-mapper-asl</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>jboss-logging</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>de.idyl</groupId>
|
|
||||||
<artifactId>winzipaes</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<source>${maven.compiler.source}</source>
|
|
||||||
<target>${maven.compiler.target}</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,82 +0,0 @@
|
||||||
package org.keycloak.exportimport.zip;
|
|
||||||
|
|
||||||
import de.idyl.winzipaes.AesZipFileEncrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESEncrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESEncrypterBC;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.representations.VersionRepresentation;
|
|
||||||
import org.keycloak.exportimport.util.ExportUtils;
|
|
||||||
import org.keycloak.exportimport.util.MultipleStepsExportProvider;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ZipExportProvider extends MultipleStepsExportProvider {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ZipExportProvider.class);
|
|
||||||
|
|
||||||
private final AesZipFileEncrypter encrypter;
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
public ZipExportProvider(File zipFile, String password) {
|
|
||||||
if (zipFile.exists()) {
|
|
||||||
throw new IllegalStateException("File " + zipFile.getAbsolutePath() + " already exists");
|
|
||||||
}
|
|
||||||
this.password = password;
|
|
||||||
|
|
||||||
try {
|
|
||||||
AESEncrypter encrypter = new AESEncrypterBC();
|
|
||||||
this.encrypter = new AesZipFileEncrypter(zipFile, encrypter);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
logger.infof("Exporting into zip file %s", zipFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeRealm(String fileName, RealmRepresentation rep) throws IOException {
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
JsonSerialization.mapper.writeValue(stream, rep);
|
|
||||||
writeStream(fileName, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeUsers(String fileName, KeycloakSession session, RealmModel realm, List<UserModel> users) throws IOException {
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
ExportUtils.exportUsersToStream(session, realm, users, JsonSerialization.mapper, stream);
|
|
||||||
writeStream(fileName, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeVersion(String fileName, VersionRepresentation version) throws IOException {
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
JsonSerialization.mapper.writeValue(stream, version);
|
|
||||||
writeStream(fileName, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeStream(String fileName, ByteArrayOutputStream stream) throws IOException {
|
|
||||||
byte[] byteArray = stream.toByteArray();
|
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
|
|
||||||
this.encrypter.add(fileName, bis, this.password);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
this.encrypter.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
package org.keycloak.exportimport.zip;
|
|
||||||
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.exportimport.ExportImportConfig;
|
|
||||||
import org.keycloak.exportimport.ExportProvider;
|
|
||||||
import org.keycloak.exportimport.ExportProviderFactory;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ZipExportProviderFactory implements ExportProviderFactory {
|
|
||||||
|
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "zip";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ExportProvider create(KeycloakSession session) {
|
|
||||||
String fileName = ExportImportConfig.getZipFile();
|
|
||||||
String password = ExportImportConfig.getZipPassword();
|
|
||||||
if (fileName == null) {
|
|
||||||
throw new IllegalArgumentException("ZIP file for export not provided");
|
|
||||||
}
|
|
||||||
if (password == null) {
|
|
||||||
throw new IllegalArgumentException("Password for encrypting ZIP not provided");
|
|
||||||
}
|
|
||||||
return new ZipExportProvider(new File(fileName), password);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Config.Scope config) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return PROVIDER_ID;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
package org.keycloak.exportimport.zip;
|
|
||||||
|
|
||||||
import de.idyl.winzipaes.AesZipFileDecrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESDecrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESDecrypterBC;
|
|
||||||
import de.idyl.winzipaes.impl.ExtZipEntry;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.exportimport.ImportProvider;
|
|
||||||
import org.keycloak.exportimport.Strategy;
|
|
||||||
import org.keycloak.exportimport.util.ExportImportSessionTask;
|
|
||||||
import org.keycloak.exportimport.util.ImportUtils;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.zip.DataFormatException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ZipImportProvider implements ImportProvider {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ZipImportProvider.class);
|
|
||||||
|
|
||||||
private final AesZipFileDecrypter decrypter;
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
public ZipImportProvider(File zipFile, String password) {
|
|
||||||
try {
|
|
||||||
if (!zipFile.exists()) {
|
|
||||||
throw new IllegalStateException("File " + zipFile.getAbsolutePath() + " doesn't exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
AESDecrypter decrypter = new AESDecrypterBC();
|
|
||||||
this.decrypter = new AesZipFileDecrypter(zipFile, decrypter);
|
|
||||||
this.password = password;
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
logger.infof("Importing from ZIP file %s", zipFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void importModel(KeycloakSessionFactory factory, Strategy strategy) throws IOException {
|
|
||||||
List<String> realmNames = getRealmsToImport();
|
|
||||||
|
|
||||||
for (String realmName : realmNames) {
|
|
||||||
importRealm(factory, realmName, strategy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMasterRealmExported() throws IOException {
|
|
||||||
List<String> realmNames = getRealmsToImport();
|
|
||||||
return realmNames.contains(Config.getAdminRealm());
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getRealmsToImport() throws IOException {
|
|
||||||
List<String> realmNames = new ArrayList<String>();
|
|
||||||
for (ExtZipEntry entry : this.decrypter.getEntryList()) {
|
|
||||||
String entryName = entry.getName();
|
|
||||||
if (entryName.endsWith("-realm.json")) {
|
|
||||||
// Parse "foo" from "foo-realm.json"
|
|
||||||
String realmName = entryName.substring(0, entryName.length() - 11);
|
|
||||||
|
|
||||||
// Ensure that master realm is imported first
|
|
||||||
if (Config.getAdminRealm().equals(realmName)) {
|
|
||||||
realmNames.add(0, realmName);
|
|
||||||
} else {
|
|
||||||
realmNames.add(realmName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return realmNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void importRealm(KeycloakSessionFactory factory, final String realmName, final Strategy strategy) throws IOException {
|
|
||||||
try {
|
|
||||||
// Import realm first
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
this.decrypter.extractEntry(this.decrypter.getEntry(realmName + "-realm.json"), bos, this.password);
|
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
|
|
||||||
final RealmRepresentation realmRep = JsonSerialization.mapper.readValue(bis, RealmRepresentation.class);
|
|
||||||
|
|
||||||
KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void runExportImportTask(KeycloakSession session) throws IOException {
|
|
||||||
ImportUtils.importRealm(session, realmRep, strategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Import users
|
|
||||||
for (ExtZipEntry entry : this.decrypter.getEntryList()) {
|
|
||||||
String name = entry.getName();
|
|
||||||
if (name.matches(realmName + "-users-[0-9]+\\.json")) {
|
|
||||||
bos = new ByteArrayOutputStream();
|
|
||||||
this.decrypter.extractEntry(entry, bos, this.password);
|
|
||||||
final ByteArrayInputStream bis2 = new ByteArrayInputStream(bos.toByteArray());
|
|
||||||
|
|
||||||
KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void runExportImportTask(KeycloakSession session) throws IOException {
|
|
||||||
ImportUtils.importUsersFromStream(session, realmName, JsonSerialization.mapper, bis2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DataFormatException dfe) {
|
|
||||||
throw new RuntimeException(dfe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
this.decrypter.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package org.keycloak.exportimport.zip;
|
|
||||||
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.exportimport.ExportImportConfig;
|
|
||||||
import org.keycloak.exportimport.ImportProvider;
|
|
||||||
import org.keycloak.exportimport.ImportProviderFactory;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ZipImportProviderFactory implements ImportProviderFactory {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImportProvider create(KeycloakSession session) {
|
|
||||||
String fileName = ExportImportConfig.getZipFile();
|
|
||||||
String password = ExportImportConfig.getZipPassword();
|
|
||||||
if (fileName == null) {
|
|
||||||
throw new IllegalArgumentException("ZIP file for import not provided");
|
|
||||||
}
|
|
||||||
if (password == null) {
|
|
||||||
throw new IllegalArgumentException("Password for decrypting ZIP not provided");
|
|
||||||
}
|
|
||||||
return new ZipImportProvider(new File(fileName), password);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Config.Scope config) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return ZipExportProviderFactory.PROVIDER_ID;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
org.keycloak.exportimport.zip.ZipExportProviderFactory
|
|
|
@ -1 +0,0 @@
|
||||||
org.keycloak.exportimport.zip.ZipImportProviderFactory
|
|
|
@ -18,7 +18,6 @@
|
||||||
<module>export-import-api</module>
|
<module>export-import-api</module>
|
||||||
<module>export-import-dir</module>
|
<module>export-import-dir</module>
|
||||||
<module>export-import-single-file</module>
|
<module>export-import-single-file</module>
|
||||||
<module>export-import-zip</module>
|
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label" for="alias">Alias </label>
|
<label class="col-md-2 control-label" for="alias">Alias </label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<input class="form-control" type="text" id="alias" name="alias" data-ng-model="flow.alias" autofocus>
|
<input class="form-control" type="text" id="alias" name="alias" data-ng-model="flow.alias" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
<kc-tooltip>Specifies display name for the flow.</kc-tooltip>
|
<kc-tooltip>Specifies display name for the flow.</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -90,14 +90,7 @@ public class Pbkdf2PasswordEncoder {
|
||||||
public static byte[] getSalt() {
|
public static byte[] getSalt() {
|
||||||
byte[] buffer = new byte[16];
|
byte[] buffer = new byte[16];
|
||||||
|
|
||||||
SecureRandom secureRandom;
|
SecureRandom secureRandom = new SecureRandom();
|
||||||
|
|
||||||
try {
|
|
||||||
secureRandom = SecureRandom.getInstance(RNG_ALGORITHM);
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException("RNG algorithm not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
secureRandom.nextBytes(buffer);
|
secureRandom.nextBytes(buffer);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
13
pom.xml
13
pom.xml
|
@ -58,7 +58,6 @@
|
||||||
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
||||||
<google.zxing.version>3.2.1</google.zxing.version>
|
<google.zxing.version>3.2.1</google.zxing.version>
|
||||||
<github.relaxng.version>2011.1</github.relaxng.version>
|
<github.relaxng.version>2011.1</github.relaxng.version>
|
||||||
<winzipaes.version>1.0.1</winzipaes.version>
|
|
||||||
<freemarker.version>2.3.23</freemarker.version>
|
<freemarker.version>2.3.23</freemarker.version>
|
||||||
<twitter4j.version>4.0.4</twitter4j.version>
|
<twitter4j.version>4.0.4</twitter4j.version>
|
||||||
<selenium.version>2.35.0</selenium.version>
|
<selenium.version>2.35.0</selenium.version>
|
||||||
|
@ -373,13 +372,6 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Encrypted ZIP -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>de.idyl</groupId>
|
|
||||||
<artifactId>winzipaes</artifactId>
|
|
||||||
<version>${winzipaes.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Apache DS -->
|
<!-- Apache DS -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.directory.server</groupId>
|
<groupId>org.apache.directory.server</groupId>
|
||||||
|
@ -700,11 +692,6 @@
|
||||||
<artifactId>keycloak-export-import-single-file</artifactId>
|
<artifactId>keycloak-export-import-single-file</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-export-import-zip</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-kerberos-federation</artifactId>
|
<artifactId>keycloak-kerberos-federation</artifactId>
|
||||||
|
|
|
@ -18,10 +18,7 @@ import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -116,6 +113,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
||||||
|
|
||||||
private class ValidationContextImpl extends FormContextImpl implements ValidationContext {
|
private class ValidationContextImpl extends FormContextImpl implements ValidationContext {
|
||||||
FormAction action;
|
FormAction action;
|
||||||
|
String error;
|
||||||
|
|
||||||
private ValidationContextImpl(AuthenticationExecutionModel executionModel, FormAction action) {
|
private ValidationContextImpl(AuthenticationExecutionModel executionModel, FormAction action) {
|
||||||
super(executionModel);
|
super(executionModel);
|
||||||
|
@ -131,6 +129,10 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
||||||
this.formData = formData;
|
this.formData = formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void error(String error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void success() {
|
public void success() {
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -145,6 +147,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
||||||
Map<String, ClientSessionModel.ExecutionStatus> executionStatus = new HashMap<>();
|
Map<String, ClientSessionModel.ExecutionStatus> executionStatus = new HashMap<>();
|
||||||
List<FormAction> requiredActions = new LinkedList<>();
|
List<FormAction> requiredActions = new LinkedList<>();
|
||||||
List<ValidationContextImpl> successes = new LinkedList<>();
|
List<ValidationContextImpl> successes = new LinkedList<>();
|
||||||
|
List<ValidationContextImpl> errors = new LinkedList<>();
|
||||||
for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
|
for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
|
||||||
if (!formActionExecution.isEnabled()) {
|
if (!formActionExecution.isEnabled()) {
|
||||||
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
|
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
|
||||||
|
@ -183,12 +186,28 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
||||||
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
|
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
|
||||||
successes.add(result);
|
successes.add(result);
|
||||||
} else {
|
} else {
|
||||||
processor.logFailure();
|
|
||||||
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
|
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
|
||||||
return renderForm(result.formData, result.errors);
|
errors.add(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
processor.logFailure();
|
||||||
|
List<FormMessage> messages = new LinkedList<>();
|
||||||
|
Set<String> fields = new HashSet<>();
|
||||||
|
for (ValidationContextImpl v : errors) {
|
||||||
|
for (FormMessage m : v.errors) {
|
||||||
|
if (!fields.contains(m.getField())) {
|
||||||
|
fields.add(m.getField());
|
||||||
|
messages.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValidationContextImpl first = errors.get(0);
|
||||||
|
first.getEvent().error(first.error);
|
||||||
|
return renderForm(first.formData, messages);
|
||||||
|
}
|
||||||
|
|
||||||
for (ValidationContextImpl context : successes) {
|
for (ValidationContextImpl context : successes) {
|
||||||
context.action.success(context);
|
context.action.success(context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ public interface ValidationContext extends FormContext {
|
||||||
*/
|
*/
|
||||||
void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors);
|
void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors);
|
||||||
|
|
||||||
|
void error(String error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark this validation as sucessful
|
* Mark this validation as sucessful
|
||||||
*
|
*
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class RegistrationPassword implements FormAction, FormActionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.size() > 0) {
|
if (errors.size() > 0) {
|
||||||
context.getEvent().error(Errors.INVALID_REGISTRATION);
|
context.error(Errors.INVALID_REGISTRATION);
|
||||||
formData.remove(RegistrationPage.FIELD_PASSWORD);
|
formData.remove(RegistrationPage.FIELD_PASSWORD);
|
||||||
formData.remove(RegistrationPage.FIELD_PASSWORD_CONFIRM);
|
formData.remove(RegistrationPage.FIELD_PASSWORD_CONFIRM);
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
|
|
|
@ -56,15 +56,17 @@ public class RegistrationProfile implements FormAction, FormActionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
String email = formData.getFirst(Validation.FIELD_EMAIL);
|
String email = formData.getFirst(Validation.FIELD_EMAIL);
|
||||||
|
boolean emailValid = true;
|
||||||
if (Validation.isBlank(email)) {
|
if (Validation.isBlank(email)) {
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
|
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
|
||||||
|
emailValid = false;
|
||||||
} else if (!Validation.isEmailValid(email)) {
|
} else if (!Validation.isEmailValid(email)) {
|
||||||
formData.remove(Validation.FIELD_EMAIL);
|
|
||||||
context.getEvent().detail(Details.EMAIL, email);
|
context.getEvent().detail(Details.EMAIL, email);
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL));
|
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL));
|
||||||
|
emailValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
|
if (emailValid && context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
|
||||||
eventError = Errors.EMAIL_IN_USE;
|
eventError = Errors.EMAIL_IN_USE;
|
||||||
formData.remove(Validation.FIELD_EMAIL);
|
formData.remove(Validation.FIELD_EMAIL);
|
||||||
context.getEvent().detail(Details.EMAIL, email);
|
context.getEvent().detail(Details.EMAIL, email);
|
||||||
|
@ -72,7 +74,7 @@ public class RegistrationProfile implements FormAction, FormActionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.size() > 0) {
|
if (errors.size() > 0) {
|
||||||
context.getEvent().error(eventError);
|
context.error(eventError);
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
|
||||||
} else {
|
} else {
|
||||||
errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED));
|
errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED));
|
||||||
formData.remove(G_RECAPTCHA_RESPONSE);
|
formData.remove(G_RECAPTCHA_RESPONSE);
|
||||||
context.getEvent().error(Errors.INVALID_REGISTRATION);
|
context.error(Errors.INVALID_REGISTRATION);
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,8 @@ public class RegistrationUserCreation implements FormAction, FormActionFactory {
|
||||||
|
|
||||||
String usernameField = RegistrationPage.FIELD_USERNAME;
|
String usernameField = RegistrationPage.FIELD_USERNAME;
|
||||||
if (context.getRealm().isRegistrationEmailAsUsername()) {
|
if (context.getRealm().isRegistrationEmailAsUsername()) {
|
||||||
username = email;
|
context.getEvent().detail(Details.USERNAME, email);
|
||||||
context.getEvent().detail(Details.USERNAME, username);
|
|
||||||
usernameField = RegistrationPage.FIELD_EMAIL;
|
|
||||||
if (Validation.isBlank(email)) {
|
if (Validation.isBlank(email)) {
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
|
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
|
||||||
} else if (!Validation.isEmailValid(email)) {
|
} else if (!Validation.isEmailValid(email)) {
|
||||||
|
@ -66,33 +65,32 @@ public class RegistrationUserCreation implements FormAction, FormActionFactory {
|
||||||
formData.remove(Validation.FIELD_EMAIL);
|
formData.remove(Validation.FIELD_EMAIL);
|
||||||
}
|
}
|
||||||
if (errors.size() > 0) {
|
if (errors.size() > 0) {
|
||||||
context.getEvent().error(Errors.INVALID_REGISTRATION);
|
context.error(Errors.INVALID_REGISTRATION);
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (email != null && context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
|
if (email != null && context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
|
||||||
context.getEvent().error(Errors.USERNAME_IN_USE);
|
context.error(Errors.EMAIL_IN_USE);
|
||||||
formData.remove(Validation.FIELD_EMAIL);
|
formData.remove(Validation.FIELD_EMAIL);
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.USERNAME_EXISTS));
|
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.EMAIL_EXISTS));
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Validation.isBlank(username)) {
|
if (Validation.isBlank(username)) {
|
||||||
context.getEvent().error(Errors.INVALID_REGISTRATION);
|
context.error(Errors.INVALID_REGISTRATION);
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_USERNAME, Messages.MISSING_USERNAME));
|
errors.add(new FormMessage(RegistrationPage.FIELD_USERNAME, Messages.MISSING_USERNAME));
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
if (context.getSession().users().getUserByUsername(username, context.getRealm()) != null) {
|
if (context.getSession().users().getUserByUsername(username, context.getRealm()) != null) {
|
||||||
context.getEvent().error(Errors.USERNAME_IN_USE);
|
context.error(Errors.USERNAME_IN_USE);
|
||||||
errors.add(new FormMessage(usernameField, Messages.USERNAME_EXISTS));
|
errors.add(new FormMessage(usernameField, Messages.USERNAME_EXISTS));
|
||||||
formData.remove(Validation.FIELD_USERNAME);
|
formData.remove(Validation.FIELD_USERNAME);
|
||||||
formData.remove(Validation.FIELD_EMAIL);
|
|
||||||
context.validationError(formData, errors);
|
context.validationError(formData, errors);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
context.success();
|
context.success();
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.console.authentication;
|
||||||
|
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||||
import org.keycloak.testsuite.console.page.authentication.PasswordPolicy;
|
import org.keycloak.testsuite.console.page.authentication.PasswordPolicy;
|
||||||
|
@ -30,7 +31,7 @@ import static org.keycloak.testsuite.console.page.authentication.PasswordPolicy.
|
||||||
* @author Petr Mensik
|
* @author Petr Mensik
|
||||||
* @author mhajas
|
* @author mhajas
|
||||||
*/
|
*/
|
||||||
//@Ignore // FIXME still unstable
|
@Ignore // FIXME still unstable
|
||||||
public class PasswordPolicyTest extends AbstractConsoleTest {
|
public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
@Page
|
@Page
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.console.realm;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.testsuite.console.page.realm.TokenSettings;
|
import org.keycloak.testsuite.console.page.realm.TokenSettings;
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||||
*
|
*
|
||||||
* @author Petr Mensik
|
* @author Petr Mensik
|
||||||
*/
|
*/
|
||||||
|
@Ignore
|
||||||
public class TokensTest extends AbstractRealmTest {
|
public class TokensTest extends AbstractRealmTest {
|
||||||
|
|
||||||
@Page
|
@Page
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.keycloak.exportimport.ExportImportConfig;
|
||||||
import org.keycloak.exportimport.dir.DirExportProvider;
|
import org.keycloak.exportimport.dir.DirExportProvider;
|
||||||
import org.keycloak.exportimport.dir.DirExportProviderFactory;
|
import org.keycloak.exportimport.dir.DirExportProviderFactory;
|
||||||
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
|
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
|
||||||
import org.keycloak.exportimport.zip.ZipExportProviderFactory;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RealmProvider;
|
import org.keycloak.models.RealmProvider;
|
||||||
|
@ -217,30 +216,6 @@ public class ExportImportTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testZipFullExportImport() throws Throwable {
|
|
||||||
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
|
|
||||||
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-full.zip";
|
|
||||||
new File(zipFilePath).delete();
|
|
||||||
ExportImportConfig.setZipFile(zipFilePath);
|
|
||||||
ExportImportConfig.setZipPassword("encPassword");
|
|
||||||
ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
|
|
||||||
|
|
||||||
testFullExportImport();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testZipRealmExportImport() throws Throwable {
|
|
||||||
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
|
|
||||||
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-realm.zip";
|
|
||||||
new File(zipFilePath).delete();
|
|
||||||
ExportImportConfig.setZipFile(zipFilePath);
|
|
||||||
ExportImportConfig.setZipPassword("encPassword");
|
|
||||||
ExportImportConfig.setUsersPerFile(3);
|
|
||||||
|
|
||||||
testRealmExportImport();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testFullExportImport() {
|
private void testFullExportImport() {
|
||||||
ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
|
ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
|
||||||
ExportImportConfig.setRealmName(null);
|
ExportImportConfig.setRealmName(null);
|
||||||
|
|
|
@ -21,10 +21,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.forms;
|
package org.keycloak.testsuite.forms;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.*;
|
||||||
import org.junit.ClassRule;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.PasswordPolicy;
|
import org.keycloak.models.PasswordPolicy;
|
||||||
|
@ -42,6 +39,8 @@ import org.keycloak.testsuite.rule.WebResource;
|
||||||
import org.keycloak.testsuite.rule.WebRule;
|
import org.keycloak.testsuite.rule.WebRule;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
@ -80,15 +79,15 @@ public class RegisterTest {
|
||||||
registerPage.register("firstName", "lastName", "registerExistingUser@email", "test-user@localhost", "password", "password");
|
registerPage.register("firstName", "lastName", "registerExistingUser@email", "test-user@localhost", "password", "password");
|
||||||
|
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Username already exists.", registerPage.getError());
|
assertEquals("Username already exists.", registerPage.getError());
|
||||||
|
|
||||||
// assert form keeps form fields on error
|
// assert form keeps form fields on error
|
||||||
Assert.assertEquals("firstName", registerPage.getFirstName());
|
assertEquals("firstName", registerPage.getFirstName());
|
||||||
Assert.assertEquals("lastName", registerPage.getLastName());
|
assertEquals("lastName", registerPage.getLastName());
|
||||||
Assert.assertEquals("", registerPage.getEmail());
|
assertEquals("registerExistingUser@email", registerPage.getEmail());
|
||||||
Assert.assertEquals("", registerPage.getUsername());
|
assertEquals("", registerPage.getUsername());
|
||||||
Assert.assertEquals("", registerPage.getPassword());
|
assertEquals("", registerPage.getPassword());
|
||||||
Assert.assertEquals("", registerPage.getPasswordConfirm());
|
assertEquals("", registerPage.getPasswordConfirm());
|
||||||
|
|
||||||
events.expectRegister("test-user@localhost", "registerExistingUser@email")
|
events.expectRegister("test-user@localhost", "registerExistingUser@email")
|
||||||
.removeDetail(Details.EMAIL)
|
.removeDetail(Details.EMAIL)
|
||||||
|
@ -104,15 +103,15 @@ public class RegisterTest {
|
||||||
registerPage.register("firstName", "lastName", "registerUserInvalidPasswordConfirm@email", "registerUserInvalidPasswordConfirm", "password", "invalid");
|
registerPage.register("firstName", "lastName", "registerUserInvalidPasswordConfirm@email", "registerUserInvalidPasswordConfirm", "password", "invalid");
|
||||||
|
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Password confirmation doesn't match.", registerPage.getError());
|
assertEquals("Password confirmation doesn't match.", registerPage.getError());
|
||||||
|
|
||||||
// assert form keeps form fields on error
|
// assert form keeps form fields on error
|
||||||
Assert.assertEquals("firstName", registerPage.getFirstName());
|
assertEquals("firstName", registerPage.getFirstName());
|
||||||
Assert.assertEquals("lastName", registerPage.getLastName());
|
assertEquals("lastName", registerPage.getLastName());
|
||||||
Assert.assertEquals("registerUserInvalidPasswordConfirm@email", registerPage.getEmail());
|
assertEquals("registerUserInvalidPasswordConfirm@email", registerPage.getEmail());
|
||||||
Assert.assertEquals("registerUserInvalidPasswordConfirm", registerPage.getUsername());
|
assertEquals("registerUserInvalidPasswordConfirm", registerPage.getUsername());
|
||||||
Assert.assertEquals("", registerPage.getPassword());
|
assertEquals("", registerPage.getPassword());
|
||||||
Assert.assertEquals("", registerPage.getPasswordConfirm());
|
assertEquals("", registerPage.getPasswordConfirm());
|
||||||
|
|
||||||
events.expectRegister("registerUserInvalidPasswordConfirm", "registerUserInvalidPasswordConfirm@email")
|
events.expectRegister("registerUserInvalidPasswordConfirm", "registerUserInvalidPasswordConfirm@email")
|
||||||
.removeDetail(Details.USERNAME)
|
.removeDetail(Details.USERNAME)
|
||||||
|
@ -129,7 +128,7 @@ public class RegisterTest {
|
||||||
registerPage.register("firstName", "lastName", "registerUserMissingPassword@email", "registerUserMissingPassword", null, null);
|
registerPage.register("firstName", "lastName", "registerUserMissingPassword@email", "registerUserMissingPassword", null, null);
|
||||||
|
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Please specify password.", registerPage.getError());
|
assertEquals("Please specify password.", registerPage.getError());
|
||||||
|
|
||||||
events.expectRegister("registerUserMissingPassword", "registerUserMissingPassword@email")
|
events.expectRegister("registerUserMissingPassword", "registerUserMissingPassword@email")
|
||||||
.removeDetail(Details.USERNAME)
|
.removeDetail(Details.USERNAME)
|
||||||
|
@ -154,7 +153,7 @@ public class RegisterTest {
|
||||||
registerPage.register("firstName", "lastName", "registerPasswordPolicy@email", "registerPasswordPolicy", "pass", "pass");
|
registerPage.register("firstName", "lastName", "registerPasswordPolicy@email", "registerPasswordPolicy", "pass", "pass");
|
||||||
|
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Invalid password: minimum length 8.", registerPage.getError());
|
assertEquals("Invalid password: minimum length 8.", registerPage.getError());
|
||||||
|
|
||||||
events.expectRegister("registerPasswordPolicy", "registerPasswordPolicy@email")
|
events.expectRegister("registerPasswordPolicy", "registerPasswordPolicy@email")
|
||||||
.removeDetail(Details.USERNAME)
|
.removeDetail(Details.USERNAME)
|
||||||
|
@ -162,7 +161,7 @@ public class RegisterTest {
|
||||||
.user((String) null).error("invalid_registration").assertEvent();
|
.user((String) null).error("invalid_registration").assertEvent();
|
||||||
|
|
||||||
registerPage.register("firstName", "lastName", "registerPasswordPolicy@email", "registerPasswordPolicy", "password", "password");
|
registerPage.register("firstName", "lastName", "registerPasswordPolicy@email", "registerPasswordPolicy", "password", "password");
|
||||||
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||||
|
|
||||||
String userId = events.expectRegister("registerPasswordPolicy", "registerPasswordPolicy@email").assertEvent().getUserId();
|
String userId = events.expectRegister("registerPasswordPolicy", "registerPasswordPolicy@email").assertEvent().getUserId();
|
||||||
|
|
||||||
|
@ -186,7 +185,7 @@ public class RegisterTest {
|
||||||
registerPage.register("firstName", "lastName", "registerUserMissingUsername@email", null, "password", "password");
|
registerPage.register("firstName", "lastName", "registerUserMissingUsername@email", null, "password", "password");
|
||||||
|
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Please specify username.", registerPage.getError());
|
assertEquals("Please specify username.", registerPage.getError());
|
||||||
|
|
||||||
events.expectRegister(null, "registerUserMissingUsername@email")
|
events.expectRegister(null, "registerUserMissingUsername@email")
|
||||||
.removeDetail(Details.USERNAME)
|
.removeDetail(Details.USERNAME)
|
||||||
|
@ -195,21 +194,51 @@ public class RegisterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void registerUserMissingOrInvalidEmail() {
|
public void registerUserManyErrors() {
|
||||||
|
loginPage.open();
|
||||||
|
loginPage.clickRegister();
|
||||||
|
registerPage.assertCurrent();
|
||||||
|
|
||||||
|
registerPage.register(null, null, null, null, null, null);
|
||||||
|
|
||||||
|
registerPage.assertCurrent();
|
||||||
|
|
||||||
|
assertEquals("Please specify username.\n" +
|
||||||
|
"Please specify first name.\n" +
|
||||||
|
"Please specify last name.\n" +
|
||||||
|
"Please specify email.\n" +
|
||||||
|
"Please specify password.", registerPage.getError());
|
||||||
|
|
||||||
|
events.expectRegister(null, "registerUserMissingUsername@email")
|
||||||
|
.removeDetail(Details.USERNAME)
|
||||||
|
.removeDetail(Details.EMAIL)
|
||||||
|
.error("invalid_registration").assertEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerUserMissingEmail() {
|
||||||
loginPage.open();
|
loginPage.open();
|
||||||
loginPage.clickRegister();
|
loginPage.clickRegister();
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
|
|
||||||
registerPage.register("firstName", "lastName", null, "registerUserMissingEmail", "password", "password");
|
registerPage.register("firstName", "lastName", null, "registerUserMissingEmail", "password", "password");
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Please specify email.", registerPage.getError());
|
assertEquals("Please specify email.", registerPage.getError());
|
||||||
events.expectRegister("registerUserMissingEmail", null)
|
events.expectRegister("registerUserMissingEmail", null)
|
||||||
.removeDetail("email")
|
.removeDetail("email")
|
||||||
.error("invalid_registration").assertEvent();
|
.error("invalid_registration").assertEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerUserInvalidEmail() {
|
||||||
|
loginPage.open();
|
||||||
|
loginPage.clickRegister();
|
||||||
|
registerPage.assertCurrent();
|
||||||
|
|
||||||
registerPage.register("firstName", "lastName", "registerUserInvalidEmailemail", "registerUserInvalidEmail", "password", "password");
|
registerPage.register("firstName", "lastName", "registerUserInvalidEmailemail", "registerUserInvalidEmail", "password", "password");
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Invalid email address.", registerPage.getError());
|
assertEquals("registerUserInvalidEmailemail", registerPage.getEmail());
|
||||||
|
assertEquals("Invalid email address.", registerPage.getError());
|
||||||
events.expectRegister("registerUserInvalidEmail", "registerUserInvalidEmailemail")
|
events.expectRegister("registerUserInvalidEmail", "registerUserInvalidEmailemail")
|
||||||
.error("invalid_registration").assertEvent();
|
.error("invalid_registration").assertEvent();
|
||||||
}
|
}
|
||||||
|
@ -222,7 +251,7 @@ public class RegisterTest {
|
||||||
|
|
||||||
registerPage.register("firstName", "lastName", "registerUserSuccess@email", "registerUserSuccess", "password", "password");
|
registerPage.register("firstName", "lastName", "registerUserSuccess@email", "registerUserSuccess", "password", "password");
|
||||||
|
|
||||||
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||||
|
|
||||||
String userId = events.expectRegister("registerUserSuccess", "registerUserSuccess@email").assertEvent().getUserId();
|
String userId = events.expectRegister("registerUserSuccess", "registerUserSuccess@email").assertEvent().getUserId();
|
||||||
events.expectLogin().detail("username", "registerusersuccess").user(userId).assertEvent();
|
events.expectLogin().detail("username", "registerusersuccess").user(userId).assertEvent();
|
||||||
|
@ -233,10 +262,10 @@ public class RegisterTest {
|
||||||
// test that timestamp is current with 10s tollerance
|
// test that timestamp is current with 10s tollerance
|
||||||
Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
|
Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
|
||||||
// test user info is set from form
|
// test user info is set from form
|
||||||
Assert.assertEquals("registerusersuccess", user.getUsername());
|
assertEquals("registerusersuccess", user.getUsername());
|
||||||
Assert.assertEquals("registerusersuccess@email", user.getEmail());
|
assertEquals("registerusersuccess@email", user.getEmail());
|
||||||
Assert.assertEquals("firstName", user.getFirstName());
|
assertEquals("firstName", user.getFirstName());
|
||||||
Assert.assertEquals("lastName", user.getLastName());
|
assertEquals("lastName", user.getLastName());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected UserModel getUser(String userId) {
|
protected UserModel getUser(String userId) {
|
||||||
|
@ -261,9 +290,9 @@ public class RegisterTest {
|
||||||
registerPage.registerWithEmailAsUsername("firstName", "lastName", "test-user@localhost", "password", "password");
|
registerPage.registerWithEmailAsUsername("firstName", "lastName", "test-user@localhost", "password", "password");
|
||||||
|
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Username already exists.", registerPage.getError());
|
assertEquals("Email already exists.", registerPage.getError());
|
||||||
|
|
||||||
events.expectRegister("test-user@localhost", "test-user@localhost").user((String) null).error("username_in_use").assertEvent();
|
events.expectRegister("test-user@localhost", "test-user@localhost").user((String) null).error("email_in_use").assertEvent();
|
||||||
} finally {
|
} finally {
|
||||||
configureRelamRegistrationEmailAsUsername(false);
|
configureRelamRegistrationEmailAsUsername(false);
|
||||||
}
|
}
|
||||||
|
@ -280,12 +309,12 @@ public class RegisterTest {
|
||||||
|
|
||||||
registerPage.registerWithEmailAsUsername("firstName", "lastName", null, "password", "password");
|
registerPage.registerWithEmailAsUsername("firstName", "lastName", null, "password", "password");
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Please specify email.", registerPage.getError());
|
assertEquals("Please specify email.", registerPage.getError());
|
||||||
events.expectRegister(null, null).removeDetail("username").removeDetail("email").error("invalid_registration").assertEvent();
|
events.expectRegister(null, null).removeDetail("username").removeDetail("email").error("invalid_registration").assertEvent();
|
||||||
|
|
||||||
registerPage.registerWithEmailAsUsername("firstName", "lastName", "registerUserInvalidEmailemail", "password", "password");
|
registerPage.registerWithEmailAsUsername("firstName", "lastName", "registerUserInvalidEmailemail", "password", "password");
|
||||||
registerPage.assertCurrent();
|
registerPage.assertCurrent();
|
||||||
Assert.assertEquals("Invalid email address.", registerPage.getError());
|
assertEquals("Invalid email address.", registerPage.getError());
|
||||||
events.expectRegister("registerUserInvalidEmailemail", "registerUserInvalidEmailemail").error("invalid_registration").assertEvent();
|
events.expectRegister("registerUserInvalidEmailemail", "registerUserInvalidEmailemail").error("invalid_registration").assertEvent();
|
||||||
} finally {
|
} finally {
|
||||||
configureRelamRegistrationEmailAsUsername(false);
|
configureRelamRegistrationEmailAsUsername(false);
|
||||||
|
@ -303,7 +332,7 @@ public class RegisterTest {
|
||||||
|
|
||||||
registerPage.registerWithEmailAsUsername("firstName", "lastName", "registerUserSuccessE@email", "password", "password");
|
registerPage.registerWithEmailAsUsername("firstName", "lastName", "registerUserSuccessE@email", "password", "password");
|
||||||
|
|
||||||
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||||
|
|
||||||
String userId = events.expectRegister("registerUserSuccessE@email", "registerUserSuccessE@email").assertEvent().getUserId();
|
String userId = events.expectRegister("registerUserSuccessE@email", "registerUserSuccessE@email").assertEvent().getUserId();
|
||||||
events.expectLogin().detail("username", "registerusersuccesse@email").user(userId).assertEvent();
|
events.expectLogin().detail("username", "registerusersuccesse@email").user(userId).assertEvent();
|
||||||
|
|
Loading…
Reference in a new issue