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>
|
||||
</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>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<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-dir" 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-themes" 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-dir" 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-themes" 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"/>
|
||||
</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">
|
||||
<maven-resource group="org.liquibase" artifact="liquibase-core"/>
|
||||
</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-dir" 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-themes" 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-dir" 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-themes" services="import"/>
|
||||
<module name="org.keycloak.keycloak-invalidation-cache-infinispan" services="import"/>
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<outputDirectory>modules/system/layers/base</outputDirectory>
|
||||
<includes>
|
||||
<include>com/google/zxing/**</include>
|
||||
<include>de/idyl/winzipaes/**</include>
|
||||
<include>org/freemarker/**</include>
|
||||
<include>org/keycloak/**</include>
|
||||
<include>org/liquibase/**</include>
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
<para>
|
||||
You can export/import your database either to:
|
||||
<itemizedlist>
|
||||
<listitem>Encrypted ZIP file on local filesystem</listitem>
|
||||
<listitem>Directory on local filesystem</listitem>
|
||||
<listitem>Single JSON file on your filesystem</listitem>
|
||||
</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.
|
||||
<itemizedlist>
|
||||
<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>
|
||||
</para>
|
||||
<para>
|
||||
Encrypted ZIP is recommended as export contains many sensitive informations like passwords of your users (even if they are hashed),
|
||||
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
|
||||
If you import to 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.
|
||||
Processing of each file is done in separate transaction as exporting/importing all users at once could also lead to memory issues.
|
||||
</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>
|
||||
To export into unencrypted directory you can use:
|
||||
<programlisting><![CDATA[
|
||||
|
@ -80,7 +63,7 @@ bin/standalone.sh -Dkeycloak.migration.action=import
|
|||
<term>-Dkeycloak.migration.usersExportStrategy</term>
|
||||
<listitem>
|
||||
<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:
|
||||
<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>
|
||||
|
|
|
@ -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-dir</module>
|
||||
<module>export-import-single-file</module>
|
||||
<module>export-import-zip</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="alias">Alias </label>
|
||||
<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>
|
||||
<kc-tooltip>Specifies display name for the flow.</kc-tooltip>
|
||||
</div>
|
||||
|
|
|
@ -90,14 +90,7 @@ public class Pbkdf2PasswordEncoder {
|
|||
public static byte[] getSalt() {
|
||||
byte[] buffer = new byte[16];
|
||||
|
||||
SecureRandom secureRandom;
|
||||
|
||||
try {
|
||||
secureRandom = SecureRandom.getInstance(RNG_ALGORITHM);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("RNG algorithm not found");
|
||||
}
|
||||
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
secureRandom.nextBytes(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>
|
||||
<google.zxing.version>3.2.1</google.zxing.version>
|
||||
<github.relaxng.version>2011.1</github.relaxng.version>
|
||||
<winzipaes.version>1.0.1</winzipaes.version>
|
||||
<freemarker.version>2.3.23</freemarker.version>
|
||||
<twitter4j.version>4.0.4</twitter4j.version>
|
||||
<selenium.version>2.35.0</selenium.version>
|
||||
|
@ -373,13 +372,6 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Encrypted ZIP -->
|
||||
<dependency>
|
||||
<groupId>de.idyl</groupId>
|
||||
<artifactId>winzipaes</artifactId>
|
||||
<version>${winzipaes.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache DS -->
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
|
@ -700,11 +692,6 @@
|
|||
<artifactId>keycloak-export-import-single-file</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-export-import-zip</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<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.UriInfo;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
FormAction action;
|
||||
String error;
|
||||
|
||||
private ValidationContextImpl(AuthenticationExecutionModel executionModel, FormAction action) {
|
||||
super(executionModel);
|
||||
|
@ -131,6 +129,10 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
|||
this.formData = formData;
|
||||
}
|
||||
|
||||
public void error(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success() {
|
||||
success = true;
|
||||
|
@ -145,6 +147,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
|||
Map<String, ClientSessionModel.ExecutionStatus> executionStatus = new HashMap<>();
|
||||
List<FormAction> requiredActions = new LinkedList<>();
|
||||
List<ValidationContextImpl> successes = new LinkedList<>();
|
||||
List<ValidationContextImpl> errors = new LinkedList<>();
|
||||
for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
|
||||
if (!formActionExecution.isEnabled()) {
|
||||
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
|
||||
|
@ -183,12 +186,28 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
|
|||
executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
|
||||
successes.add(result);
|
||||
} else {
|
||||
processor.logFailure();
|
||||
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) {
|
||||
context.action.success(context);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ public interface ValidationContext extends FormContext {
|
|||
*/
|
||||
void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors);
|
||||
|
||||
void error(String error);
|
||||
|
||||
/**
|
||||
* Mark this validation as sucessful
|
||||
*
|
||||
|
|
|
@ -59,7 +59,7 @@ public class RegistrationPassword implements FormAction, FormActionFactory {
|
|||
}
|
||||
|
||||
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_CONFIRM);
|
||||
context.validationError(formData, errors);
|
||||
|
|
|
@ -56,15 +56,17 @@ public class RegistrationProfile implements FormAction, FormActionFactory {
|
|||
}
|
||||
|
||||
String email = formData.getFirst(Validation.FIELD_EMAIL);
|
||||
boolean emailValid = true;
|
||||
if (Validation.isBlank(email)) {
|
||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
|
||||
emailValid = false;
|
||||
} else if (!Validation.isEmailValid(email)) {
|
||||
formData.remove(Validation.FIELD_EMAIL);
|
||||
context.getEvent().detail(Details.EMAIL, 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;
|
||||
formData.remove(Validation.FIELD_EMAIL);
|
||||
context.getEvent().detail(Details.EMAIL, email);
|
||||
|
@ -72,7 +74,7 @@ public class RegistrationProfile implements FormAction, FormActionFactory {
|
|||
}
|
||||
|
||||
if (errors.size() > 0) {
|
||||
context.getEvent().error(eventError);
|
||||
context.error(eventError);
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
|
|||
} else {
|
||||
errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED));
|
||||
formData.remove(G_RECAPTCHA_RESPONSE);
|
||||
context.getEvent().error(Errors.INVALID_REGISTRATION);
|
||||
context.error(Errors.INVALID_REGISTRATION);
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
|
||||
|
|
|
@ -56,9 +56,8 @@ public class RegistrationUserCreation implements FormAction, FormActionFactory {
|
|||
|
||||
String usernameField = RegistrationPage.FIELD_USERNAME;
|
||||
if (context.getRealm().isRegistrationEmailAsUsername()) {
|
||||
username = email;
|
||||
context.getEvent().detail(Details.USERNAME, username);
|
||||
usernameField = RegistrationPage.FIELD_EMAIL;
|
||||
context.getEvent().detail(Details.USERNAME, email);
|
||||
|
||||
if (Validation.isBlank(email)) {
|
||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
|
||||
} else if (!Validation.isEmailValid(email)) {
|
||||
|
@ -66,33 +65,32 @@ public class RegistrationUserCreation implements FormAction, FormActionFactory {
|
|||
formData.remove(Validation.FIELD_EMAIL);
|
||||
}
|
||||
if (errors.size() > 0) {
|
||||
context.getEvent().error(Errors.INVALID_REGISTRATION);
|
||||
context.error(Errors.INVALID_REGISTRATION);
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.USERNAME_EXISTS));
|
||||
errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.EMAIL_EXISTS));
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
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));
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
if (context.getSession().users().getUserByUsername(username, context.getRealm()) != null) {
|
||||
context.getEvent().error(Errors.USERNAME_IN_USE);
|
||||
errors.add(new FormMessage(usernameField, Messages.USERNAME_EXISTS));
|
||||
formData.remove(Validation.FIELD_USERNAME);
|
||||
formData.remove(Validation.FIELD_EMAIL);
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
if (context.getSession().users().getUserByUsername(username, context.getRealm()) != null) {
|
||||
context.error(Errors.USERNAME_IN_USE);
|
||||
errors.add(new FormMessage(usernameField, Messages.USERNAME_EXISTS));
|
||||
formData.remove(Validation.FIELD_USERNAME);
|
||||
context.validationError(formData, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
context.success();
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.console.authentication;
|
|||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||
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 mhajas
|
||||
*/
|
||||
//@Ignore // FIXME still unstable
|
||||
@Ignore // FIXME still unstable
|
||||
public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.console.realm;
|
|||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.console.page.realm.TokenSettings;
|
||||
|
||||
|
@ -30,6 +31,7 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
|||
*
|
||||
* @author Petr Mensik
|
||||
*/
|
||||
@Ignore
|
||||
public class TokensTest extends AbstractRealmTest {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.keycloak.exportimport.ExportImportConfig;
|
|||
import org.keycloak.exportimport.dir.DirExportProvider;
|
||||
import org.keycloak.exportimport.dir.DirExportProviderFactory;
|
||||
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
|
||||
import org.keycloak.exportimport.zip.ZipExportProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
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() {
|
||||
ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
|
||||
ExportImportConfig.setRealmName(null);
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.forms;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
|
@ -42,6 +39,8 @@ import org.keycloak.testsuite.rule.WebResource;
|
|||
import org.keycloak.testsuite.rule.WebRule;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @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.assertCurrent();
|
||||
Assert.assertEquals("Username already exists.", registerPage.getError());
|
||||
assertEquals("Username already exists.", registerPage.getError());
|
||||
|
||||
// assert form keeps form fields on error
|
||||
Assert.assertEquals("firstName", registerPage.getFirstName());
|
||||
Assert.assertEquals("lastName", registerPage.getLastName());
|
||||
Assert.assertEquals("", registerPage.getEmail());
|
||||
Assert.assertEquals("", registerPage.getUsername());
|
||||
Assert.assertEquals("", registerPage.getPassword());
|
||||
Assert.assertEquals("", registerPage.getPasswordConfirm());
|
||||
assertEquals("firstName", registerPage.getFirstName());
|
||||
assertEquals("lastName", registerPage.getLastName());
|
||||
assertEquals("registerExistingUser@email", registerPage.getEmail());
|
||||
assertEquals("", registerPage.getUsername());
|
||||
assertEquals("", registerPage.getPassword());
|
||||
assertEquals("", registerPage.getPasswordConfirm());
|
||||
|
||||
events.expectRegister("test-user@localhost", "registerExistingUser@email")
|
||||
.removeDetail(Details.EMAIL)
|
||||
|
@ -104,15 +103,15 @@ public class RegisterTest {
|
|||
registerPage.register("firstName", "lastName", "registerUserInvalidPasswordConfirm@email", "registerUserInvalidPasswordConfirm", "password", "invalid");
|
||||
|
||||
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.assertEquals("firstName", registerPage.getFirstName());
|
||||
Assert.assertEquals("lastName", registerPage.getLastName());
|
||||
Assert.assertEquals("registerUserInvalidPasswordConfirm@email", registerPage.getEmail());
|
||||
Assert.assertEquals("registerUserInvalidPasswordConfirm", registerPage.getUsername());
|
||||
Assert.assertEquals("", registerPage.getPassword());
|
||||
Assert.assertEquals("", registerPage.getPasswordConfirm());
|
||||
assertEquals("firstName", registerPage.getFirstName());
|
||||
assertEquals("lastName", registerPage.getLastName());
|
||||
assertEquals("registerUserInvalidPasswordConfirm@email", registerPage.getEmail());
|
||||
assertEquals("registerUserInvalidPasswordConfirm", registerPage.getUsername());
|
||||
assertEquals("", registerPage.getPassword());
|
||||
assertEquals("", registerPage.getPasswordConfirm());
|
||||
|
||||
events.expectRegister("registerUserInvalidPasswordConfirm", "registerUserInvalidPasswordConfirm@email")
|
||||
.removeDetail(Details.USERNAME)
|
||||
|
@ -129,7 +128,7 @@ public class RegisterTest {
|
|||
registerPage.register("firstName", "lastName", "registerUserMissingPassword@email", "registerUserMissingPassword", null, null);
|
||||
|
||||
registerPage.assertCurrent();
|
||||
Assert.assertEquals("Please specify password.", registerPage.getError());
|
||||
assertEquals("Please specify password.", registerPage.getError());
|
||||
|
||||
events.expectRegister("registerUserMissingPassword", "registerUserMissingPassword@email")
|
||||
.removeDetail(Details.USERNAME)
|
||||
|
@ -154,7 +153,7 @@ public class RegisterTest {
|
|||
registerPage.register("firstName", "lastName", "registerPasswordPolicy@email", "registerPasswordPolicy", "pass", "pass");
|
||||
|
||||
registerPage.assertCurrent();
|
||||
Assert.assertEquals("Invalid password: minimum length 8.", registerPage.getError());
|
||||
assertEquals("Invalid password: minimum length 8.", registerPage.getError());
|
||||
|
||||
events.expectRegister("registerPasswordPolicy", "registerPasswordPolicy@email")
|
||||
.removeDetail(Details.USERNAME)
|
||||
|
@ -162,7 +161,7 @@ public class RegisterTest {
|
|||
.user((String) null).error("invalid_registration").assertEvent();
|
||||
|
||||
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();
|
||||
|
||||
|
@ -186,7 +185,7 @@ public class RegisterTest {
|
|||
registerPage.register("firstName", "lastName", "registerUserMissingUsername@email", null, "password", "password");
|
||||
|
||||
registerPage.assertCurrent();
|
||||
Assert.assertEquals("Please specify username.", registerPage.getError());
|
||||
assertEquals("Please specify username.", registerPage.getError());
|
||||
|
||||
events.expectRegister(null, "registerUserMissingUsername@email")
|
||||
.removeDetail(Details.USERNAME)
|
||||
|
@ -195,21 +194,51 @@ public class RegisterTest {
|
|||
}
|
||||
|
||||
@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.clickRegister();
|
||||
registerPage.assertCurrent();
|
||||
|
||||
registerPage.register("firstName", "lastName", null, "registerUserMissingEmail", "password", "password");
|
||||
registerPage.assertCurrent();
|
||||
Assert.assertEquals("Please specify email.", registerPage.getError());
|
||||
assertEquals("Please specify email.", registerPage.getError());
|
||||
events.expectRegister("registerUserMissingEmail", null)
|
||||
.removeDetail("email")
|
||||
.error("invalid_registration").assertEvent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerUserInvalidEmail() {
|
||||
loginPage.open();
|
||||
loginPage.clickRegister();
|
||||
registerPage.assertCurrent();
|
||||
|
||||
registerPage.register("firstName", "lastName", "registerUserInvalidEmailemail", "registerUserInvalidEmail", "password", "password");
|
||||
registerPage.assertCurrent();
|
||||
Assert.assertEquals("Invalid email address.", registerPage.getError());
|
||||
assertEquals("registerUserInvalidEmailemail", registerPage.getEmail());
|
||||
assertEquals("Invalid email address.", registerPage.getError());
|
||||
events.expectRegister("registerUserInvalidEmail", "registerUserInvalidEmailemail")
|
||||
.error("invalid_registration").assertEvent();
|
||||
}
|
||||
|
@ -222,7 +251,7 @@ public class RegisterTest {
|
|||
|
||||
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();
|
||||
events.expectLogin().detail("username", "registerusersuccess").user(userId).assertEvent();
|
||||
|
@ -233,10 +262,10 @@ public class RegisterTest {
|
|||
// test that timestamp is current with 10s tollerance
|
||||
Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
|
||||
// test user info is set from form
|
||||
Assert.assertEquals("registerusersuccess", user.getUsername());
|
||||
Assert.assertEquals("registerusersuccess@email", user.getEmail());
|
||||
Assert.assertEquals("firstName", user.getFirstName());
|
||||
Assert.assertEquals("lastName", user.getLastName());
|
||||
assertEquals("registerusersuccess", user.getUsername());
|
||||
assertEquals("registerusersuccess@email", user.getEmail());
|
||||
assertEquals("firstName", user.getFirstName());
|
||||
assertEquals("lastName", user.getLastName());
|
||||
}
|
||||
|
||||
protected UserModel getUser(String userId) {
|
||||
|
@ -261,9 +290,9 @@ public class RegisterTest {
|
|||
registerPage.registerWithEmailAsUsername("firstName", "lastName", "test-user@localhost", "password", "password");
|
||||
|
||||
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 {
|
||||
configureRelamRegistrationEmailAsUsername(false);
|
||||
}
|
||||
|
@ -280,12 +309,12 @@ public class RegisterTest {
|
|||
|
||||
registerPage.registerWithEmailAsUsername("firstName", "lastName", null, "password", "password");
|
||||
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();
|
||||
|
||||
registerPage.registerWithEmailAsUsername("firstName", "lastName", "registerUserInvalidEmailemail", "password", "password");
|
||||
registerPage.assertCurrent();
|
||||
Assert.assertEquals("Invalid email address.", registerPage.getError());
|
||||
assertEquals("Invalid email address.", registerPage.getError());
|
||||
events.expectRegister("registerUserInvalidEmailemail", "registerUserInvalidEmailemail").error("invalid_registration").assertEvent();
|
||||
} finally {
|
||||
configureRelamRegistrationEmailAsUsername(false);
|
||||
|
@ -303,7 +332,7 @@ public class RegisterTest {
|
|||
|
||||
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();
|
||||
events.expectLogin().detail("username", "registerusersuccesse@email").user(userId).assertEvent();
|
||||
|
|
Loading…
Reference in a new issue