commit
ac7f4833d8
104 changed files with 6176 additions and 704 deletions
|
@ -111,7 +111,7 @@ public class AbstractOAuthClient {
|
|||
.param("grant_type", "authorization_code")
|
||||
.param("code", code)
|
||||
.param("client_id", clientId)
|
||||
.param("Password", password)
|
||||
.param("password", password)
|
||||
.param("redirect_uri", redirectUri);
|
||||
Response res = client.target(codeUrl).request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(codeForm));
|
||||
try {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package org.keycloak.representations.idm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ResourceRepresentation {
|
||||
public class ApplicationRepresentation {
|
||||
protected String self; // link
|
||||
protected String id;
|
||||
protected String name;
|
||||
|
@ -70,14 +68,14 @@ public class ResourceRepresentation {
|
|||
this.roles = roles;
|
||||
}
|
||||
|
||||
public ResourceRepresentation role(RoleRepresentation role) {
|
||||
public ApplicationRepresentation role(RoleRepresentation role) {
|
||||
if (this.roles == null) this.roles = new ArrayList<RoleRepresentation>();
|
||||
this.roles.add(role);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ResourceRepresentation role(String role, String description) {
|
||||
public ApplicationRepresentation role(String role, String description) {
|
||||
if (this.roles == null) this.roles = new ArrayList<RoleRepresentation>();
|
||||
this.roles.add(new RoleRepresentation(role, description));
|
||||
return this;
|
||||
|
@ -123,12 +121,11 @@ public class ResourceRepresentation {
|
|||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public ResourceRepresentation credential(String type, String value, boolean hashed) {
|
||||
public ApplicationRepresentation credential(String type, String value) {
|
||||
if (this.credentials == null) credentials = new ArrayList<CredentialRepresentation>();
|
||||
CredentialRepresentation cred = new CredentialRepresentation();
|
||||
cred.setType(type);
|
||||
cred.setValue(value);
|
||||
cred.setHashed(hashed);
|
||||
credentials.add(cred);
|
||||
return this;
|
||||
}
|
|
@ -5,9 +5,13 @@ package org.keycloak.representations.idm;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CredentialRepresentation {
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String TOTP = "totp";
|
||||
public static final String CLIENT_CERT = "cert";
|
||||
|
||||
protected String type;
|
||||
protected String value;
|
||||
protected boolean hashed;
|
||||
protected String device;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
|
@ -25,11 +29,11 @@ public class CredentialRepresentation {
|
|||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isHashed() {
|
||||
return hashed;
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setHashed(boolean hashed) {
|
||||
this.hashed = hashed;
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,16 +17,18 @@ public class RealmRepresentation {
|
|||
protected boolean enabled;
|
||||
protected boolean sslNotRequired;
|
||||
protected boolean cookieLoginAllowed;
|
||||
protected boolean registrationAllowed;
|
||||
protected boolean social;
|
||||
protected String privateKey;
|
||||
protected String publicKey;
|
||||
protected List<RoleRepresentation> roles;
|
||||
protected List<RequiredCredentialRepresentation> requiredCredentials;
|
||||
protected List<RequiredCredentialRepresentation> requiredResourceCredentials;
|
||||
protected List<RequiredCredentialRepresentation> requiredOAuthClientCredentials;
|
||||
protected Set<String> requiredCredentials;
|
||||
protected Set<String> requiredApplicationCredentials;
|
||||
protected Set<String> requiredOAuthClientCredentials;
|
||||
protected List<UserRepresentation> users;
|
||||
protected List<RoleMappingRepresentation> roleMappings;
|
||||
protected List<ScopeMappingRepresentation> scopeMappings;
|
||||
protected List<ResourceRepresentation> resources;
|
||||
protected List<ApplicationRepresentation> applications;
|
||||
|
||||
|
||||
public String getSelf() {
|
||||
|
@ -57,14 +59,14 @@ public class RealmRepresentation {
|
|||
return users;
|
||||
}
|
||||
|
||||
public List<ResourceRepresentation> getResources() {
|
||||
return resources;
|
||||
public List<ApplicationRepresentation> getApplications() {
|
||||
return applications;
|
||||
}
|
||||
|
||||
public ResourceRepresentation resource(String name) {
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
if (resources == null) resources = new ArrayList<ResourceRepresentation>();
|
||||
resources.add(resource);
|
||||
public ApplicationRepresentation resource(String name) {
|
||||
ApplicationRepresentation resource = new ApplicationRepresentation();
|
||||
if (applications == null) applications = new ArrayList<ApplicationRepresentation>();
|
||||
applications.add(resource);
|
||||
resource.setName(name);
|
||||
return resource;
|
||||
}
|
||||
|
@ -81,8 +83,8 @@ public class RealmRepresentation {
|
|||
return user;
|
||||
}
|
||||
|
||||
public void setResources(List<ResourceRepresentation> resources) {
|
||||
this.resources = resources;
|
||||
public void setApplications(List<ApplicationRepresentation> applications) {
|
||||
this.applications = applications;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
|
@ -141,27 +143,27 @@ public class RealmRepresentation {
|
|||
return mapping;
|
||||
}
|
||||
|
||||
public List<RequiredCredentialRepresentation> getRequiredCredentials() {
|
||||
public Set<String> getRequiredCredentials() {
|
||||
return requiredCredentials;
|
||||
}
|
||||
|
||||
public void setRequiredCredentials(List<RequiredCredentialRepresentation> requiredCredentials) {
|
||||
public void setRequiredCredentials(Set<String> requiredCredentials) {
|
||||
this.requiredCredentials = requiredCredentials;
|
||||
}
|
||||
|
||||
public List<RequiredCredentialRepresentation> getRequiredResourceCredentials() {
|
||||
return requiredResourceCredentials;
|
||||
public Set<String> getRequiredApplicationCredentials() {
|
||||
return requiredApplicationCredentials;
|
||||
}
|
||||
|
||||
public void setRequiredResourceCredentials(List<RequiredCredentialRepresentation> requiredResourceCredentials) {
|
||||
this.requiredResourceCredentials = requiredResourceCredentials;
|
||||
public void setRequiredApplicationCredentials(Set<String> requiredApplicationCredentials) {
|
||||
this.requiredApplicationCredentials = requiredApplicationCredentials;
|
||||
}
|
||||
|
||||
public List<RequiredCredentialRepresentation> getRequiredOAuthClientCredentials() {
|
||||
public Set<String> getRequiredOAuthClientCredentials() {
|
||||
return requiredOAuthClientCredentials;
|
||||
}
|
||||
|
||||
public void setRequiredOAuthClientCredentials(List<RequiredCredentialRepresentation> requiredOAuthClientCredentials) {
|
||||
public void setRequiredOAuthClientCredentials(Set<String> requiredOAuthClientCredentials) {
|
||||
this.requiredOAuthClientCredentials = requiredOAuthClientCredentials;
|
||||
}
|
||||
|
||||
|
@ -196,4 +198,20 @@ public class RealmRepresentation {
|
|||
public void setPublicKey(String publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public boolean isRegistrationAllowed() {
|
||||
return registrationAllowed;
|
||||
}
|
||||
|
||||
public void setRegistrationAllowed(boolean registrationAllowed) {
|
||||
this.registrationAllowed = registrationAllowed;
|
||||
}
|
||||
|
||||
public boolean isSocial() {
|
||||
return social;
|
||||
}
|
||||
|
||||
public void setSocial(boolean social) {
|
||||
this.social = social;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package org.keycloak.representations.idm;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RequiredCredentialRepresentation {
|
||||
public static final String PASSWORD = "Password";
|
||||
public static final String TOTP = "TOTP";
|
||||
public static final String CLIENT_CERT = "CLIENT_CERT";
|
||||
public static final String CALLER_PRINCIPAL = "CALLER_PRINCIPAL";
|
||||
protected String type;
|
||||
protected boolean input;
|
||||
protected boolean secret;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setInput(boolean input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public boolean isSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(boolean secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,9 @@ public class UserRepresentation {
|
|||
protected String self; // link
|
||||
protected String username;
|
||||
protected boolean enabled;
|
||||
protected String firstName;
|
||||
protected String lastName;
|
||||
protected String email;
|
||||
protected Map<String, String> attributes;
|
||||
protected List<CredentialRepresentation> credentials;
|
||||
|
||||
|
@ -25,6 +28,30 @@ public class UserRepresentation {
|
|||
this.self = self;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
@ -55,12 +82,11 @@ public class UserRepresentation {
|
|||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public UserRepresentation credential(String type, String value, boolean hashed) {
|
||||
public UserRepresentation credential(String type, String value) {
|
||||
if (this.credentials == null) credentials = new ArrayList<CredentialRepresentation>();
|
||||
CredentialRepresentation cred = new CredentialRepresentation();
|
||||
cred.setType(type);
|
||||
cred.setValue(value);
|
||||
cred.setHashed(hashed);
|
||||
credentials.add(cred);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.keycloak.example.demo;
|
||||
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.models.KeycloakSession;
|
||||
|
@ -40,7 +41,7 @@ public class DemoApplication extends KeycloakApplication {
|
|||
defaultRealm.setCookieLoginAllowed(true);
|
||||
defaultRealm.setRegistrationAllowed(true);
|
||||
manager.generateRealmKeys(defaultRealm);
|
||||
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
|
||||
defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE);
|
||||
|
||||
RealmRepresentation rep = loadJson("META-INF/testrealm.json");
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
|
||||
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
|
||||
<class>org.keycloak.services.models.picketlink.mappings.RealmEntity</class>
|
||||
<class>org.keycloak.services.models.picketlink.mappings.ResourceEntity</class>
|
||||
<class>org.keycloak.services.models.picketlink.mappings.ApplicationEntity</class>
|
||||
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
|
||||
|
|
|
@ -1,33 +1,15 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"enabled" : true,
|
||||
"tokenLifespan" : 10,
|
||||
"accessCodeLifespan" : 10,
|
||||
"sslNotRequired" : true,
|
||||
"cookieLoginAllowed" : true,
|
||||
"privateKey" : "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"requiredCredentials" : [
|
||||
{
|
||||
"type" : "Password",
|
||||
"input" : true,
|
||||
"secret" : true
|
||||
}
|
||||
],
|
||||
"requiredResourceCredentials" : [
|
||||
{
|
||||
"type" : "Password",
|
||||
"input" : true,
|
||||
"secret" : true
|
||||
}
|
||||
],
|
||||
"requiredOAuthClientCredentials" : [
|
||||
{
|
||||
"type" : "Password",
|
||||
"input" : true,
|
||||
"secret" : true
|
||||
}
|
||||
],
|
||||
"realm": "demo",
|
||||
"enabled": true,
|
||||
"tokenLifespan": 300,
|
||||
"accessCodeLifespan": 10,
|
||||
"sslNotRequired": true,
|
||||
"cookieLoginAllowed": true,
|
||||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "password" ],
|
||||
"requiredOAuthClientCredentials": [ "password" ],
|
||||
"users" : [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
|
@ -36,7 +18,7 @@
|
|||
"email" : "bburke@redhat.com"
|
||||
},
|
||||
"credentials" : [
|
||||
{ "type" : "Password",
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
]
|
||||
},
|
||||
|
@ -44,50 +26,60 @@
|
|||
"username" : "third-party",
|
||||
"enabled" : true,
|
||||
"credentials" : [
|
||||
{ "type" : "Password",
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"roles" : [
|
||||
{ "name" : "user", "description" : "Have User privileges" },
|
||||
{ "name" : "admin", "description" : "Have Administrator privileges" }
|
||||
],
|
||||
"roleMappings" : [
|
||||
"roles": [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
"roles" : ["user"]
|
||||
"name": "user",
|
||||
"description": "Have User privileges"
|
||||
},
|
||||
{
|
||||
"username" : "third-party",
|
||||
"roles" : ["KEYCLOAK_IDENTITY_REQUESTER"]
|
||||
"name": "admin",
|
||||
"description": "Have Administrator privileges"
|
||||
}
|
||||
],
|
||||
"scopeMappings" : [
|
||||
"roleMappings": [
|
||||
{
|
||||
"username" : "third-party",
|
||||
"roles" : ["user"]
|
||||
"username": "bburke@redhat.com",
|
||||
"roles": ["user"]
|
||||
},
|
||||
{
|
||||
"username": "third-party",
|
||||
"roles": ["KEYCLOAK_IDENTITY_REQUESTER"]
|
||||
}
|
||||
],
|
||||
"resources" : [
|
||||
"scopeMappings": [
|
||||
{
|
||||
"name" : "customer-portal",
|
||||
"enabled" : true,
|
||||
"adminUrl" : "http://localhost:8080/customer-portal/j_admin_request",
|
||||
"useRealmMappings" : true,
|
||||
"credentials" : [
|
||||
{ "type" : "Password",
|
||||
"value" : "password" }
|
||||
"username": "third-party",
|
||||
"roles": ["user"]
|
||||
}
|
||||
],
|
||||
"applications": [
|
||||
{
|
||||
"name": "customer-portal",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
|
||||
"useRealmMappings": true,
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "product-portal",
|
||||
"enabled" : true,
|
||||
"adminUrl" : "http://localhost:8080/product-portal/j_admin_request",
|
||||
"useRealmMappings" : true,
|
||||
"credentials" : [
|
||||
{ "type" : "Password",
|
||||
"value" : "password" }
|
||||
"name": "product-portal",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8080/product-portal/j_admin_request",
|
||||
"useRealmMappings": true,
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -15,13 +15,20 @@
|
|||
<link href="lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
<link href="css/admin.css" rel="stylesheet">
|
||||
<link href="css/admin-responsive.css" rel="stylesheet">
|
||||
<link href="lib/select2-3.4.1/select2.css" rel="stylesheet">
|
||||
|
||||
<link href="css/styles.css" rel="stylesheet">
|
||||
|
||||
<script src="lib/jquery/jquery-1.10.2.js" type="text/javascript"></script>
|
||||
<script src="lib/select2-3.4.1/select2.js" type="text/javascript"></script>
|
||||
|
||||
<script src="lib/angular/angular.js"></script>
|
||||
<script src="lib/angular/angular-resource.js"></script>
|
||||
<script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
|
||||
|
||||
<script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
|
||||
<script src="lib/angular/select2.js" type="text/javascript"></script>
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/controllers.js"></script>
|
||||
<script src="js/loaders.js"></script>
|
||||
|
@ -57,9 +64,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script src="lib/jquery/jquery-1.10.2.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$.idleTimeout('#idletimeout', '#idletimeout a', {
|
||||
idleAfter: 300,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.loaders', 'keycloak.controllers', 'ui.bootstrap' ]);
|
||||
var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.loaders', 'keycloak.controllers', 'ui.bootstrap', 'ui.select2' ]);
|
||||
var resourceRequests = 0;
|
||||
|
||||
module.config([ '$routeProvider', function($routeProvider) {
|
||||
|
@ -197,13 +197,12 @@ module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location
|
|||
};
|
||||
});
|
||||
|
||||
/*
|
||||
module.directive('kcInput', function() {
|
||||
var d = {
|
||||
scope : true,
|
||||
replace : false,
|
||||
link : function(scope, element, attrs) {
|
||||
var form = element.closest('form');
|
||||
var form = element.children('form');
|
||||
var label = element.children('label');
|
||||
var input = element.children('input');
|
||||
|
||||
|
@ -242,7 +241,7 @@ module.directive('kcEnter', function() {
|
|||
});
|
||||
};
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
module.filter('remove', function() {
|
||||
return function(input, remove, attribute) {
|
||||
|
|
|
@ -27,25 +27,9 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
|
|||
|
||||
$http.get('/auth-server/rest/saas/admin/realms').success(function(data) {
|
||||
Current.realms = data;
|
||||
var count = 0;
|
||||
var showrealm = false;
|
||||
var id = null;
|
||||
for (var key in data) {
|
||||
if (count > 0) {
|
||||
showrealm = false;
|
||||
break;
|
||||
}
|
||||
id = key;
|
||||
showrealm = true;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (showrealm) {
|
||||
console.log('default redirect to realm: ' + id);
|
||||
Current.realm = Current.realms[id];
|
||||
$location.url("/realms/" + id);
|
||||
} else {
|
||||
//console.log('not redirecting');
|
||||
if (data.length > 0) {
|
||||
Current.realm = data[0];
|
||||
$location.url("/realms/" + Current.realm.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -58,137 +42,115 @@ module.controller('RealmListCtrl', function($scope, Realm, Current) {
|
|||
module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $location) {
|
||||
// Current.realms = Realm.get();
|
||||
$scope.current = Current;
|
||||
if (Current.realms.length > 0) {
|
||||
console.log('[0]: ' + current.realms[0].realm);
|
||||
}
|
||||
$scope.changeRealm = function() {
|
||||
for (var id in Current.realms) {
|
||||
var val = Current.realms[id];
|
||||
if (val == Current.realm) {
|
||||
$location.url("/realms/" + id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$location.url("/realms/" + $scope.current.realm.id);
|
||||
};
|
||||
$scope.showNav = function() {
|
||||
var show = false;
|
||||
for (var key in Current.realms) {
|
||||
if (typeof Current.realms[key] != "function") {
|
||||
if (Current.realms[key] == Current.realm) {
|
||||
$scope.currentRealmId = key;
|
||||
}
|
||||
show = true;
|
||||
}
|
||||
}
|
||||
var show = Current.realms.length > 0;
|
||||
console.log('Show dropdown? ' + show);
|
||||
return Auth.loggedIn && show;
|
||||
}
|
||||
});
|
||||
|
||||
module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $location, Dialog, Notifications) {
|
||||
$scope.realm = angular.copy(realm);
|
||||
module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $http, $location, Dialog, Notifications) {
|
||||
$scope.createRealm = !realm.id;
|
||||
|
||||
console.log('RealmDetailCtrl');
|
||||
|
||||
if ($scope.createRealm) {
|
||||
$scope.realm.enabled = true;
|
||||
$scope.realm.requireSsl = true;
|
||||
$scope.realm.cookieLoginAllowed = true;
|
||||
$scope.realm.tokenLifespan = 300;
|
||||
$scope.realm.tokenLifespanUnit = 'SECONDS';
|
||||
$scope.realm.accessCodeLifespan = 300;
|
||||
$scope.realm.accessCodeLifespanUnit = 'SECONDS';
|
||||
$scope.realm = {
|
||||
enabled: true,
|
||||
requireSsl: true,
|
||||
cookieLoginAllowed: true,
|
||||
tokenLifespan: 300,
|
||||
tokenLifespanUnit: 'SECONDS',
|
||||
accessCodeLifespan: 300,
|
||||
accessCodeLifespanUnit: 'SECONDS',
|
||||
requiredCredentials: ['password'],
|
||||
requiredOAuthClientCredentials: ['password'],
|
||||
requiredApplicationCredentials: ['password']
|
||||
|
||||
};
|
||||
} else {
|
||||
$scope.realm.name = realm.realm;
|
||||
$scope.realm.requireSsl = !$scope.realm.sslNotRequired;
|
||||
$scope.realm.tokenLifespanUnit = 'SECONDS';
|
||||
$scope.realm.acessCodeLifespanUnit = 'SECONDS';
|
||||
if (Current.realm == null || Current.realm.id != realm.id) {
|
||||
for (var i = 0; i < Current.realms.length; i++) {
|
||||
if (realm.id == Current.realms[i].id) {
|
||||
Current.realm = Current.realms[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Current.realm == null || Current.realm.id != realm.id) {
|
||||
console.log('should be unreachable');
|
||||
console.log('Why? ' + Current.realms.length + ' ' + Current.realm);
|
||||
return;
|
||||
}
|
||||
$scope.realm = angular.copy(realm);
|
||||
$scope.realm.requireSsl = !realm.sslNotRequired;
|
||||
$scope.realm.tokenLifespanUnit = 'SECONDS';
|
||||
$scope.realm.accessCodeLifespanUnit = 'SECONDS';
|
||||
|
||||
}
|
||||
|
||||
var oldCopy = angular.copy($scope.realm);
|
||||
|
||||
|
||||
|
||||
$scope.userCredentialOptions = {
|
||||
'multiple' : true,
|
||||
'simple_tags' : true,
|
||||
'tags' : ['password', 'totp', 'cert']
|
||||
};
|
||||
|
||||
$scope.changed = $scope.create;
|
||||
|
||||
$scope.$watch('realm', function() {
|
||||
if (!angular.equals($scope.realm, realm)) {
|
||||
if (!angular.equals($scope.realm, oldCopy)) {
|
||||
$scope.changed = true;
|
||||
}
|
||||
}, true);
|
||||
|
||||
$scope.addRole = function() {
|
||||
if ($scope.newRole) {
|
||||
if ($scope.realm.roles) {
|
||||
for ( var i = 0; i < $scope.realm.roles.length; i++) {
|
||||
if ($scope.realm.roles[i] == $scope.newRole) {
|
||||
Notifications.warn("Role already exists");
|
||||
$scope.newRole = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$scope.realm.roles) {
|
||||
$scope.realm.roles = [];
|
||||
}
|
||||
|
||||
$scope.realm.roles.push($scope.newRole);
|
||||
$scope.newRole = null;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.removeRole = function(role) {
|
||||
Dialog.confirmDelete(role, 'role', function() {
|
||||
var i = $scope.realm.roles.indexOf(role);
|
||||
if (i > -1) {
|
||||
$scope.realm.roles.splice(i, 1);
|
||||
}
|
||||
|
||||
if ($scope.realm.initialRoles) {
|
||||
$scope.removeInitialRole(role);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addInitialRole = function() {
|
||||
if ($scope.newInitialRole) {
|
||||
if (!$scope.realm.initialRoles) {
|
||||
$scope.realm.initialRoles = [];
|
||||
}
|
||||
|
||||
$scope.realm.initialRoles.push($scope.newInitialRole);
|
||||
$scope.newInitialRole = null;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.removeInitialRole = function(role) {
|
||||
var i = $scope.realm.initialRoles.indexOf(role);
|
||||
if (i > -1) {
|
||||
$scope.realm.initialRoles.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.save = function() {
|
||||
if ($scope.realmForm.$valid) {
|
||||
var realmCopy = {
|
||||
realm: $scope.realm.name,
|
||||
enabled: $scope.realm.enabled,
|
||||
cookieLoginAllowed: $scope.realm.cookieLoginAllowed,
|
||||
sslNotRequired: !$scope.realm.requireSsl,
|
||||
tokenLifespan: $scope.realm.tokenLifespan,
|
||||
accessCodeLifespan: $scope.realm.accessCodeLifespan
|
||||
|
||||
};
|
||||
|
||||
var realmCopy = angular.copy($scope.realm);
|
||||
realmCopy.sslNotRequired = !realmCopy.requireSsl;
|
||||
delete realmCopy["requireSsl"];
|
||||
delete realmCopy["tokenLifespanUnit"];
|
||||
delete realmCopy["accessCodeLifespanUnit"];
|
||||
if ($scope.createRealm) {
|
||||
Realm.save(realmCopy, function(data, headers) {
|
||||
console.log('creating new realm');
|
||||
var l = headers().location;
|
||||
var id = l.substring(l.lastIndexOf("/") + 1);
|
||||
|
||||
var data = Realm.get(function() {
|
||||
var data = Realm.query(function() {
|
||||
Current.realms = data;
|
||||
Current.realm = Current.realms[id];
|
||||
for (var i = 0; i < Current.realms.length; i++) {
|
||||
if (Current.realms[i].id == id) {
|
||||
Current.realm = Current.realms[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
$location.url("/realms/" + id);
|
||||
Notifications.success("Created realm");
|
||||
});
|
||||
} else {
|
||||
Realm.update(realmCopy, function() {
|
||||
Current.realms = Realm.get();
|
||||
console.log('updating realm...');
|
||||
$scope.changed = false;
|
||||
realm = angular.copy($scope.realm);
|
||||
Realm.update(realmCopy, function() {
|
||||
var id = realmCopy.id;
|
||||
var data = Realm.query(function() {
|
||||
Current.realms = data;
|
||||
for (var i = 0; i < Current.realms.length; i++) {
|
||||
if (Current.realms[i].id == id) {
|
||||
Current.realm = Current.realms[i];
|
||||
oldCopy = angular.copy($scope.realm);
|
||||
}
|
||||
}
|
||||
});
|
||||
$location.url("/realms/" + id);
|
||||
Notifications.success("Saved changes to realm");
|
||||
});
|
||||
}
|
||||
|
@ -198,7 +160,7 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $lo
|
|||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
$scope.realm = angular.copy(realm);
|
||||
$scope.realm = angular.copy(oldCopy);
|
||||
$scope.changed = false;
|
||||
$scope.realmForm.showErrors = false;
|
||||
};
|
||||
|
@ -385,7 +347,7 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, applications,
|
|||
application : null
|
||||
};
|
||||
|
||||
selection.applications = angular.copy(applications);
|
||||
selection.applications = applications;
|
||||
|
||||
for (var i=0;i < selection.applications.length; i++) {
|
||||
if (selection.applications[i].name == application.name) {
|
||||
|
@ -396,10 +358,11 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, applications,
|
|||
}
|
||||
|
||||
$scope.selection = selection;
|
||||
|
||||
$scope.application = angular.copy(application);
|
||||
|
||||
|
||||
if (!$scope.create) {
|
||||
$scope.application= selection.application;
|
||||
} else {
|
||||
$scope.application = {};
|
||||
}
|
||||
|
||||
$scope.changeApplication = function() {
|
||||
console.log('ApplicationDetailCtrl.changeApplication() - ' + $scope.selection.application.name);
|
||||
|
@ -407,7 +370,7 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, applications,
|
|||
};
|
||||
|
||||
$scope.$watch('application', function() {
|
||||
if (!angular.equals($scope.application, application)) {
|
||||
if (!angular.equals($scope.selection.application, application)) {
|
||||
$scope.changed = true;
|
||||
}
|
||||
}, true);
|
||||
|
|
|
@ -132,7 +132,7 @@ module.factory('Role', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('Application', function($resource) {
|
||||
return $resource('/auth-server/rest/saas/admin/realms/:realm/resources/:id', {
|
||||
return $resource('/auth-server/rest/saas/admin/realms/:realm/applications/:id', {
|
||||
realm : '@realm',
|
||||
id : '@id'
|
||||
}, {
|
||||
|
|
|
@ -22574,7 +22574,7 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|||
* @description
|
||||
* Fetches, compiles and includes an external HTML fragment.
|
||||
*
|
||||
* Keep in mind that Same Origin Policy applies to included resources
|
||||
* Keep in mind that Same Origin Policy applies to included applications
|
||||
* (e.g. ngInclude won't work for cross-domain requests on all browsers and for
|
||||
* file:// access on some browsers).
|
||||
*
|
||||
|
|
|
@ -13168,7 +13168,7 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|||
* @description
|
||||
* Fetches, compiles and includes an external HTML fragment.
|
||||
*
|
||||
* Keep in mind that Same Origin Policy applies to included resources
|
||||
* Keep in mind that Same Origin Policy applies to included applications
|
||||
* (e.g. ngInclude won't work for cross-domain requests on all browsers and for
|
||||
* file:// access on some browsers).
|
||||
*
|
||||
|
|
195
examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/angular/select2.js
vendored
Executable file
195
examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/angular/select2.js
vendored
Executable file
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
* Enhanced Select2 Dropmenus
|
||||
*
|
||||
* @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
|
||||
* This change is so that you do not have to do an additional query yourself on top of Select2's own query
|
||||
* @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
|
||||
*/
|
||||
angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelect2', ['uiSelect2Config', '$timeout', function (uiSelect2Config, $timeout) {
|
||||
var options = {};
|
||||
if (uiSelect2Config) {
|
||||
angular.extend(options, uiSelect2Config);
|
||||
}
|
||||
return {
|
||||
require: 'ngModel',
|
||||
compile: function (tElm, tAttrs) {
|
||||
var watch,
|
||||
repeatOption,
|
||||
repeatAttr,
|
||||
isSelect = tElm.is('select'),
|
||||
isMultiple = (tAttrs.multiple !== undefined);
|
||||
|
||||
// Enable watching of the options dataset if in use
|
||||
if (tElm.is('select')) {
|
||||
repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');
|
||||
|
||||
if (repeatOption.length) {
|
||||
repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
|
||||
watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
|
||||
}
|
||||
}
|
||||
|
||||
return function (scope, elm, attrs, controller) {
|
||||
// instance-specific options
|
||||
var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
|
||||
|
||||
/*
|
||||
Convert from Select2 view-model to Angular view-model.
|
||||
*/
|
||||
var convertToAngularModel = function(select2_data) {
|
||||
var model;
|
||||
if (opts.simple_tags) {
|
||||
model = []
|
||||
angular.forEach(select2_data, function(value, index) {
|
||||
model.push(value.id)
|
||||
})
|
||||
} else {
|
||||
model = select2_data
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
/*
|
||||
Convert from Angular view-model to Select2 view-model.
|
||||
*/
|
||||
var convertToSelect2Model = function(angular_data) {
|
||||
var model = []
|
||||
if (!angular_data) {
|
||||
return model;
|
||||
}
|
||||
|
||||
if (opts.simple_tags) {
|
||||
model = [];
|
||||
angular.forEach(
|
||||
angular_data,
|
||||
function(value, index) {
|
||||
model.push({'id': value, 'text': value});
|
||||
})
|
||||
} else {
|
||||
model = angular_data;
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
if (isSelect) {
|
||||
// Use <select multiple> instead
|
||||
delete opts.multiple;
|
||||
delete opts.initSelection;
|
||||
} else if (isMultiple) {
|
||||
opts.multiple = true;
|
||||
}
|
||||
|
||||
if (controller) {
|
||||
// Watch the model for programmatic changes
|
||||
scope.$watch(tAttrs.ngModel, function(current, old) {
|
||||
if (!current) {
|
||||
return
|
||||
}
|
||||
if (current == old) {
|
||||
return
|
||||
}
|
||||
controller.$render()
|
||||
}, true)
|
||||
controller.$render = function () {
|
||||
if (isSelect) {
|
||||
elm.select2('val', controller.$viewValue);
|
||||
} else {
|
||||
if (opts.multiple) {
|
||||
elm.select2(
|
||||
'data', convertToSelect2Model(controller.$viewValue));
|
||||
} else {
|
||||
if (angular.isObject(controller.$viewValue)) {
|
||||
elm.select2('data', controller.$viewValue);
|
||||
} else if (!controller.$viewValue) {
|
||||
elm.select2('data', null);
|
||||
} else {
|
||||
elm.select2('val', controller.$viewValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Watch the options dataset for changes
|
||||
if (watch) {
|
||||
scope.$watch(watch, function (newVal, oldVal, scope) {
|
||||
if (!newVal) return;
|
||||
// Delayed so that the options have time to be rendered
|
||||
$timeout(function () {
|
||||
elm.select2('val', controller.$viewValue);
|
||||
// Refresh angular to remove the superfluous option
|
||||
elm.trigger('change');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Update valid and dirty statuses
|
||||
controller.$parsers.push(function (value) {
|
||||
var div = elm.prev()
|
||||
div
|
||||
.toggleClass('ng-invalid', !controller.$valid)
|
||||
.toggleClass('ng-valid', controller.$valid)
|
||||
.toggleClass('ng-invalid-required', !controller.$valid)
|
||||
.toggleClass('ng-valid-required', controller.$valid)
|
||||
.toggleClass('ng-dirty', controller.$dirty)
|
||||
.toggleClass('ng-pristine', controller.$pristine);
|
||||
return value;
|
||||
});
|
||||
|
||||
if (!isSelect) {
|
||||
// Set the view and model value and update the angular template manually for the ajax/multiple select2.
|
||||
elm.bind("change", function () {
|
||||
if (scope.$$phase) return;
|
||||
scope.$apply(function () {
|
||||
controller.$setViewValue(
|
||||
convertToAngularModel(elm.select2('data')));
|
||||
});
|
||||
});
|
||||
|
||||
if (opts.initSelection) {
|
||||
var initSelection = opts.initSelection;
|
||||
opts.initSelection = function (element, callback) {
|
||||
initSelection(element, function (value) {
|
||||
controller.$setViewValue(convertToAngularModel(value));
|
||||
callback(value);
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elm.bind("$destroy", function() {
|
||||
elm.select2("destroy");
|
||||
});
|
||||
|
||||
attrs.$observe('disabled', function (value) {
|
||||
elm.select2('enable', !value);
|
||||
});
|
||||
|
||||
attrs.$observe('readonly', function (value) {
|
||||
elm.select2('readonly', !!value);
|
||||
});
|
||||
|
||||
if (attrs.ngMultiple) {
|
||||
scope.$watch(attrs.ngMultiple, function(newVal) {
|
||||
elm.select2(opts);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize the plugin late so that the injected DOM does not disrupt the template compiler
|
||||
$timeout(function () {
|
||||
elm.select2(opts);
|
||||
|
||||
// Set initial value - I'm not sure about this but it seems to need to be there
|
||||
elm.val(controller.$viewValue);
|
||||
// important!
|
||||
controller.$render();
|
||||
|
||||
// Not sure if I should just check for !isSelect OR if I should check for 'tags' key
|
||||
if (!opts.initSelection && !isSelect)
|
||||
controller.$setViewValue(
|
||||
convertToAngularModel(elm.select2('data')));
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -0,0 +1,18 @@
|
|||
Copyright 2012 Igor Vaynberg
|
||||
|
||||
Version: @@ver@@ Timestamp: @@timestamp@@
|
||||
|
||||
This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
|
||||
General Public License version 2 (the "GPL License"). You may choose either license to govern your
|
||||
use of this software only upon the condition that you accept all of the terms of either the Apache
|
||||
License or the GPL License.
|
||||
|
||||
You may obtain a copy of the Apache License and the GPL License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the Apache License
|
||||
or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
either express or implied. See the Apache License and the GPL License for the specific language governing
|
||||
permissions and limitations under the Apache License and the GPL License.
|
|
@ -0,0 +1,83 @@
|
|||
Select2
|
||||
=======
|
||||
|
||||
Select2 is a jQuery-based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.
|
||||
|
||||
To get started, checkout examples and documentation at http://ivaynberg.github.com/select2
|
||||
|
||||
Use cases
|
||||
---------
|
||||
|
||||
* Enhancing native selects with search.
|
||||
* Enhancing native selects with a better multi-select interface.
|
||||
* Loading data from JavaScript: easily load items via ajax and have them searchable.
|
||||
* Nesting optgroups: native selects only support one level of nested. Select2 does not have this restriction.
|
||||
* Tagging: ability to add new items on the fly.
|
||||
* Working with large, remote datasets: ability to partially load a dataset based on the search term.
|
||||
* Paging of large datasets: easy support for loading more pages when the results are scrolled to the end.
|
||||
* Templating: support for custom rendering of results and selections.
|
||||
|
||||
Browser compatibility
|
||||
---------------------
|
||||
* IE 8+
|
||||
* Chrome 8+
|
||||
* Firefox 10+
|
||||
* Safari 3+
|
||||
* Opera 10.6+
|
||||
|
||||
Integrations
|
||||
------------
|
||||
|
||||
* [Wicket-Select2](https://github.com/ivaynberg/wicket-select2) (Java / [Apache Wicket](http://wicket.apache.org))
|
||||
* [select2-rails](https://github.com/argerim/select2-rails) (Ruby on Rails)
|
||||
* [AngularUI](http://angular-ui.github.com/#directives-select2) ([AngularJS](angularjs.org))
|
||||
* [Django](https://github.com/applegrew/django-select2)
|
||||
* [Symfony](https://github.com/19Gerhard85/sfSelect2WidgetsPlugin)
|
||||
* [Bootstrap](https://github.com/t0m/select2-bootstrap-css) (CSS skin)
|
||||
* [Yii](https://github.com/tonybolzan/yii-select2)
|
||||
|
||||
Internationalization (i18n)
|
||||
---------------------------
|
||||
|
||||
Select2 supports multiple languages by simply including the right
|
||||
language JS file (`select2_locale_it.js`, `select2_locale_nl.js`, etc.).
|
||||
|
||||
Missing a language? Just copy `select2_locale_en.js.template`, translate
|
||||
it, and make a pull request back to Select2 here on GitHub.
|
||||
|
||||
Bug tracker
|
||||
-----------
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
|
||||
https://github.com/ivaynberg/select2/issues
|
||||
|
||||
Mailing list
|
||||
------------
|
||||
|
||||
Have a question? Ask on our mailing list!
|
||||
|
||||
select2@googlegroups.com
|
||||
|
||||
https://groups.google.com/d/forum/select2
|
||||
|
||||
|
||||
Copyright and license
|
||||
---------------------
|
||||
|
||||
Copyright 2012 Igor Vaynberg
|
||||
|
||||
This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
|
||||
General Public License version 2 (the "GPL License"). You may choose either license to govern your
|
||||
use of this software only upon the condition that you accept all of the terms of either the Apache
|
||||
License or the GPL License.
|
||||
|
||||
You may obtain a copy of the Apache License and the GPL License in the LICENSE file, or at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the Apache License
|
||||
or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
either express or implied. See the Apache License and the GPL License for the specific language governing
|
||||
permissions and limitations under the Apache License and the GPL License.
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "select2",
|
||||
"version": "3.4.1",
|
||||
"main": ["select2.js", "select2.css", "select2.png", "select2x2.png", "select2-spinner.gif"],
|
||||
"dependencies": {
|
||||
"jquery": ">= 1.7.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo -n "Enter the version for this release: "
|
||||
|
||||
read ver
|
||||
|
||||
if [ ! $ver ]; then
|
||||
echo "Invalid version."
|
||||
exit
|
||||
fi
|
||||
|
||||
name="select2"
|
||||
js="$name.js"
|
||||
mini="$name.min.js"
|
||||
css="$name.css"
|
||||
release="$name-$ver"
|
||||
tag="$ver"
|
||||
branch="build-$ver"
|
||||
curbranch=`git branch | grep "*" | sed "s/* //"`
|
||||
timestamp=$(date)
|
||||
tokens="s/@@ver@@/$ver/g;s/\@@timestamp@@/$timestamp/g"
|
||||
remote="github"
|
||||
|
||||
echo "Updating Version Identifiers"
|
||||
|
||||
sed -E -e "s/\"version\": \"([0-9\.]+)\",/\"version\": \"$ver\",/g" -i "" component.json select2.jquery.json
|
||||
git add component.json
|
||||
git add select2.jquery.json
|
||||
git commit -m "modified version identifiers in descriptors for release $ver"
|
||||
git push
|
||||
|
||||
git branch "$branch"
|
||||
git checkout "$branch"
|
||||
|
||||
echo "Tokenizing..."
|
||||
|
||||
find . -name "$js" | xargs -I{} sed -e "$tokens" -i "" {}
|
||||
find . -name "$css" | xargs -I{} sed -e "$tokens" -i "" {}
|
||||
sed -e "s/latest/$ver/g" -i "" component.json
|
||||
|
||||
git add "$js"
|
||||
git add "$css"
|
||||
|
||||
echo "Minifying..."
|
||||
|
||||
echo "/*" > "$mini"
|
||||
cat LICENSE | sed "$tokens" >> "$mini"
|
||||
echo "*/" >> "$mini"
|
||||
|
||||
curl -s \
|
||||
--data-urlencode "js_code@$js" \
|
||||
http://marijnhaverbeke.nl/uglifyjs \
|
||||
>> "$mini"
|
||||
|
||||
git add "$mini"
|
||||
|
||||
git commit -m "release $ver"
|
||||
|
||||
echo "Tagging..."
|
||||
git tag -a "$tag" -m "tagged version $ver"
|
||||
git push "$remote" --tags
|
||||
|
||||
echo "Cleaning Up..."
|
||||
|
||||
git checkout "$curbranch"
|
||||
git branch -D "$branch"
|
||||
|
||||
echo "Done"
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,680 @@
|
|||
/*
|
||||
Version: 3.4.1 Timestamp: Thu Jun 27 18:02:10 PDT 2013
|
||||
*/
|
||||
.select2-container {
|
||||
margin: 0;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
/* inline-block for ie7 */
|
||||
zoom: 1;
|
||||
*display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.select2-container,
|
||||
.select2-drop,
|
||||
.select2-search,
|
||||
.select2-search input{
|
||||
/*
|
||||
Force border-box so that % widths fit the parent
|
||||
container without overlap because of margin/padding.
|
||||
|
||||
More Info : http://www.quirksmode.org/css/box.html
|
||||
*/
|
||||
-webkit-box-sizing: border-box; /* webkit */
|
||||
-khtml-box-sizing: border-box; /* konqueror */
|
||||
-moz-box-sizing: border-box; /* firefox */
|
||||
-ms-box-sizing: border-box; /* ie */
|
||||
box-sizing: border-box; /* css3 */
|
||||
}
|
||||
|
||||
.select2-container .select2-choice {
|
||||
display: block;
|
||||
height: 26px;
|
||||
padding: 0 0 0 8px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
border: 1px solid #aaa;
|
||||
white-space: nowrap;
|
||||
line-height: 26px;
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding;
|
||||
background-clip: padding-box;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
background-color: #fff;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white));
|
||||
background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%);
|
||||
background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%);
|
||||
background-image: -o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%);
|
||||
background-image: -ms-linear-gradient(top, #ffffff 0%, #eeeeee 50%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
|
||||
background-image: linear-gradient(top, #ffffff 0%, #eeeeee 50%);
|
||||
}
|
||||
|
||||
.select2-container.select2-drop-above .select2-choice {
|
||||
border-bottom-color: #aaa;
|
||||
|
||||
-webkit-border-radius:0 0 4px 4px;
|
||||
-moz-border-radius:0 0 4px 4px;
|
||||
border-radius:0 0 4px 4px;
|
||||
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.9, white));
|
||||
background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 90%);
|
||||
background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 90%);
|
||||
background-image: -o-linear-gradient(bottom, #eeeeee 0%, white 90%);
|
||||
background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 90%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 );
|
||||
background-image: linear-gradient(top, #eeeeee 0%,#ffffff 90%);
|
||||
}
|
||||
|
||||
.select2-container.select2-allowclear .select2-choice .select2-chosen {
|
||||
margin-right: 42px;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice > .select2-chosen {
|
||||
margin-right: 26px;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
-ms-text-overflow: ellipsis;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice abbr {
|
||||
display: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
top: 8px;
|
||||
|
||||
font-size: 1px;
|
||||
text-decoration: none;
|
||||
|
||||
border: 0;
|
||||
background: url('select2.png') right top no-repeat;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.select2-container.select2-allowclear .select2-choice abbr {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice abbr:hover {
|
||||
background-position: right -11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select2-drop-undermask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 9998;
|
||||
background-color: transparent;
|
||||
filter: alpha(opacity=0);
|
||||
}
|
||||
|
||||
.select2-drop-mask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 9998;
|
||||
/* styles required for IE to work */
|
||||
background-color: #fff;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
}
|
||||
|
||||
.select2-drop {
|
||||
width: 100%;
|
||||
margin-top: -1px;
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
top: 100%;
|
||||
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #aaa;
|
||||
border-top: 0;
|
||||
|
||||
-webkit-border-radius: 0 0 4px 4px;
|
||||
-moz-border-radius: 0 0 4px 4px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
|
||||
-webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
|
||||
-moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
|
||||
box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.select2-drop-auto-width {
|
||||
border-top: 1px solid #aaa;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.select2-drop-auto-width .select2-search {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.select2-drop.select2-drop-above {
|
||||
margin-top: 1px;
|
||||
border-top: 1px solid #aaa;
|
||||
border-bottom: 0;
|
||||
|
||||
-webkit-border-radius: 4px 4px 0 0;
|
||||
-moz-border-radius: 4px 4px 0 0;
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
-webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
|
||||
-moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
|
||||
box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.select2-drop-active {
|
||||
border: 1px solid #5897fb;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.select2-drop.select2-drop-above.select2-drop-active {
|
||||
border-top: 1px solid #5897fb;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice .select2-arrow {
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
border-left: 1px solid #aaa;
|
||||
-webkit-border-radius: 0 4px 4px 0;
|
||||
-moz-border-radius: 0 4px 4px 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding;
|
||||
background-clip: padding-box;
|
||||
|
||||
background: #ccc;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
|
||||
background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
|
||||
background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
|
||||
background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%);
|
||||
background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
|
||||
background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%);
|
||||
}
|
||||
|
||||
.select2-container .select2-choice .select2-arrow b {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('select2.png') no-repeat 0 1px;
|
||||
}
|
||||
|
||||
.select2-search {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
min-height: 26px;
|
||||
margin: 0;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
|
||||
position: relative;
|
||||
z-index: 10000;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.select2-search input {
|
||||
width: 100%;
|
||||
height: auto !important;
|
||||
min-height: 26px;
|
||||
padding: 4px 20px 4px 5px;
|
||||
margin: 0;
|
||||
|
||||
outline: 0;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
|
||||
border: 1px solid #aaa;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
|
||||
background: #fff url('select2.png') no-repeat 100% -22px;
|
||||
background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
|
||||
background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
|
||||
background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
|
||||
background: url('select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
|
||||
background: url('select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
|
||||
background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
|
||||
}
|
||||
|
||||
.select2-drop.select2-drop-above .select2-search input {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.select2-search input.select2-active {
|
||||
background: #fff url('select2-spinner.gif') no-repeat 100%;
|
||||
background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
|
||||
background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
|
||||
background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
|
||||
background: url('select2-spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
|
||||
background: url('select2-spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
|
||||
background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
|
||||
}
|
||||
|
||||
.select2-container-active .select2-choice,
|
||||
.select2-container-active .select2-choices {
|
||||
border: 1px solid #5897fb;
|
||||
outline: none;
|
||||
|
||||
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||
-moz-box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||
box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
.select2-dropdown-open .select2-choice {
|
||||
border-bottom-color: transparent;
|
||||
-webkit-box-shadow: 0 1px 0 #fff inset;
|
||||
-moz-box-shadow: 0 1px 0 #fff inset;
|
||||
box-shadow: 0 1px 0 #fff inset;
|
||||
|
||||
-webkit-border-bottom-left-radius: 0;
|
||||
-moz-border-radius-bottomleft: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
|
||||
-webkit-border-bottom-right-radius: 0;
|
||||
-moz-border-radius-bottomright: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
background-color: #eee;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee));
|
||||
background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%);
|
||||
background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%);
|
||||
background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 );
|
||||
background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%);
|
||||
}
|
||||
|
||||
.select2-dropdown-open.select2-drop-above .select2-choice,
|
||||
.select2-dropdown-open.select2-drop-above .select2-choices {
|
||||
border: 1px solid #5897fb;
|
||||
border-top-color: transparent;
|
||||
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, white), color-stop(0.5, #eeeeee));
|
||||
background-image: -webkit-linear-gradient(center top, white 0%, #eeeeee 50%);
|
||||
background-image: -moz-linear-gradient(center top, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: -ms-linear-gradient(bottom, #ffffff 0%,#eeeeee 50%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 );
|
||||
background-image: linear-gradient(bottom, #ffffff 0%,#eeeeee 50%);
|
||||
}
|
||||
|
||||
.select2-dropdown-open .select2-choice .select2-arrow {
|
||||
background: transparent;
|
||||
border-left: none;
|
||||
filter: none;
|
||||
}
|
||||
.select2-dropdown-open .select2-choice .select2-arrow b {
|
||||
background-position: -18px 1px;
|
||||
}
|
||||
|
||||
/* results */
|
||||
.select2-results {
|
||||
max-height: 200px;
|
||||
padding: 0 0 0 4px;
|
||||
margin: 4px 4px 4px 0;
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.select2-results ul.select2-result-sub {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
|
||||
.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
|
||||
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
|
||||
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
|
||||
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
|
||||
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
|
||||
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
|
||||
|
||||
.select2-results li {
|
||||
list-style: none;
|
||||
display: list-item;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.select2-results li.select2-result-with-children > .select2-result-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.select2-results .select2-result-label {
|
||||
padding: 3px 7px 4px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
|
||||
min-height: 1em;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.select2-results .select2-highlighted {
|
||||
background: #3875d7;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.select2-results li em {
|
||||
background: #feffde;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.select2-results .select2-highlighted em {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.select2-results .select2-highlighted ul {
|
||||
background: white;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
.select2-results .select2-no-results,
|
||||
.select2-results .select2-searching,
|
||||
.select2-results .select2-selection-limit {
|
||||
background: #f4f4f4;
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/*
|
||||
disabled look for disabled choices in the results dropdown
|
||||
*/
|
||||
.select2-results .select2-disabled.select2-highlighted {
|
||||
color: #666;
|
||||
background: #f4f4f4;
|
||||
display: list-item;
|
||||
cursor: default;
|
||||
}
|
||||
.select2-results .select2-disabled {
|
||||
background: #f4f4f4;
|
||||
display: list-item;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-results .select2-selected {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select2-more-results.select2-active {
|
||||
background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%;
|
||||
}
|
||||
|
||||
.select2-more-results {
|
||||
background: #f4f4f4;
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* disabled styles */
|
||||
|
||||
.select2-container.select2-container-disabled .select2-choice {
|
||||
background-color: #f4f4f4;
|
||||
background-image: none;
|
||||
border: 1px solid #ddd;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-container.select2-container-disabled .select2-choice .select2-arrow {
|
||||
background-color: #f4f4f4;
|
||||
background-image: none;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.select2-container.select2-container-disabled .select2-choice abbr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* multiselect */
|
||||
|
||||
.select2-container-multi .select2-choices {
|
||||
height: auto !important;
|
||||
height: 1%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
|
||||
border: 1px solid #aaa;
|
||||
cursor: text;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: #fff;
|
||||
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||
background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||
background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||
background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||
}
|
||||
|
||||
.select2-locked {
|
||||
padding: 3px 5px 3px 5px !important;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices {
|
||||
min-height: 26px;
|
||||
}
|
||||
|
||||
.select2-container-multi.select2-container-active .select2-choices {
|
||||
border: 1px solid #5897fb;
|
||||
outline: none;
|
||||
|
||||
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||
-moz-box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||
box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||
}
|
||||
.select2-container-multi .select2-choices li {
|
||||
float: left;
|
||||
list-style: none;
|
||||
}
|
||||
.select2-container-multi .select2-choices .select2-search-field {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices .select2-search-field input {
|
||||
padding: 5px;
|
||||
margin: 1px 0;
|
||||
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
color: #666;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices .select2-search-field input.select2-active {
|
||||
background: #fff url('select2-spinner.gif') no-repeat 100% !important;
|
||||
}
|
||||
|
||||
.select2-default {
|
||||
color: #999 !important;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices .select2-search-choice {
|
||||
padding: 3px 5px 3px 18px;
|
||||
margin: 3px 0 3px 5px;
|
||||
position: relative;
|
||||
|
||||
line-height: 13px;
|
||||
color: #333;
|
||||
cursor: default;
|
||||
border: 1px solid #aaaaaa;
|
||||
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
|
||||
-webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||
-moz-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||
box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding;
|
||||
background-clip: padding-box;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
background-color: #e4e4e4;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0 );
|
||||
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
|
||||
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||
background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||
background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||
background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||
}
|
||||
.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
|
||||
cursor: default;
|
||||
}
|
||||
.select2-container-multi .select2-choices .select2-search-choice-focus {
|
||||
background: #d4d4d4;
|
||||
}
|
||||
|
||||
.select2-search-choice-close {
|
||||
display: block;
|
||||
width: 12px;
|
||||
height: 13px;
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: 4px;
|
||||
|
||||
font-size: 1px;
|
||||
outline: none;
|
||||
background: url('select2.png') right top no-repeat;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-search-choice-close {
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
|
||||
background-position: right -11px;
|
||||
}
|
||||
.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
|
||||
background-position: right -11px;
|
||||
}
|
||||
|
||||
/* disabled styles */
|
||||
.select2-container-multi.select2-container-disabled .select2-choices{
|
||||
background-color: #f4f4f4;
|
||||
background-image: none;
|
||||
border: 1px solid #ddd;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
|
||||
padding: 3px 5px 3px 5px;
|
||||
border: 1px solid #ddd;
|
||||
background-image: none;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
|
||||
background:none;
|
||||
}
|
||||
/* end multiselect */
|
||||
|
||||
|
||||
.select2-result-selectable .select2-match,
|
||||
.select2-result-unselectable .select2-match {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.select2-offscreen, .select2-offscreen:focus {
|
||||
clip: rect(0 0 0 0);
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
outline: 0;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.select2-display-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select2-measure-scrollbar {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: scroll;
|
||||
}
|
||||
/* Retina-ize icons */
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
|
||||
.select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b {
|
||||
background-image: url('select2x2.png') !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-size: 60px 40px !important;
|
||||
}
|
||||
.select2-search input {
|
||||
background-position: 100% -21px !important;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "select2",
|
||||
"title": "Select2",
|
||||
"description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.",
|
||||
"keywords": [
|
||||
"select",
|
||||
"autocomplete",
|
||||
"typeahead",
|
||||
"dropdown",
|
||||
"multiselect",
|
||||
"tag",
|
||||
"tagging"
|
||||
],
|
||||
"version": "3.4.1",
|
||||
"author": {
|
||||
"name": "Igor Vaynberg",
|
||||
"url": "https://github.com/ivaynberg"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "Apache",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"type": "GPL v2",
|
||||
"url": "http://www.gnu.org/licenses/gpl-2.0.html"
|
||||
}
|
||||
],
|
||||
"bugs": "https://github.com/ivaynberg/select2/issues",
|
||||
"homepage": "http://ivaynberg.github.com/select2",
|
||||
"docs": "http://ivaynberg.github.com/select2/",
|
||||
"download": "https://github.com/ivaynberg/select2/tags",
|
||||
"dependencies": {
|
||||
"jquery": ">=1.7.1"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
22
examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/select2-3.4.1/select2.min.js
vendored
Normal file
22
examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/select2-3.4.1/select2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 613 B |
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Arabic translation.
|
||||
*
|
||||
* Author: Your Name <amedhat3@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "لا توجد نتائج"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "من فضلك أدخل " + n + " حروف أكثر"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "من فضلك أحذف " + n + " حروف"; },
|
||||
formatSelectionTooBig: function (limit) { return "يمكنك ان تختار " + limit + " أختيارات فقط"; },
|
||||
formatLoadMore: function (pageNumber) { return "تحمل المذيد من النتائج ..."; },
|
||||
formatSearching: function () { return "جاري البحث ..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Catalan translation.
|
||||
*
|
||||
* Author: David Planella <david.planella@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "No s'ha trobat cap coincidència"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduïu " + n + " caràcter" + (n == 1 ? "" : "s") + " més"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Introduïu " + n + " caràcter" + (n == 1? "" : "s") + "menys"; },
|
||||
formatSelectionTooBig: function (limit) { return "Només podeu seleccionar " + limit + " element" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "S'estan carregant més resultats..."; },
|
||||
formatSearching: function () { return "S'està cercant..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Select2 Czech translation.
|
||||
*
|
||||
* Author: Michal Marek <ahoj@michal-marek.cz>
|
||||
* Author - sklonovani: David Vallner <david@vallner.net>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
// use text for the numbers 2 through 4
|
||||
var smallNumbers = {
|
||||
2: function(masc) { return (masc ? "dva" : "dvě"); },
|
||||
3: function() { return "tři"; },
|
||||
4: function() { return "čtyři"; }
|
||||
}
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nenalezeny žádné položky"; },
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
if (n == 1) {
|
||||
return "Prosím zadejte ještě jeden znak";
|
||||
} else if (n <= 4) {
|
||||
return "Prosím zadejte ještě další "+smallNumbers[n](true)+" znaky";
|
||||
} else {
|
||||
return "Prosím zadejte ještě dalších "+n+" znaků";
|
||||
}
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
if (n == 1) {
|
||||
return "Prosím zadejte o jeden znak méně";
|
||||
} else if (n <= 4) {
|
||||
return "Prosím zadejte o "+smallNumbers[n](true)+" znaky méně";
|
||||
} else {
|
||||
return "Prosím zadejte o "+n+" znaků méně";
|
||||
}
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
if (limit == 1) {
|
||||
return "Můžete zvolit jen jednu položku";
|
||||
} else if (limit <= 4) {
|
||||
return "Můžete zvolit maximálně "+smallNumbers[limit](false)+" položky";
|
||||
} else {
|
||||
return "Můžete zvolit maximálně "+limit+" položek";
|
||||
}
|
||||
},
|
||||
formatLoadMore: function (pageNumber) { return "Načítají se další výsledky..."; },
|
||||
formatSearching: function () { return "Vyhledávání..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Danish translation.
|
||||
*
|
||||
* Author: Anders Jenbo <anders@jenbo.dk>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Ingen resultater fundet"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Angiv venligst " + n + " tegn mere"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Angiv venligst " + n + " tegn mindre"; },
|
||||
formatSelectionTooBig: function (limit) { return "Du kan kun vælge " + limit + " emne" + (limit === 1 ? "" : "r"); },
|
||||
formatLoadMore: function (pageNumber) { return "Indlæser flere resultater…"; },
|
||||
formatSearching: function () { return "Søger…"; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 German translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Keine Übereinstimmungen gefunden"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Bitte " + n + " Zeichen mehr eingeben"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Bitte " + n + " Zeichen weniger eingeben"; },
|
||||
formatSelectionTooBig: function (limit) { return "Sie können nur " + limit + " Eintr" + (limit === 1 ? "ag" : "äge") + " auswählen"; },
|
||||
formatLoadMore: function (pageNumber) { return "Lade mehr Ergebnisse..."; },
|
||||
formatSearching: function () { return "Suche..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 <Language> translation.
|
||||
*
|
||||
* Author: Your Name <your@email>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Δεν βρέθηκαν αποτελέσματα"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Παρακαλούμε εισάγετε " + n + " περισσότερους χαρακτήρες" + (n == 1 ? "" : "s"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Παρακαλούμε διαγράψτε " + n + " χαρακτήρες" + (n == 1 ? "" : "s"); },
|
||||
formatSelectionTooBig: function (limit) { return "Μπορείτε να επιλέξετε μόνο " + limit + " αντικείμενο" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Φόρτωση περισσότερων..."; },
|
||||
formatSearching: function () { return "Αναζήτηση..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 <Language> translation.
|
||||
*
|
||||
* Author: Your Name <your@email>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "No matches found"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1 ? "" : "s"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); },
|
||||
formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Loading more results..."; },
|
||||
formatSearching: function () { return "Searching..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Spanish translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "No se encontraron resultados"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Por favor adicione " + n + " caracter" + (n == 1? "" : "es"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Por favor elimine " + n + " caracter" + (n == 1? "" : "es"); },
|
||||
formatSelectionTooBig: function (limit) { return "Solo puede seleccionar " + limit + " elemento" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Cargando más resultados..."; },
|
||||
formatSearching: function () { return "Buscando..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Estonian translation.
|
||||
*
|
||||
* Author: Kuldar Kalvik <kuldar@kalvik.ee>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Tulemused puuduvad"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Sisesta " + n + " täht" + (n == 1 ? "" : "e") + " rohkem"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Sisesta " + n + " täht" + (n == 1? "" : "e") + " vähem"; },
|
||||
formatSelectionTooBig: function (limit) { return "Saad vaid " + limit + " tulemus" + (limit == 1 ? "e" : "t") + " valida"; },
|
||||
formatLoadMore: function (pageNumber) { return "Laen tulemusi.."; },
|
||||
formatSearching: function () { return "Otsin.."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Select2 Basque translation.
|
||||
*
|
||||
* Author: Julen Ruiz Aizpuru <julenx at gmail dot com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () {
|
||||
return "Ez da bat datorrenik aurkitu";
|
||||
},
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
if (n === 1) {
|
||||
return "Idatzi karaktere bat gehiago";
|
||||
} else {
|
||||
return "Idatzi " + n + " karaktere gehiago";
|
||||
}
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
if (n === 1) {
|
||||
return "Idatzi karaktere bat gutxiago";
|
||||
} else {
|
||||
return "Idatzi " + n + " karaktere gutxiago";
|
||||
}
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
if (limit === 1 ) {
|
||||
return "Elementu bakarra hauta dezakezu";
|
||||
} else {
|
||||
return limit + " elementu hauta ditzakezu soilik";
|
||||
}
|
||||
},
|
||||
formatLoadMore: function (pageNumber) {
|
||||
return "Emaitza gehiago kargatzen...";
|
||||
},
|
||||
formatSearching: function () {
|
||||
return "Bilatzen...";
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Select2 Finnish translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () {
|
||||
return "Ei tuloksia";
|
||||
},
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
return "Ole hyvä ja anna " + n + " merkkiä lisää.";
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
return "Ole hyvä ja annar " + n + " merkkiä vähemmän.";
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
return "Voit valita ainoastaan " + limit + " kpl";
|
||||
},
|
||||
formatLoadMore: function (pageNumber) {
|
||||
return "Ladataan lisää tuloksia...";
|
||||
},
|
||||
formatSearching: function () {
|
||||
return "Etsitään...";
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 French translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Aucun résultat trouvé"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Merci de saisir " + n + " caractère" + (n == 1? "" : "s") + " de plus"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Merci de supprimer " + n + " caractère" + (n == 1? "" : "s"); },
|
||||
formatSelectionTooBig: function (limit) { return "Vous pouvez seulement sélectionner " + limit + " élément" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Chargement de résultats supplémentaires..."; },
|
||||
formatSearching: function () { return "Recherche en cours..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Select2 Galician translation
|
||||
*
|
||||
* Author: Leandro Regueiro <leandro.regueiro@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () {
|
||||
return "Non se atoparon resultados";
|
||||
},
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
if (n === 1) {
|
||||
return "Engada un carácter";
|
||||
} else {
|
||||
return "Engada " + n + " caracteres";
|
||||
}
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
if (n === 1) {
|
||||
return "Elimine un carácter";
|
||||
} else {
|
||||
return "Elimine " + n + " caracteres";
|
||||
}
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
if (limit === 1 ) {
|
||||
return "Só pode seleccionar un elemento";
|
||||
} else {
|
||||
return "Só pode seleccionar " + limit + " elementos";
|
||||
}
|
||||
},
|
||||
formatLoadMore: function (pageNumber) {
|
||||
return "Cargando máis resultados...";
|
||||
},
|
||||
formatSearching: function () {
|
||||
return "Buscando...";
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Hebrew translation.
|
||||
*
|
||||
* Author: Yakir Sitbon <http://www.yakirs.net/>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "לא נמצאו התאמות"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "נא להזין עוד " + n + " תווים נוספים"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "נא להזין פחות " + n + " תווים"; },
|
||||
formatSelectionTooBig: function (limit) { return "ניתן לבחור " + limit + " פריטים"; },
|
||||
formatLoadMore: function (pageNumber) { return "טוען תוצאות נוספות..."; },
|
||||
formatSearching: function () { return "מחפש..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Select2 Croatian translation.
|
||||
*
|
||||
* Author: Edi Modrić <edi.modric@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
var specialNumbers = {
|
||||
1: function(n) { return (n % 100 != 11 ? "znak" : "znakova"); },
|
||||
2: function(n) { return (n % 100 != 12 ? "znaka" : "znakova"); },
|
||||
3: function(n) { return (n % 100 != 13 ? "znaka" : "znakova"); },
|
||||
4: function(n) { return (n % 100 != 14 ? "znaka" : "znakova"); }
|
||||
};
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nema rezultata"; },
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
var nMod10 = n % 10;
|
||||
|
||||
if (nMod10 > 0 && nMod10 < 5) {
|
||||
return "Unesite još " + n + " " + specialNumbers[nMod10](n);
|
||||
}
|
||||
|
||||
return "Unesite još " + n + " znakova";
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
var nMod10 = n % 10;
|
||||
|
||||
if (nMod10 > 0 && nMod10 < 5) {
|
||||
return "Unesite " + n + " " + specialNumbers[nMod10](n) + " manje";
|
||||
}
|
||||
|
||||
return "Unesite " + n + " znakova manje";
|
||||
},
|
||||
formatSelectionTooBig: function (limit) { return "Maksimalan broj odabranih stavki je " + limit; },
|
||||
formatLoadMore: function (pageNumber) { return "Učitavanje rezultata..."; },
|
||||
formatSearching: function () { return "Pretraga..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Hungarian translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nincs találat."; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Túl rövid. Még " + n + " karakter hiányzik."; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Túl hosszú. " + n + " kerekterrel több mint kellene."; },
|
||||
formatSelectionTooBig: function (limit) { return "Csak " + limit + " elemet lehet kiválasztani."; },
|
||||
formatLoadMore: function (pageNumber) { return "Töltés..."; },
|
||||
formatSearching: function () { return "Keresés..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Indonesian translation.
|
||||
*
|
||||
* Author: Ibrahim Yusuf <ibrahim7usuf@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Tidak ada data yang sesuai"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Masukkan " + n + " huruf lagi" + (n == 1 ? "" : "s"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Hapus " + n + " huruf" + (n == 1 ? "" : "s"); },
|
||||
formatSelectionTooBig: function (limit) { return "Anda hanya dapat memilih " + limit + " pilihan" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Mengambil data..."; },
|
||||
formatSearching: function () { return "Mencari..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Select2 Icelandic translation.
|
||||
*
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Ekkert fannst"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vinsamlegast skrifið " + n + " staf" + (n == 1 ? "" : "i") + " í viðbót"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vinsamlegast styttið texta um " + n + " staf" + (n == 1 ? "" : "i"); },
|
||||
formatSelectionTooBig: function (limit) { return "Þú getur aðeins valið " + limit + " atriði"; },
|
||||
formatLoadMore: function (pageNumber) { return "Sæki fleiri niðurstöður..."; },
|
||||
formatSearching: function () { return "Leita..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Italian translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nessuna corrispondenza trovata"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Inserisci ancora " + n + " caratter" + (n == 1? "e" : "i"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Inserisci " + n + " caratter" + (n == 1? "e" : "i") + " in meno"; },
|
||||
formatSelectionTooBig: function (limit) { return "Puoi selezionare solo " + limit + " element" + (limit == 1 ? "o" : "i"); },
|
||||
formatLoadMore: function (pageNumber) { return "Caricamento in corso..."; },
|
||||
formatSearching: function () { return "Ricerca..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Japanese translation.
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "該当なし"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "後" + n + "文字入れてください"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "検索文字列が" + n + "文字長すぎます"; },
|
||||
formatSelectionTooBig: function (limit) { return "最多で" + limit + "項目までしか選択できません"; },
|
||||
formatLoadMore: function (pageNumber) { return "読込中・・・"; },
|
||||
formatSearching: function () { return "検索中・・・"; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 <Language> translation.
|
||||
*
|
||||
* Author: Swen Mun <longfinfunnel@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "결과 없음"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "너무 짧습니다. "+n+"글자 더 입력해주세요."; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "너무 깁니다. "+n+"글자 지워주세요."; },
|
||||
formatSelectionTooBig: function (limit) { return "최대 "+limit+"개까지만 선택하실 수 있습니다."; },
|
||||
formatLoadMore: function (pageNumber) { return "불러오는 중…"; },
|
||||
formatSearching: function () { return "검색 중…"; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Select2 lithuanian translation.
|
||||
*
|
||||
* Author: CRONUS Karmalakas <cronus dot karmalakas at gmail dot com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Atitikmenų nerasta"; },
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length,
|
||||
suffix = (n % 10 == 1) && (n % 100 != 11) ? 'į' : (((n % 10 >= 2) && ((n % 100 < 10) || (n % 100 >= 20))) ? 'ius' : 'ių');
|
||||
return "Įrašykite dar " + n + " simbol" + suffix;
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max,
|
||||
suffix = (n % 10 == 1) && (n % 100 != 11) ? 'į' : (((n % 10 >= 2) && ((n % 100 < 10) || (n % 100 >= 20))) ? 'ius' : 'ių');
|
||||
return "Pašalinkite " + n + " simbol" + suffix;
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
var n = limit,
|
||||
suffix = (n % 10 == 1) && (n % 100 != 11) ? 'ą' : (((n % 10 >= 2) && ((n % 100 < 10) || (n % 100 >= 20))) ? 'us' : 'ų');
|
||||
return "Jūs galite pasirinkti tik " + limit + " element" + suffix;
|
||||
},
|
||||
formatLoadMore: function (pageNumber) { return "Kraunama daugiau rezultatų..."; },
|
||||
formatSearching: function () { return "Ieškoma..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Select2 Latvian translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Sakritību nav"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Lūdzu ievadiet vēl " + n + " simbol" + (n == 11 ? "us" : (/^\d*[1]$/im.test(n)? "u" : "us")); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Lūdzu ievadiet par " + n + " simbol" + (n == 11 ? "iem" : (/^\d*[1]$/im.test(n)? "u" : "iem")) + " mazāk"; },
|
||||
formatSelectionTooBig: function (limit) { return "Jūs varat izvēlēties ne vairāk kā " + limit + " element" + (limit == 11 ? "us" : (/^\d*[1]$/im.test(limit)? "u" : "us")); },
|
||||
formatLoadMore: function (pageNumber) { return "Datu ielāde..."; },
|
||||
formatSearching: function () { return "Meklēšana..."; }
|
||||
});
|
||||
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Macedonian translation.
|
||||
*
|
||||
* Author: Marko Aleksic <psybaron@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Нема пронајдено совпаѓања"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Ве молиме внесете уште " + n + " карактер" + (n == 1 ? "" : "и"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Ве молиме внесете " + n + " помалку карактер" + (n == 1? "" : "и"); },
|
||||
formatSelectionTooBig: function (limit) { return "Можете да изберете само " + limit + " ставк" + (limit == 1 ? "а" : "и"); },
|
||||
formatLoadMore: function (pageNumber) { return "Вчитување резултати..."; },
|
||||
formatSearching: function () { return "Пребарување..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Dutch translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Geen resultaten gevonden"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " meer in"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " minder in"; },
|
||||
formatSelectionTooBig: function (limit) { return "Maximaal " + limit + " item" + (limit == 1 ? "" : "s") + " toegestaan"; },
|
||||
formatLoadMore: function (pageNumber) { return "Meer resultaten laden..."; },
|
||||
formatSearching: function () { return "Zoeken..."; },
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Select2 Norwegian translation.
|
||||
*
|
||||
* Author: Torgeir Veimo <torgeir.veimo@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Ingen treff"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vennligst skriv inn " + n + (n>1 ? " flere tegn" : " tegn til"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vennligst fjern " + n + " tegn"; },
|
||||
formatSelectionTooBig: function (limit) { return "Du kan velge maks " + limit + " elementer"; },
|
||||
formatLoadMore: function (pageNumber) { return "Laster flere resultater..."; },
|
||||
formatSearching: function () { return "Søker..."; }
|
||||
});
|
||||
})(jQuery);
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Select2 Polish translation.
|
||||
*
|
||||
* Author: Jan Kondratowicz <jan@kondratowicz.pl>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
var pl_suffix = function(n) {
|
||||
if(n == 1) return "";
|
||||
if((n%100 > 1 && n%100 < 5) || (n%100 > 20 && n%10 > 1 && n%10 < 5)) return "i";
|
||||
return "ów";
|
||||
};
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () {
|
||||
return "Brak wyników.";
|
||||
},
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
return "Wpisz jeszcze " + n + " znak" + pl_suffix(n) + ".";
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
return "Wpisana fraza jest za długa o " + n + " znak" + pl_suffix(n) + ".";
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
return "Możesz zaznaczyć najwyżej " + limit + " element" + pl_suffix(limit) + ".";
|
||||
},
|
||||
formatLoadMore: function (pageNumber) {
|
||||
return "Ładowanie wyników...";
|
||||
},
|
||||
formatSearching: function () {
|
||||
return "Szukanie...";
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Brazilian Portuguese translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nenhum resultado encontrado"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Informe " + n + " caracter" + (n == 1? "" : "es"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " caracter" + (n == 1? "" : "es"); },
|
||||
formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Carregando mais resultados..."; },
|
||||
formatSearching: function () { return "Buscando..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Portuguese (Portugal) translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nenhum resultado encontrado"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduza " + n + " caracter" + (n == 1 ? "" : "es"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " caracter" + (n == 1 ? "" : "es"); },
|
||||
formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "A carregar mais resultados..."; },
|
||||
formatSearching: function () { return "A pesquisar..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Romanian translation.
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nu a fost găsit nimic"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vă rugăm să introduceți incă " + n + " caracter" + (n == 1 ? "" : "e"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vă rugăm să introduceți mai puțin de " + n + " caracter" + (n == 1? "" : "e"); },
|
||||
formatSelectionTooBig: function (limit) { return "Aveți voie să selectați cel mult " + limit + " element" + (limit == 1 ? "" : "e"); },
|
||||
formatLoadMore: function (pageNumber) { return "Se încarcă..."; },
|
||||
formatSearching: function () { return "Căutare..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Select2 Russian translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Совпадений не найдено"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Пожалуйста, введите еще " + n + " символ" + (n == 1 ? "" : ((n > 1)&&(n < 5) ? "а" : "ов")); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Пожалуйста, введите на " + n + " символ" + (n == 1 ? "" : ((n > 1)&&(n < 5)? "а" : "ов")) + " меньше"; },
|
||||
formatSelectionTooBig: function (limit) { return "Вы можете выбрать не более " + limit + " элемент" + (limit == 1 ? "а" : "ов"); },
|
||||
formatLoadMore: function (pageNumber) { return "Загрузка данных..."; },
|
||||
formatSearching: function () { return "Поиск..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Select2 Slovak translation.
|
||||
*
|
||||
* Author: David Vallner <david@vallner.net>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
// use text for the numbers 2 through 4
|
||||
var smallNumbers = {
|
||||
2: function(masc) { return (masc ? "dva" : "dve"); },
|
||||
3: function() { return "tri"; },
|
||||
4: function() { return "štyri"; }
|
||||
}
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Nenašli sa žiadne položky"; },
|
||||
formatInputTooShort: function (input, min) {
|
||||
var n = min - input.length;
|
||||
if (n == 1) {
|
||||
return "Prosím zadajte ešte jeden znak";
|
||||
} else if (n <= 4) {
|
||||
return "Prosím zadajte ešte ďalšie "+smallNumbers[n](true)+" znaky";
|
||||
} else {
|
||||
return "Prosím zadajte ešte ďalších "+n+" znakov";
|
||||
}
|
||||
},
|
||||
formatInputTooLong: function (input, max) {
|
||||
var n = input.length - max;
|
||||
if (n == 1) {
|
||||
return "Prosím zadajte o jeden znak menej";
|
||||
} else if (n <= 4) {
|
||||
return "Prosím zadajte o "+smallNumbers[n](true)+" znaky menej";
|
||||
} else {
|
||||
return "Prosím zadajte o "+n+" znakov menej";
|
||||
}
|
||||
},
|
||||
formatSelectionTooBig: function (limit) {
|
||||
if (limit == 1) {
|
||||
return "Môžete zvoliť len jednu položku";
|
||||
} else if (limit <= 4) {
|
||||
return "Môžete zvoliť najviac "+smallNumbers[limit](false)+" položky";
|
||||
} else {
|
||||
return "Môžete zvoliť najviac "+limit+" položiek";
|
||||
}
|
||||
},
|
||||
formatLoadMore: function (pageNumber) { return "Načítavajú sa ďalšie výsledky..."; },
|
||||
formatSearching: function () { return "Vyhľadávanie..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Swedish translation.
|
||||
*
|
||||
* Author: Jens Rantil <jens.rantil@telavox.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Inga träffar"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Var god skriv in " + n + (n>1 ? " till tecken" : " tecken till"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Var god sudda ut " + n + " tecken"; },
|
||||
formatSelectionTooBig: function (limit) { return "Du kan max välja " + limit + " element"; },
|
||||
formatLoadMore: function (pageNumber) { return "Laddar fler resultat..."; },
|
||||
formatSearching: function () { return "Söker..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 Turkish translation.
|
||||
*
|
||||
* Author: Salim KAYABAŞI <salim.kayabasi@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Sonuç bulunamadı"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "En az " + n + " karakter daha girmelisiniz"; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return n + " karakter azaltmalısınız"; },
|
||||
formatSelectionTooBig: function (limit) { return "Sadece " + limit + " seçim yapabilirsiniz"; },
|
||||
formatLoadMore: function (pageNumber) { return "Daha fazla..."; },
|
||||
formatSearching: function () { return "Aranıyor..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Select2 <Language> translation.
|
||||
*
|
||||
* Author: bigmihail <bigmihail@bigmir.net>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Нічого не знайдено"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length, s = ["", "и", "ів"], p = [2,0,1,1,1,2]; return "Введіть буль ласка ще " + n + " символ" + s[ (n%100>4 && n%100<=20)? 2 : p[Math.min(n%10, 5)] ]; },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max, s = ["", "и", "ів"], p = [2,0,1,1,1,2]; return "Введіть буль ласка на " + n + " символ" + s[ (n%100>4 && n%100<=20)? 2 : p[Math.min(n%10, 5)] ] + " менше"; },
|
||||
formatSelectionTooBig: function (limit) {var s = ["", "и", "ів"], p = [2,0,1,1,1,2]; return "Ви можете вибрати лише " + limit + " елемент" + s[ (limit%100>4 && limit%100<=20)? 2 : p[Math.min(limit%10, 5)] ]; },
|
||||
formatLoadMore: function (pageNumber) { return "Завантаження даних..."; },
|
||||
formatSearching: function () { return "Пошук..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Select2 Vietnamese translation.
|
||||
*
|
||||
* Author: Long Nguyen <olragon@gmail.com>
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "Không tìm thấy kết quả"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vui lòng nhập nhiều hơn " + n + " ký tự" + (n == 1 ? "" : "s"); },
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vui lòng nhập ít hơn " + n + " ký tự" + (n == 1? "" : "s"); },
|
||||
formatSelectionTooBig: function (limit) { return "Chỉ có thể chọn được " + limit + " tùy chọn" + (limit == 1 ? "" : "s"); },
|
||||
formatLoadMore: function (pageNumber) { return "Đang lấy thêm kết quả..."; },
|
||||
formatSearching: function () { return "Đang tìm..."; }
|
||||
});
|
||||
})(jQuery);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Select2 Chinese translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "没有找到匹配项"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "请再输入" + n + "个字符";},
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "请删掉" + n + "个字符";},
|
||||
formatSelectionTooBig: function (limit) { return "你只能选择最多" + limit + "项"; },
|
||||
formatLoadMore: function (pageNumber) { return "加载结果中..."; },
|
||||
formatSearching: function () { return "搜索中..."; }
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Select2 Traditional Chinese translation
|
||||
*/
|
||||
(function ($) {
|
||||
"use strict";
|
||||
$.extend($.fn.select2.defaults, {
|
||||
formatNoMatches: function () { return "沒有找到相符的項目"; },
|
||||
formatInputTooShort: function (input, min) { var n = min - input.length; return "請再輸入" + n + "個字元";},
|
||||
formatInputTooLong: function (input, max) { var n = input.length - max; return "請刪掉" + n + "個字元";},
|
||||
formatSelectionTooBig: function (limit) { return "你只能選擇最多" + limit + "項"; },
|
||||
formatLoadMore: function (pageNumber) { return "載入中..."; },
|
||||
formatSearching: function () { return "搜尋中..."; }
|
||||
});
|
||||
})(jQuery);
|
Binary file not shown.
After Width: | Height: | Size: 845 B |
|
@ -16,10 +16,10 @@
|
|||
</ul>
|
||||
<hr/>
|
||||
<div>
|
||||
<a href="#/realms/{{realm.id}}">Back to realm management...</a>
|
||||
<a href="#/create/application/{{realm.id}}">New Application...</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#/create/application/{{realm.id}}">New Application...</a>
|
||||
<a href="#/realms/{{realm.id}}">Back to realm management...</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
|
@ -5,9 +5,9 @@
|
|||
<nav id="global-nav">
|
||||
<div data-ng-controller="RealmDropdownCtrl" >
|
||||
<ul class="nav pull-left" data-ng-show="showNav()">
|
||||
<li class="divider-vertical-right"><a href="#/realms/{{currentRealmId}}">Realm</a></li>
|
||||
<li class="divider-vertical-right"><a href="#/realms/{{current.realm.id}}">Realm</a></li>
|
||||
</ul>
|
||||
<select class="nav pull-left" data-ng-show="showNav()" ng-change="changeRealm()" ng-model="current.realm" ng-options="name for (id, name) in current.realms">
|
||||
<select class="nav pull-left" data-ng-show="showNav()" ng-change="changeRealm()" ng-model="current.realm" ng-options="r.realm for r in current.realms">
|
||||
</select>
|
||||
<!-- <select class="nav pull-left" ng-options="r.name for r in current.realms"></select> -->
|
||||
</div>
|
||||
|
|
|
@ -17,39 +17,74 @@
|
|||
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<fieldset>
|
||||
<legend>Settings</legend>
|
||||
|
||||
<div data-kc-input>
|
||||
<label>Name</label>
|
||||
<input class="input-xlarge" type="text" name="name" data-ng-model="realm.name" autofocus
|
||||
<div class="control-group">
|
||||
<label for="realmForm-name" class="control-label">Name <span class="required">*</span></label>
|
||||
|
||||
<div class="controls">
|
||||
<input class="input-xlarge" type="text" name="name" data-ng-model="realm.realm" autofocus
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div data-kc-input>
|
||||
<label>Enabled</label>
|
||||
<input class="input-xlarge" type="checkbox" name="enabled" data-ng-model="realm.enabled">
|
||||
</div>
|
||||
|
||||
<div data-kc-input>
|
||||
<label>Social login</label>
|
||||
<input class="input-xlarge" type="checkbox" name="social" data-ng-model="realm.social">
|
||||
</div>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Enabled</label>
|
||||
|
||||
<div data-kc-input>
|
||||
<label>Require SSL</label>
|
||||
<input class="input-xlarge" type="checkbox" name="requireSsl" data-ng-model="realm.requireSsl">
|
||||
<div class="controls">
|
||||
<input class="input-xlarge" type="checkbox" name="enabled"
|
||||
data-ng-model="realm.enabled">
|
||||
</div>
|
||||
|
||||
<div data-kc-input>
|
||||
<label>Cookie login allowed</label>
|
||||
<input class="input-xlarge" type="checkbox" name="cookieLoginAllowed" data-ng-model="realm.cookieLoginAllowed">
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Social login</label>
|
||||
|
||||
<div data-kc-input>
|
||||
<label>User registration</label>
|
||||
<div class="controls">
|
||||
<input class="input-xlarge" type="checkbox" name="social"
|
||||
data-ng-model="realm.social">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Require SSL</label>
|
||||
|
||||
<div class="controls">
|
||||
<input class="input-xlarge" type="checkbox" name="requireSsl"
|
||||
data-ng-model="realm.requireSsl">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Cookie login allowed</label>
|
||||
|
||||
<div class="controls">
|
||||
<input class="input-xlarge" type="checkbox" name="cookieLoginAllowed"
|
||||
data-ng-model="realm.cookieLoginAllowed">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<label class="control-label">User registration</label>
|
||||
|
||||
<div class="controls">
|
||||
<input class="input-xlarge" type="checkbox" name="userRegistration"
|
||||
data-ng-model="realm.userRegistration">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="realmForm-tokenLifespan" class="control-label">Token lifespan</label>
|
||||
|
@ -74,13 +109,35 @@
|
|||
data-ng-model="realm.accessCodeLifespan">
|
||||
<select style="width: auto;" name="accessCodeLifespanUnit"
|
||||
data-ng-model="realm.accessCodeLifespanUnit">
|
||||
<option value="SECONDS" data-ng-selected="!realm.accessCodeLifespanUnit">Seconds</option>
|
||||
<option value="SECONDS" data-ng-selected="!realm.accessCodeLifespanUnit">Seconds
|
||||
</option>
|
||||
<option value="MINUTES">Minutes</option>
|
||||
<option value="HOURS">Hours</option>
|
||||
<option value="DAYS">Days</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Required User Credentials</label>
|
||||
|
||||
<div class="controls">
|
||||
<input style="width:250px" type="text" ui-select2="userCredentialOptions" ng-model="realm.requiredCredentials">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Required Application Credentials</label>
|
||||
|
||||
<div class="controls">
|
||||
<input style="width:250px" type="text" ui-select2="userCredentialOptions" ng-model="realm.requiredApplicationCredentials">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Required OAuth Credentials</label>
|
||||
|
||||
<div class="controls">
|
||||
<input style="width:250px" type="text" ui-select2="userCredentialOptions" ng-model="realm.requiredOAuthClientCredentials">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="form-actions" data-ng-show="createRealm">
|
||||
<button type="submit" data-ng-click="save()" class="btn btn-primary" data-ng-show="changed">Save
|
||||
|
@ -96,7 +153,6 @@
|
|||
</button>
|
||||
<button type="submit" data-ng-click="reset()" class="btn" data-ng-show="changed">Clear changes
|
||||
</button>
|
||||
<a href="#/realms" data-ng-hide="changed">View realms »</a>
|
||||
<button type="submit" data-ng-click="remove()" class="btn btn-danger" data-ng-hide="changed">
|
||||
Delete
|
||||
</button>
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
<div data-ng-hide="createRealm">
|
||||
<nav id="local-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li data-ng-class="!path[2] && 'active'"><a href="#/realms/{{realm.id}}">Realm Settings</a></li>
|
||||
<li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{realm.id}}/roles">Realm Roles</a>
|
||||
<ul class="sub-items">
|
||||
<li data-ng-class="path[0] == 'create' && path[1] == 'role' && 'active'"><a
|
||||
href="#/create/role/{{realm.id}}">Add Role</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li data-ng-class="path[2] == 'users' && 'active'"><a href="#/realms/{{realm.id}}/users">Realm Users</a>
|
||||
<li data-ng-class="path[2] == 'users' && 'active'"><a href="#/realms/{{realm.id}}/users">Users</a>
|
||||
<ul class="sub-items">
|
||||
<li data-ng-class="path[0] == 'create' && path[1] == 'user' && 'active'"><a
|
||||
href="#/create/user/{{realm.id}}">Add User</a></li>
|
||||
href="#/create/user/{{realm.id}}">New User</a></li>
|
||||
<li data-ng-class="path[0] == 'find' && path[1] == 'user' && 'active'"><a
|
||||
href="#/find/user/{{realm.id}}">Find User</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li data-ng-class="path[2] == 'resources' && 'active'"><a href="#/realms/{{realm.id}}/applications">Manage Applications</a></li>
|
||||
|
||||
<li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{realm.id}}/roles">Roles</a>
|
||||
<ul class="sub-items">
|
||||
<li data-ng-class="path[0] == 'create' && path[1] == 'role' && 'active'"><a
|
||||
href="#/create/role/{{realm.id}}">New Role</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li data-ng-class="path[2] == 'applications' && 'active'"><a href="#/realms/{{realm.id}}/applications">Manage Applications</a></li>
|
||||
<li data-ng-class="!path[2] && 'active'"><a href="#/realms/{{realm.id}}">Realm Settings</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
|
@ -447,7 +447,7 @@ public class OAuthAuthenticationServerValve extends FormAuthenticator implements
|
|||
userSessionManagement.logout(username);
|
||||
request.setUserPrincipal(null);
|
||||
request.setAuthType(null);
|
||||
// logout user on all declared authenticated resources
|
||||
// logout user on all declared authenticated applications
|
||||
logoutResources(username, admin);
|
||||
redirectToWelcomePage(request, response);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.keycloak.RealmConfiguration;
|
|||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -230,7 +230,7 @@ public class ServletOAuthLogin {
|
|||
form.param("grant_type", "authorization_code")
|
||||
.param("code", code)
|
||||
.param("client_id", client_id)
|
||||
.param(RequiredCredentialRepresentation.PASSWORD, password)
|
||||
.param(CredentialRepresentation.PASSWORD, password)
|
||||
.param("redirect_uri", redirectUri);
|
||||
|
||||
Response res = realmInfo.getCodeUrl().request()
|
||||
|
|
|
@ -153,7 +153,7 @@ public class LoginBean {
|
|||
requiredCredentials = new LinkedList<RequiredCredential>();
|
||||
for (RequiredCredentialModel m : realm.getRequiredCredentials()) {
|
||||
if (m.isInput()) {
|
||||
requiredCredentials.add(new RequiredCredential(m.getType(), m.isSecret()));
|
||||
requiredCredentials.add(new RequiredCredential(m.getType(), m.isSecret(), m.getFormLabel()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,10 +193,12 @@ public class LoginBean {
|
|||
public class RequiredCredential {
|
||||
private String type;
|
||||
private boolean secret;
|
||||
private String formLabel;
|
||||
|
||||
public RequiredCredential(String type, boolean secure) {
|
||||
public RequiredCredential(String type, boolean secure, String formLabel) {
|
||||
this.type = type;
|
||||
this.secret = secure;
|
||||
this.formLabel = formLabel;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -204,7 +206,7 @@ public class LoginBean {
|
|||
}
|
||||
|
||||
public String getLabel() {
|
||||
return type;
|
||||
return formLabel;
|
||||
}
|
||||
|
||||
public String getInputType() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
|||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RequiredCredentialModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
|
@ -206,9 +206,9 @@ public class AuthenticationManager {
|
|||
|
||||
List<RequiredCredentialModel> requiredCredentials = null;
|
||||
if (realm.hasRole(user, RealmManager.RESOURCE_ROLE)) {
|
||||
requiredCredentials = realm.getResourceRequiredCredentials();
|
||||
requiredCredentials = realm.getRequiredApplicationCredentials();
|
||||
} else if (realm.hasRole(user, RealmManager.IDENTITY_REQUESTER_ROLE)) {
|
||||
requiredCredentials = realm.getOAuthClientRequiredCredentials();
|
||||
requiredCredentials = realm.getRequiredOAuthClientCredentials();
|
||||
} else {
|
||||
requiredCredentials = realm.getRequiredCredentials();
|
||||
}
|
||||
|
@ -216,21 +216,23 @@ public class AuthenticationManager {
|
|||
types.add(credential.getType());
|
||||
}
|
||||
|
||||
if (types.contains(RequiredCredentialRepresentation.PASSWORD)) {
|
||||
String password = formData.getFirst(RequiredCredentialRepresentation.PASSWORD);
|
||||
if (types.contains(CredentialRepresentation.PASSWORD)) {
|
||||
String password = formData.getFirst(CredentialRepresentation.PASSWORD);
|
||||
if (password == null) {
|
||||
logger.warn("Password not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (types.contains(RequiredCredentialRepresentation.TOTP)) {
|
||||
String token = formData.getFirst(RequiredCredentialRepresentation.TOTP);
|
||||
if (types.contains(CredentialRepresentation.TOTP)) {
|
||||
String token = formData.getFirst(CredentialRepresentation.TOTP);
|
||||
if (token == null) {
|
||||
logger.warn("TOTP token not provided");
|
||||
return false;
|
||||
}
|
||||
logger.info("validating TOTP");
|
||||
return realm.validateTOTP(user, password, token);
|
||||
} else {
|
||||
logger.info("validating password for user: " + user.getLoginName());
|
||||
return realm.validatePassword(user, password);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,28 +1,14 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.RoleMappingRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.services.models.KeycloakSession;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RequiredCredentialModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserCredentialModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.representations.idm.*;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.services.models.*;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
|
@ -32,6 +18,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmManager {
|
||||
protected static final Logger logger = Logger.getLogger(RealmManager.class);
|
||||
private static AtomicLong counter = new AtomicLong(1);
|
||||
public static final String RESOURCE_ROLE = "KEYCLOAK_RESOURCE";
|
||||
public static final String IDENTITY_REQUESTER_ROLE = "KEYCLOAK_IDENTITY_REQUESTER";
|
||||
|
@ -79,6 +66,26 @@ public class RealmManager {
|
|||
realm.setPublicKey(keyPair.getPublic());
|
||||
}
|
||||
|
||||
public void updateRealm(RealmRepresentation rep, RealmModel realm) {
|
||||
if (rep.getRealm() != null) realm.setName(rep.getRealm());
|
||||
realm.setEnabled(rep.isEnabled());
|
||||
realm.setSocial(rep.isSocial());
|
||||
realm.setCookieLoginAllowed(rep.isCookieLoginAllowed());
|
||||
realm.setRegistrationAllowed(rep.isRegistrationAllowed());
|
||||
realm.setSslNotRequired((rep.isSslNotRequired()));
|
||||
realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
|
||||
realm.setTokenLifespan(rep.getTokenLifespan());
|
||||
if (rep.getRequiredOAuthClientCredentials() != null) {
|
||||
realm.updateRequiredOAuthClientCredentials(rep.getRequiredOAuthClientCredentials());
|
||||
}
|
||||
if (rep.getRequiredCredentials() != null) {
|
||||
realm.updateRequiredCredentials(rep.getRequiredCredentials());
|
||||
}
|
||||
if (rep.getRequiredApplicationCredentials() != null) {
|
||||
realm.updateRequiredApplicationCredentials(rep.getRequiredApplicationCredentials());
|
||||
}
|
||||
}
|
||||
|
||||
public RealmModel importRealm(RealmRepresentation rep, UserModel realmCreator) {
|
||||
//verifyRealmRepresentation(rep);
|
||||
RealmModel realm = createRealm(rep.getRealm());
|
||||
|
@ -91,6 +98,7 @@ public class RealmManager {
|
|||
public void importRealm(RealmRepresentation rep, RealmModel newRealm) {
|
||||
newRealm.setName(rep.getRealm());
|
||||
newRealm.setEnabled(rep.isEnabled());
|
||||
newRealm.setSocial(rep.isSocial());
|
||||
newRealm.setTokenLifespan(rep.getTokenLifespan());
|
||||
newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
|
||||
newRealm.setSslNotRequired(rep.isSslNotRequired());
|
||||
|
@ -105,19 +113,19 @@ public class RealmManager {
|
|||
Map<String, UserModel> userMap = new HashMap<String, UserModel>();
|
||||
|
||||
if (rep.getRequiredCredentials() != null) {
|
||||
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials()) {
|
||||
for (String requiredCred : rep.getRequiredCredentials()) {
|
||||
addRequiredCredential(newRealm, requiredCred);
|
||||
}
|
||||
}
|
||||
|
||||
if (rep.getRequiredResourceCredentials() != null) {
|
||||
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials()) {
|
||||
if (rep.getRequiredApplicationCredentials() != null) {
|
||||
for (String requiredCred : rep.getRequiredCredentials()) {
|
||||
addResourceRequiredCredential(newRealm, requiredCred);
|
||||
}
|
||||
}
|
||||
|
||||
if (rep.getRequiredOAuthClientCredentials() != null) {
|
||||
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials()) {
|
||||
for (String requiredCred : rep.getRequiredCredentials()) {
|
||||
addOAuthClientRequiredCredential(newRealm, requiredCred);
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +145,7 @@ public class RealmManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (rep.getResources() != null) {
|
||||
if (rep.getApplications() != null) {
|
||||
createResources(rep, newRealm);
|
||||
}
|
||||
|
||||
|
@ -193,33 +201,22 @@ public class RealmManager {
|
|||
return user;
|
||||
}
|
||||
|
||||
public void addRequiredCredential(RealmModel newRealm, RequiredCredentialRepresentation requiredCred) {
|
||||
RequiredCredentialModel credential = initializeCred(requiredCred);
|
||||
newRealm.addRequiredCredential(credential);
|
||||
public void addRequiredCredential(RealmModel newRealm, String requiredCred) {
|
||||
newRealm.addRequiredCredential(requiredCred);
|
||||
}
|
||||
public void addResourceRequiredCredential(RealmModel newRealm, RequiredCredentialRepresentation requiredCred) {
|
||||
RequiredCredentialModel credential = initializeCred(requiredCred);
|
||||
newRealm.addResourceRequiredCredential(credential);
|
||||
public void addResourceRequiredCredential(RealmModel newRealm, String requiredCred) {
|
||||
newRealm.addRequiredResourceCredential(requiredCred);
|
||||
}
|
||||
public void addOAuthClientRequiredCredential(RealmModel newRealm, RequiredCredentialRepresentation requiredCred) {
|
||||
RequiredCredentialModel credential = initializeCred(requiredCred);
|
||||
newRealm.addOAuthClientRequiredCredential(credential);
|
||||
public void addOAuthClientRequiredCredential(RealmModel newRealm, String requiredCred) {
|
||||
newRealm.addRequiredOAuthClientCredential(requiredCred);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private RequiredCredentialModel initializeCred(RequiredCredentialRepresentation requiredCred) {
|
||||
RequiredCredentialModel credential = new RequiredCredentialModel();
|
||||
credential.setType(requiredCred.getType());
|
||||
credential.setInput(requiredCred.isInput());
|
||||
credential.setSecret(requiredCred.isSecret());
|
||||
return credential;
|
||||
}
|
||||
|
||||
protected void createResources(RealmRepresentation rep, RealmModel realm) {
|
||||
RoleModel loginRole = realm.getRole(RealmManager.RESOURCE_ROLE);
|
||||
ResourceManager manager = new ResourceManager(this);
|
||||
for (ResourceRepresentation resourceRep : rep.getResources()) {
|
||||
for (ApplicationRepresentation resourceRep : rep.getApplications()) {
|
||||
manager.createResource(realm, loginRole, resourceRep);
|
||||
}
|
||||
}
|
||||
|
@ -232,4 +229,40 @@ public class RealmManager {
|
|||
return rep;
|
||||
}
|
||||
|
||||
public RealmRepresentation toRepresentation(RealmModel realm) {
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
rep.setId(realm.getId());
|
||||
rep.setRealm(realm.getName());
|
||||
rep.setEnabled(realm.isEnabled());
|
||||
rep.setSocial(realm.isSocial());
|
||||
rep.setSslNotRequired(realm.isSslNotRequired());
|
||||
rep.setCookieLoginAllowed(realm.isCookieLoginAllowed());
|
||||
rep.setPublicKey(realm.getPublicKeyPem());
|
||||
rep.setTokenLifespan(realm.getTokenLifespan());
|
||||
rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
|
||||
List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
|
||||
if (requiredCredentialModels.size() > 0) {
|
||||
rep.setRequiredCredentials(new HashSet<String>());
|
||||
for (RequiredCredentialModel cred : requiredCredentialModels) {
|
||||
rep.getRequiredCredentials().add(cred.getType());
|
||||
}
|
||||
}
|
||||
List<RequiredCredentialModel> requiredResourceCredentialModels = realm.getRequiredApplicationCredentials();
|
||||
if (requiredResourceCredentialModels.size() > 0) {
|
||||
rep.setRequiredApplicationCredentials(new HashSet<String>());
|
||||
for (RequiredCredentialModel cred : requiredResourceCredentialModels) {
|
||||
rep.getRequiredApplicationCredentials().add(cred.getType());
|
||||
}
|
||||
}
|
||||
List<RequiredCredentialModel> requiredOAuthCredentialModels = realm.getRequiredOAuthClientCredentials();
|
||||
if (requiredOAuthCredentialModels.size() > 0) {
|
||||
rep.setRequiredOAuthClientCredentials(new HashSet<String>());
|
||||
for (RequiredCredentialModel cred : requiredOAuthCredentialModels) {
|
||||
rep.getRequiredOAuthClientCredentials().add(cred.getType());
|
||||
}
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.jboss.resteasy.logging.Logger;
|
|||
import org.keycloak.TokenIdGenerator;
|
||||
import org.keycloak.representations.idm.admin.LogoutAction;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.core.Form;
|
||||
|
@ -29,14 +29,14 @@ public class ResourceAdminManager {
|
|||
.disableTrustManager() // todo fix this, should have a trust manager or a good default
|
||||
.build();
|
||||
|
||||
List<ResourceModel> resources = realm.getResources();
|
||||
List<ApplicationModel> resources = realm.getApplications();
|
||||
logger.info("logging out " + resources.size() + " resoures.");
|
||||
for (ResourceModel resource : resources) {
|
||||
for (ApplicationModel resource : resources) {
|
||||
logoutResource(realm, resource, user, client);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean logoutResource(RealmModel realm, ResourceModel resource, String user, ResteasyClient client) {
|
||||
protected boolean logoutResource(RealmModel realm, ApplicationModel resource, String user, ResteasyClient client) {
|
||||
LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), System.currentTimeMillis() / 1000 + 30, resource.getName(), user);
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
Form form = new Form();
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.RoleMappingRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
||||
import org.keycloak.representations.idm.*;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserCredentialModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
@ -25,8 +20,8 @@ public class ResourceManager {
|
|||
this.realmManager = realmManager;
|
||||
}
|
||||
|
||||
public ResourceModel createResource(RealmModel realm, RoleModel loginRole, ResourceRepresentation resourceRep) {
|
||||
ResourceModel resource = realm.addResource(resourceRep.getName());
|
||||
public ApplicationModel createResource(RealmModel realm, RoleModel loginRole, ApplicationRepresentation resourceRep) {
|
||||
ApplicationModel resource = realm.addApplication(resourceRep.getName());
|
||||
resource.setEnabled(resourceRep.isEnabled());
|
||||
resource.setManagementUrl(resourceRep.getAdminUrl());
|
||||
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
||||
|
@ -78,12 +73,12 @@ public class ResourceManager {
|
|||
return resource;
|
||||
}
|
||||
|
||||
public ResourceModel createResource(RealmModel realm, ResourceRepresentation resourceRep) {
|
||||
public ApplicationModel createResource(RealmModel realm, ApplicationRepresentation resourceRep) {
|
||||
RoleModel loginRole = realm.getRole(RealmManager.RESOURCE_ROLE);
|
||||
return createResource(realm, loginRole, resourceRep);
|
||||
}
|
||||
|
||||
public void updateResource(ResourceRepresentation rep, ResourceModel resource) {
|
||||
public void updateResource(ApplicationRepresentation rep, ApplicationModel resource) {
|
||||
resource.setName(rep.getName());
|
||||
resource.setEnabled(rep.isEnabled());
|
||||
resource.setManagementUrl(rep.getAdminUrl());
|
||||
|
@ -92,13 +87,13 @@ public class ResourceManager {
|
|||
|
||||
}
|
||||
|
||||
public ResourceRepresentation toRepresentation(ResourceModel resourceModel) {
|
||||
ResourceRepresentation rep = new ResourceRepresentation();
|
||||
rep.setId(resourceModel.getId());
|
||||
rep.setName(resourceModel.getName());
|
||||
rep.setEnabled(resourceModel.isEnabled());
|
||||
rep.setAdminUrl(resourceModel.getManagementUrl());
|
||||
rep.setSurrogateAuthRequired(resourceModel.isSurrogateAuthRequired());
|
||||
public ApplicationRepresentation toRepresentation(ApplicationModel applicationModel) {
|
||||
ApplicationRepresentation rep = new ApplicationRepresentation();
|
||||
rep.setId(applicationModel.getId());
|
||||
rep.setName(applicationModel.getName());
|
||||
rep.setEnabled(applicationModel.isEnabled());
|
||||
rep.setAdminUrl(applicationModel.getManagementUrl());
|
||||
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
|
||||
return rep;
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.jboss.resteasy.jwt.JsonSerialization;
|
|||
import org.keycloak.representations.SkeletonKeyScope;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class TokenManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (ResourceModel resource : realm.getResources()) {
|
||||
for (ApplicationModel resource : realm.getApplications()) {
|
||||
Set<String> mapping = resource.getRoleMappings(user);
|
||||
if (mapping != null && mapping.size() > 0 && (scopeMap == null || scopeMap.containsKey(resource.getName()))) {
|
||||
Set<String> scope = resource.getScope(client);
|
||||
|
@ -131,9 +131,9 @@ public class TokenManager {
|
|||
}
|
||||
|
||||
if (accessCodeEntry.getResourceRolesRequested().size() > 0) {
|
||||
Map<String, ResourceModel> resourceMap = realm.getResourceNameMap();
|
||||
Map<String, ApplicationModel> resourceMap = realm.getResourceNameMap();
|
||||
for (String resourceName : accessCodeEntry.getResourceRolesRequested().keySet()) {
|
||||
ResourceModel resource = resourceMap.get(resourceName);
|
||||
ApplicationModel resource = resourceMap.get(resourceName);
|
||||
SkeletonKeyToken.Access access = token.addAccess(resourceName).verifyCaller(resource.isSurrogateAuthRequired());
|
||||
for (RoleModel role : accessCodeEntry.getResourceRolesRequested().get(resourceName)) {
|
||||
access.addRole(role.getName());
|
||||
|
@ -166,7 +166,7 @@ public class TokenManager {
|
|||
|
||||
|
||||
public SkeletonKeyToken createAccessToken(RealmModel realm, UserModel user) {
|
||||
List<ResourceModel> resources = realm.getResources();
|
||||
List<ApplicationModel> resources = realm.getApplications();
|
||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
||||
token.id(RealmManager.generateId());
|
||||
token.issuedNow();
|
||||
|
@ -186,7 +186,7 @@ public class TokenManager {
|
|||
token.setRealmAccess(access);
|
||||
}
|
||||
if (resources != null) {
|
||||
for (ResourceModel resource : resources) {
|
||||
for (ApplicationModel resource : resources) {
|
||||
Set<String> mapping = resource.getRoleMappings(user);
|
||||
if (mapping == null) continue;
|
||||
SkeletonKeyToken.Access access = token.addAccess(resource.getName())
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ResourceModel {
|
||||
public interface ApplicationModel {
|
||||
void updateResource();
|
||||
|
||||
UserModel getResourceUser();
|
|
@ -61,7 +61,7 @@ public interface RealmModel {
|
|||
|
||||
List<RequiredCredentialModel> getRequiredCredentials();
|
||||
|
||||
void addRequiredCredential(RequiredCredentialModel cred);
|
||||
void addRequiredCredential(String cred);
|
||||
|
||||
boolean validatePassword(UserModel user, String password);
|
||||
|
||||
|
@ -79,11 +79,11 @@ public interface RealmModel {
|
|||
|
||||
List<RoleModel> getRoles();
|
||||
|
||||
Map<String, ResourceModel> getResourceNameMap();
|
||||
Map<String, ApplicationModel> getResourceNameMap();
|
||||
|
||||
List<ResourceModel> getResources();
|
||||
List<ApplicationModel> getApplications();
|
||||
|
||||
ResourceModel addResource(String name);
|
||||
ApplicationModel addApplication(String name);
|
||||
|
||||
boolean hasRole(UserModel user, RoleModel role);
|
||||
|
||||
|
@ -101,15 +101,27 @@ public interface RealmModel {
|
|||
|
||||
RoleModel getRoleById(String id);
|
||||
|
||||
void addResourceRequiredCredential(RequiredCredentialModel cred);
|
||||
|
||||
List<RequiredCredentialModel> getResourceRequiredCredentials();
|
||||
List<RequiredCredentialModel> getRequiredApplicationCredentials();
|
||||
|
||||
void addOAuthClientRequiredCredential(RequiredCredentialModel cred);
|
||||
|
||||
List<RequiredCredentialModel> getOAuthClientRequiredCredentials();
|
||||
List<RequiredCredentialModel> getRequiredOAuthClientCredentials();
|
||||
|
||||
boolean hasRole(UserModel user, String role);
|
||||
|
||||
ResourceModel getResourceById(String id);
|
||||
ApplicationModel getApplicationById(String id);
|
||||
|
||||
void addRequiredOAuthClientCredential(String type);
|
||||
|
||||
void addRequiredResourceCredential(String type);
|
||||
|
||||
void updateRequiredCredentials(Set<String> creds);
|
||||
|
||||
void updateRequiredOAuthClientCredentials(Set<String> creds);
|
||||
|
||||
void updateRequiredApplicationCredentials(Set<String> creds);
|
||||
|
||||
boolean isSocial();
|
||||
|
||||
void setSocial(boolean social);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package org.keycloak.services.models;
|
||||
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -10,16 +14,11 @@ public class RequiredCredentialModel {
|
|||
protected String type;
|
||||
protected boolean input;
|
||||
protected boolean secret;
|
||||
protected String formLabel;
|
||||
|
||||
public RequiredCredentialModel() {
|
||||
}
|
||||
|
||||
public RequiredCredentialModel(String type, boolean input, boolean secret) {
|
||||
this.type = type;
|
||||
this.input = input;
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
@ -44,5 +43,39 @@ public class RequiredCredentialModel {
|
|||
this.secret = secret;
|
||||
}
|
||||
|
||||
public static final RequiredCredentialModel PASSWORD = new RequiredCredentialModel(RequiredCredentialRepresentation.PASSWORD, true, true);
|
||||
public String getFormLabel() {
|
||||
return formLabel;
|
||||
}
|
||||
|
||||
public void setFormLabel(String formLabel) {
|
||||
this.formLabel = formLabel;
|
||||
}
|
||||
|
||||
public static final Map<String, RequiredCredentialModel> BUILT_IN;
|
||||
public static final RequiredCredentialModel PASSWORD;
|
||||
public static final RequiredCredentialModel TOTP;
|
||||
public static final RequiredCredentialModel CLIENT_CERT;
|
||||
|
||||
static {
|
||||
Map<String, RequiredCredentialModel> map = new HashMap<String, RequiredCredentialModel>();
|
||||
PASSWORD = new RequiredCredentialModel();
|
||||
PASSWORD.setType(CredentialRepresentation.PASSWORD);
|
||||
PASSWORD.setInput(true);
|
||||
PASSWORD.setSecret(true);
|
||||
PASSWORD.setFormLabel("Password");
|
||||
map.put(PASSWORD.getType(), PASSWORD);
|
||||
TOTP = new RequiredCredentialModel();
|
||||
TOTP.setType(CredentialRepresentation.TOTP);
|
||||
TOTP.setInput(true);
|
||||
TOTP.setSecret(false);
|
||||
TOTP.setFormLabel("Authenticator Code");
|
||||
map.put(TOTP.getType(), TOTP);
|
||||
CLIENT_CERT = new RequiredCredentialModel();
|
||||
CLIENT_CERT.setType(CredentialRepresentation.CLIENT_CERT);
|
||||
CLIENT_CERT.setInput(false);
|
||||
CLIENT_CERT.setSecret(false);
|
||||
CLIENT_CERT.setFormLabel("Client Certificate");
|
||||
map.put(CLIENT_CERT.getType(), CLIENT_CERT);
|
||||
BUILT_IN = Collections.unmodifiableMap(map);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ public class UserCredentialModel {
|
|||
|
||||
protected String type;
|
||||
protected String value;
|
||||
protected String device;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
|
@ -24,4 +25,12 @@ public class UserCredentialModel {
|
|||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,4 +20,16 @@ public interface UserModel {
|
|||
String getAttribute(String name);
|
||||
|
||||
Map<String, String> getAttributes();
|
||||
|
||||
String getFirstName();
|
||||
|
||||
void setFirstName(String firstName);
|
||||
|
||||
String getLastName();
|
||||
|
||||
void setLastName(String lastName);
|
||||
|
||||
String getEmail();
|
||||
|
||||
void setEmail(String email);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package org.keycloak.services.models.picketlink;
|
||||
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.keycloak.services.models.picketlink.mappings.ResourceData;
|
||||
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship;
|
||||
import org.keycloak.services.models.picketlink.mappings.ApplicationData;
|
||||
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
|
@ -24,14 +23,14 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ResourceAdapter implements ResourceModel {
|
||||
protected ResourceData resource;
|
||||
public class ApplicationAdapter implements ApplicationModel {
|
||||
protected ApplicationData resource;
|
||||
protected RealmAdapter realm;
|
||||
protected IdentityManager idm;
|
||||
protected PartitionManager partitionManager;
|
||||
protected RelationshipManager relationshipManager;
|
||||
|
||||
public ResourceAdapter(ResourceData resource, RealmAdapter realm, PartitionManager partitionManager) {
|
||||
public ApplicationAdapter(ApplicationData resource, RealmAdapter realm, PartitionManager partitionManager) {
|
||||
this.resource = resource;
|
||||
this.realm = realm;
|
||||
this.partitionManager = partitionManager;
|
|
@ -1,24 +1,21 @@
|
|||
package org.keycloak.services.models.picketlink;
|
||||
|
||||
import org.bouncycastle.openssl.PEMWriter;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.security.PemUtils;
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.models.KeycloakSession;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RequiredCredentialModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserCredentialModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.keycloak.services.models.picketlink.mappings.RealmData;
|
||||
import org.keycloak.services.models.picketlink.mappings.ResourceData;
|
||||
import org.keycloak.services.models.picketlink.relationships.OAuthClientRequiredCredentialRelationship;
|
||||
import org.keycloak.services.models.picketlink.relationships.RealmAdminRelationship;
|
||||
import org.keycloak.services.models.picketlink.relationships.RequiredCredentialRelationship;
|
||||
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship;
|
||||
import org.keycloak.services.models.picketlink.relationships.ResourceRequiredCredentialRelationship;
|
||||
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
|
||||
import org.keycloak.services.models.picketlink.mappings.ApplicationData;
|
||||
import org.keycloak.services.models.picketlink.relationships.*;
|
||||
import org.keycloak.services.models.picketlink.relationships.RequiredApplicationCredentialRelationship;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
import org.picketlink.idm.RelationshipManager;
|
||||
|
@ -29,6 +26,7 @@ import org.picketlink.idm.credential.TOTPCredentials;
|
|||
import org.picketlink.idm.credential.UsernamePasswordCredentials;
|
||||
import org.picketlink.idm.credential.X509CertificateCredentials;
|
||||
import org.picketlink.idm.model.IdentityType;
|
||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||
import org.picketlink.idm.model.sample.Grant;
|
||||
import org.picketlink.idm.model.sample.Role;
|
||||
import org.picketlink.idm.model.sample.SampleModel;
|
||||
|
@ -55,6 +53,7 @@ import java.util.Set;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmAdapter implements RealmModel {
|
||||
protected static final Logger logger = Logger.getLogger(RealmManager.class);
|
||||
|
||||
protected RealmData realm;
|
||||
protected volatile transient PublicKey publicKey;
|
||||
|
@ -112,6 +111,16 @@ public class RealmAdapter implements RealmModel {
|
|||
updateRealm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSocial() {
|
||||
return realm.isSocial();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSocial(boolean social) {
|
||||
realm.setSocial(social);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSslNotRequired() {
|
||||
return realm.isSslNotRequired();
|
||||
|
@ -251,44 +260,51 @@ public class RealmAdapter implements RealmModel {
|
|||
|
||||
@Override
|
||||
public List<RequiredCredentialModel> getRequiredCredentials() {
|
||||
RelationshipQuery<RequiredCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(RequiredCredentialRelationship.class);
|
||||
query.setParameter(RequiredCredentialRelationship.REALM, realm.getName());
|
||||
List<RequiredCredentialRelationship> results = query.getResultList();
|
||||
List<RequiredCredentialRelationship> results = getRequiredCredentialRelationships();
|
||||
return getRequiredCredentialModels(results);
|
||||
}
|
||||
|
||||
protected List<RequiredCredentialRelationship> getRequiredCredentialRelationships() {
|
||||
RelationshipQuery<RequiredCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(RequiredCredentialRelationship.class);
|
||||
query.setParameter(RequiredCredentialRelationship.REALM, realm.getName());
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceRequiredCredential(RequiredCredentialModel cred) {
|
||||
ResourceRequiredCredentialRelationship relationship = new ResourceRequiredCredentialRelationship();
|
||||
|
||||
public void addRequiredApplicationCredential(RequiredCredentialModel cred) {
|
||||
RequiredApplicationCredentialRelationship relationship = new RequiredApplicationCredentialRelationship();
|
||||
addRequiredCredential(cred, relationship);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RequiredCredentialModel> getResourceRequiredCredentials() {
|
||||
RelationshipQuery<ResourceRequiredCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(ResourceRequiredCredentialRelationship.class);
|
||||
query.setParameter(ResourceRequiredCredentialRelationship.REALM, realm.getName());
|
||||
List<ResourceRequiredCredentialRelationship> results = query.getResultList();
|
||||
public List<RequiredCredentialModel> getRequiredApplicationCredentials() {
|
||||
List<RequiredApplicationCredentialRelationship> results = getResourceRequiredCredentialRelationships();
|
||||
return getRequiredCredentialModels(results);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOAuthClientRequiredCredential(RequiredCredentialModel cred) {
|
||||
protected List<RequiredApplicationCredentialRelationship> getResourceRequiredCredentialRelationships() {
|
||||
RelationshipQuery<RequiredApplicationCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(RequiredApplicationCredentialRelationship.class);
|
||||
query.setParameter(RequiredApplicationCredentialRelationship.REALM, realm.getName());
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
public void addRequiredOAuthClientCredential(RequiredCredentialModel cred) {
|
||||
OAuthClientRequiredCredentialRelationship relationship = new OAuthClientRequiredCredentialRelationship();
|
||||
addRequiredCredential(cred, relationship);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RequiredCredentialModel> getOAuthClientRequiredCredentials() {
|
||||
RelationshipQuery<OAuthClientRequiredCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(OAuthClientRequiredCredentialRelationship.class);
|
||||
query.setParameter(ResourceRequiredCredentialRelationship.REALM, realm.getName());
|
||||
List<OAuthClientRequiredCredentialRelationship> results = query.getResultList();
|
||||
public List<RequiredCredentialModel> getRequiredOAuthClientCredentials() {
|
||||
List<OAuthClientRequiredCredentialRelationship> results = getOAuthClientRequiredCredentialRelationships();
|
||||
return getRequiredCredentialModels(results);
|
||||
}
|
||||
|
||||
protected List<OAuthClientRequiredCredentialRelationship> getOAuthClientRequiredCredentialRelationships() {
|
||||
RelationshipQuery<OAuthClientRequiredCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(OAuthClientRequiredCredentialRelationship.class);
|
||||
query.setParameter(RequiredApplicationCredentialRelationship.REALM, realm.getName());
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addRequiredCredential(RequiredCredentialModel cred) {
|
||||
RequiredCredentialRelationship relationship = new RequiredCredentialRelationship();
|
||||
addRequiredCredential(cred, relationship);
|
||||
|
@ -302,6 +318,7 @@ public class RealmAdapter implements RealmModel {
|
|||
model.setInput(relationship.isInput());
|
||||
model.setSecret(relationship.isSecret());
|
||||
model.setType(relationship.getCredentialType());
|
||||
model.setFormLabel(relationship.getFormLabel());
|
||||
rtn.add(model);
|
||||
}
|
||||
return rtn;
|
||||
|
@ -311,9 +328,94 @@ public class RealmAdapter implements RealmModel {
|
|||
relationship.setInput(cred.isInput());
|
||||
relationship.setSecret(cred.isSecret());
|
||||
relationship.setRealm(realm.getName());
|
||||
relationship.setFormLabel(cred.getFormLabel());
|
||||
getRelationshipManager().add(relationship);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRequiredCredentials(Set<String> creds) {
|
||||
List<RequiredCredentialRelationship> relationships = getRequiredCredentialRelationships();
|
||||
RelationshipManager rm = getRelationshipManager();
|
||||
Set<String> already = new HashSet<String>();
|
||||
for (RequiredCredentialRelationship rel : relationships) {
|
||||
if (!creds.contains(rel.getCredentialType())) {
|
||||
rm.remove(rel);
|
||||
} else {
|
||||
already.add(rel.getCredentialType());
|
||||
}
|
||||
}
|
||||
for (String cred : creds) {
|
||||
logger.info("updating cred: " + cred);
|
||||
if (!already.contains(cred)) {
|
||||
addRequiredCredential(cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRequiredOAuthClientCredentials(Set<String> creds) {
|
||||
List<OAuthClientRequiredCredentialRelationship> relationships = getOAuthClientRequiredCredentialRelationships();
|
||||
RelationshipManager rm = getRelationshipManager();
|
||||
Set<String> already = new HashSet<String>();
|
||||
for (RequiredCredentialRelationship rel : relationships) {
|
||||
if (!creds.contains(rel.getCredentialType())) {
|
||||
rm.remove(rel);
|
||||
} else {
|
||||
already.add(rel.getCredentialType());
|
||||
}
|
||||
}
|
||||
for (String cred : creds) {
|
||||
if (!already.contains(cred)) {
|
||||
addRequiredOAuthClientCredential(cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRequiredApplicationCredentials(Set<String> creds) {
|
||||
List<RequiredApplicationCredentialRelationship> relationships = getResourceRequiredCredentialRelationships();
|
||||
RelationshipManager rm = getRelationshipManager();
|
||||
Set<String> already = new HashSet<String>();
|
||||
for (RequiredCredentialRelationship rel : relationships) {
|
||||
if (!creds.contains(rel.getCredentialType())) {
|
||||
rm.remove(rel);
|
||||
} else {
|
||||
already.add(rel.getCredentialType());
|
||||
}
|
||||
}
|
||||
for (String cred : creds) {
|
||||
if (!already.contains(cred)) {
|
||||
addRequiredResourceCredential(cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addRequiredCredential(String type) {
|
||||
RequiredCredentialModel model = initRequiredCredentialModel(type);
|
||||
addRequiredCredential(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredOAuthClientCredential(String type) {
|
||||
RequiredCredentialModel model = initRequiredCredentialModel(type);
|
||||
addRequiredOAuthClientCredential(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredResourceCredential(String type) {
|
||||
RequiredCredentialModel model = initRequiredCredentialModel(type);
|
||||
addRequiredApplicationCredential(model);
|
||||
}
|
||||
|
||||
protected RequiredCredentialModel initRequiredCredentialModel(String type) {
|
||||
RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
|
||||
if (model == null) {
|
||||
throw new RuntimeException("Unknown credential type " + type);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validatePassword(UserModel user, String password) {
|
||||
|
@ -335,13 +437,14 @@ public class RealmAdapter implements RealmModel {
|
|||
@Override
|
||||
public void updateCredential(UserModel user, UserCredentialModel cred) {
|
||||
IdentityManager idm = getIdm();
|
||||
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) {
|
||||
if (cred.getType().equals(CredentialRepresentation.PASSWORD)) {
|
||||
Password password = new Password(cred.getValue());
|
||||
idm.updateCredential(((UserAdapter)user).getUser(), password);
|
||||
} else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) {
|
||||
} else if (cred.getType().equals(CredentialRepresentation.TOTP)) {
|
||||
TOTPCredential totp = new TOTPCredential(cred.getValue());
|
||||
totp.setDevice(cred.getDevice());
|
||||
idm.updateCredential(((UserAdapter)user).getUser(), totp);
|
||||
} else if (cred.getType().equals(RequiredCredentialRepresentation.CLIENT_CERT)) {
|
||||
} else if (cred.getType().equals(CredentialRepresentation.CLIENT_CERT)) {
|
||||
X509Certificate cert = null;
|
||||
try {
|
||||
cert = org.keycloak.PemUtils.decodeCertificate(cred.getValue());
|
||||
|
@ -416,9 +519,9 @@ public class RealmAdapter implements RealmModel {
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, ResourceModel> getResourceNameMap() {
|
||||
Map<String, ResourceModel> resourceMap = new HashMap<String, ResourceModel>();
|
||||
for (ResourceModel resource : getResources()) {
|
||||
public Map<String, ApplicationModel> getResourceNameMap() {
|
||||
Map<String, ApplicationModel> resourceMap = new HashMap<String, ApplicationModel>();
|
||||
for (ApplicationModel resource : getApplications()) {
|
||||
resourceMap.put(resource.getName(), resource);
|
||||
}
|
||||
return resourceMap;
|
||||
|
@ -430,27 +533,27 @@ public class RealmAdapter implements RealmModel {
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ResourceModel getResourceById(String id) {
|
||||
public ApplicationModel getApplicationById(String id) {
|
||||
RelationshipQuery<ResourceRelationship> query = getRelationshipManager().createRelationshipQuery(ResourceRelationship.class);
|
||||
query.setParameter(ResourceRelationship.REALM, realm.getName());
|
||||
query.setParameter(ResourceRelationship.RESOURCE, id);
|
||||
List<ResourceRelationship> results = query.getResultList();
|
||||
if (results.size() == 0) return null;
|
||||
ResourceData resource = partitionManager.getPartition(ResourceData.class, id);
|
||||
ResourceModel model = new ResourceAdapter(resource, this, partitionManager);
|
||||
ApplicationData resource = partitionManager.getPartition(ApplicationData.class, id);
|
||||
ApplicationModel model = new ApplicationAdapter(resource, this, partitionManager);
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ResourceModel> getResources() {
|
||||
public List<ApplicationModel> getApplications() {
|
||||
RelationshipQuery<ResourceRelationship> query = getRelationshipManager().createRelationshipQuery(ResourceRelationship.class);
|
||||
query.setParameter(ResourceRelationship.REALM, realm.getName());
|
||||
List<ResourceRelationship> results = query.getResultList();
|
||||
List<ResourceModel> resources = new ArrayList<ResourceModel>();
|
||||
List<ApplicationModel> resources = new ArrayList<ApplicationModel>();
|
||||
for (ResourceRelationship relationship : results) {
|
||||
ResourceData resource = partitionManager.getPartition(ResourceData.class, relationship.getResource());
|
||||
ResourceModel model = new ResourceAdapter(resource, this, partitionManager);
|
||||
ApplicationData resource = partitionManager.getPartition(ApplicationData.class, relationship.getResource());
|
||||
ApplicationModel model = new ApplicationAdapter(resource, this, partitionManager);
|
||||
resources.add(model);
|
||||
}
|
||||
|
||||
|
@ -458,19 +561,19 @@ public class RealmAdapter implements RealmModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceModel addResource(String name) {
|
||||
ResourceData resourceData = new ResourceData(RealmManager.generateId());
|
||||
public ApplicationModel addApplication(String name) {
|
||||
ApplicationData applicationData = new ApplicationData(RealmManager.generateId());
|
||||
User resourceUser = new User(name);
|
||||
idm.add(resourceUser);
|
||||
resourceData.setResourceUser(resourceUser);
|
||||
resourceData.setResourceName(name);
|
||||
resourceData.setResourceUser(resourceUser);
|
||||
partitionManager.add(resourceData);
|
||||
applicationData.setResourceUser(resourceUser);
|
||||
applicationData.setResourceName(name);
|
||||
applicationData.setResourceUser(resourceUser);
|
||||
partitionManager.add(applicationData);
|
||||
ResourceRelationship resourceRelationship = new ResourceRelationship();
|
||||
resourceRelationship.setRealm(realm.getName());
|
||||
resourceRelationship.setResource(resourceData.getName());
|
||||
resourceRelationship.setResource(applicationData.getName());
|
||||
getRelationshipManager().add(resourceRelationship);
|
||||
ResourceModel resource = new ResourceAdapter(resourceData, this, partitionManager);
|
||||
ApplicationModel resource = new ApplicationAdapter(applicationData, this, partitionManager);
|
||||
resource.addRole("*");
|
||||
resource.addScope(new UserAdapter(resourceUser, idm), "*");
|
||||
return resource;
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak.services.models.picketlink;
|
|||
import org.keycloak.services.models.UserModel;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
import org.picketlink.idm.model.Attribute;
|
||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||
import org.picketlink.idm.model.sample.User;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -41,6 +42,39 @@ public class UserAdapter implements UserModel {
|
|||
idm.update(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstName() {
|
||||
return user.getFirstName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirstName(String firstName) {
|
||||
user.setFirstName(firstName);
|
||||
idm.update(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastName() {
|
||||
return user.getLastName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastName(String lastName) {
|
||||
user.setLastName(lastName);
|
||||
idm.update(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
return user.getEmail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmail(String email) {
|
||||
user.setEmail(email);
|
||||
idm.update(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, String value) {
|
||||
user.setAttribute(new Attribute<String>(name, value));
|
||||
|
|
|
@ -9,17 +9,17 @@ import org.picketlink.idm.model.sample.User;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ResourceData extends AbstractPartition {
|
||||
public class ApplicationData extends AbstractPartition {
|
||||
private String resourceName;
|
||||
private boolean enabled;
|
||||
private boolean surrogateAuthRequired;
|
||||
private String managementUrl;
|
||||
private User resourceUser;
|
||||
|
||||
public ResourceData() {
|
||||
public ApplicationData() {
|
||||
super(null);
|
||||
}
|
||||
public ResourceData(String name) {
|
||||
public ApplicationData(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
|
@ -15,9 +15,9 @@ import java.io.Serializable;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@IdentityManaged(ResourceData.class)
|
||||
@IdentityManaged(ApplicationData.class)
|
||||
@Entity
|
||||
public class ResourceEntity implements Serializable {
|
||||
public class ApplicationEntity implements Serializable {
|
||||
@OneToOne
|
||||
@Id
|
||||
@OwnerReference
|
|
@ -14,6 +14,7 @@ public class RealmData extends AbstractPartition {
|
|||
private boolean sslNotRequired;
|
||||
private boolean cookieLoginAllowed;
|
||||
private boolean registrationAllowed;
|
||||
private boolean social;
|
||||
private int tokenLifespan;
|
||||
private int accessCodeLifespan;
|
||||
private String publicKeyPem;
|
||||
|
@ -44,6 +45,15 @@ public class RealmData extends AbstractPartition {
|
|||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@AttributeProperty
|
||||
public boolean isSocial() {
|
||||
return social;
|
||||
}
|
||||
|
||||
public void setSocial(boolean social) {
|
||||
this.social = social;
|
||||
}
|
||||
|
||||
@AttributeProperty
|
||||
public boolean isSslNotRequired() {
|
||||
return sslNotRequired;
|
||||
|
|
|
@ -35,6 +35,8 @@ public class RealmEntity implements Serializable {
|
|||
@AttributeValue
|
||||
private boolean registrationAllowed;
|
||||
@AttributeValue
|
||||
private boolean social;
|
||||
@AttributeValue
|
||||
private int tokenLifespan;
|
||||
@AttributeValue
|
||||
private int accessCodeLifespan;
|
||||
|
@ -94,6 +96,14 @@ public class RealmEntity implements Serializable {
|
|||
this.registrationAllowed = registrationAllowed;
|
||||
}
|
||||
|
||||
public boolean isSocial() {
|
||||
return social;
|
||||
}
|
||||
|
||||
public void setSocial(boolean social) {
|
||||
this.social = social;
|
||||
}
|
||||
|
||||
public int getTokenLifespan() {
|
||||
return tokenLifespan;
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ package org.keycloak.services.models.picketlink.relationships;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ResourceRequiredCredentialRelationship extends RequiredCredentialRelationship {
|
||||
public class RequiredApplicationCredentialRelationship extends RequiredCredentialRelationship {
|
||||
}
|
|
@ -68,4 +68,14 @@ public class RequiredCredentialRelationship extends AbstractAttributedType imple
|
|||
public void setSecret(boolean secret) {
|
||||
setAttribute(new Attribute<Boolean>("secret", secret));
|
||||
}
|
||||
|
||||
@AttributeProperty
|
||||
public String getFormLabel() {
|
||||
return (String)getAttribute("formLabel").getValue();
|
||||
}
|
||||
|
||||
public void setFormLabel(String label) {
|
||||
setAttribute(new Attribute<String>("formLabel", label));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.keycloak.services.managers.TokenManager;
|
|||
import org.keycloak.services.models.KeycloakSessionFactory;
|
||||
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession;
|
||||
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSessionFactory;
|
||||
import org.keycloak.services.models.picketlink.mappings.ApplicationEntity;
|
||||
import org.keycloak.services.models.picketlink.mappings.RealmEntity;
|
||||
import org.keycloak.services.models.picketlink.mappings.ResourceEntity;
|
||||
import org.keycloak.social.SocialRequestManager;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
||||
|
@ -98,7 +98,7 @@ public class KeycloakApplication extends Application {
|
|||
OTPCredentialTypeEntity.class,
|
||||
AttributeTypeEntity.class,
|
||||
RealmEntity.class,
|
||||
ResourceEntity.class
|
||||
ApplicationEntity.class
|
||||
)
|
||||
.supportGlobalRelationship(org.picketlink.idm.model.Relationship.class)
|
||||
.addContextInitializer(new JPAContextInitializer(null) {
|
||||
|
|
|
@ -6,7 +6,6 @@ import org.jboss.resteasy.spi.HttpRequest;
|
|||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.NotImplementedYetException;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -19,6 +18,7 @@ import org.keycloak.services.resources.admin.RealmsAdminResource;
|
|||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.*;
|
||||
import java.net.URI;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -109,7 +109,7 @@ public class SaasService {
|
|||
if (user == null) {
|
||||
return Response.status(401).build();
|
||||
}
|
||||
return Response.ok(new WhoAmI(user.getLoginName(), user.getLoginName())).build();
|
||||
return Response.ok(new WhoAmI(user.getLoginName(), user.getFirstName() + " " + user.getLastName())).build();
|
||||
}
|
||||
}.call();
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ public class SaasService {
|
|||
@Path("registrations")
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response processRegister(final @FormParam("name") String name,
|
||||
public Response processRegister(final @FormParam("name") String fullname,
|
||||
final @FormParam("email") String email,
|
||||
final @FormParam("username") String username,
|
||||
final @FormParam("password") String password,
|
||||
|
@ -312,7 +312,29 @@ public class SaasService {
|
|||
RealmModel defaultRealm = realmManager.defaultRealm();
|
||||
UserRepresentation newUser = new UserRepresentation();
|
||||
newUser.setUsername(username);
|
||||
newUser.credential(RequiredCredentialRepresentation.PASSWORD, password, false);
|
||||
newUser.setEmail(email);
|
||||
if (fullname != null) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(fullname, " ");
|
||||
StringBuffer first = null;
|
||||
String last = "";
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String token = tokenizer.nextToken();
|
||||
if (tokenizer.hasMoreTokens()) {
|
||||
if (first == null) {
|
||||
first = new StringBuffer();
|
||||
} else {
|
||||
first.append(" ");
|
||||
}
|
||||
first.append(token);
|
||||
} else {
|
||||
last = token;
|
||||
}
|
||||
}
|
||||
if (first == null) first = new StringBuffer();
|
||||
newUser.setFirstName(first.toString());
|
||||
newUser.setLastName(last);
|
||||
}
|
||||
newUser.credential(CredentialRepresentation.PASSWORD, password);
|
||||
UserModel user = registerMe(defaultRealm, newUser);
|
||||
if (user == null) {
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Username already exists.");
|
||||
|
@ -340,6 +362,9 @@ public class SaasService {
|
|||
}
|
||||
|
||||
user = defaultRealm.addUser(newUser.getUsername());
|
||||
user.setFirstName(newUser.getFirstName());
|
||||
user.setLastName(newUser.getLastName());
|
||||
user.setEmail(newUser.getEmail());
|
||||
for (CredentialRepresentation cred : newUser.getCredentials()) {
|
||||
UserCredentialModel credModel = new UserCredentialModel();
|
||||
credModel.setType(cred.getType());
|
||||
|
|
|
@ -2,53 +2,45 @@ package org.keycloak.services.resources.admin;
|
|||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.representations.idm.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.ResourceManager;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.keycloak.services.resources.Transaction;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmResourceResource {
|
||||
public class ApplicationResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
|
||||
protected UserModel admin;
|
||||
protected RealmModel realm;
|
||||
protected ResourceModel resourceModel;
|
||||
protected ApplicationModel applicationModel;
|
||||
|
||||
public RealmResourceResource(UserModel admin, RealmModel realm, ResourceModel resourceModel) {
|
||||
public ApplicationResource(UserModel admin, RealmModel realm, ApplicationModel applicationModel) {
|
||||
this.admin = admin;
|
||||
this.realm = realm;
|
||||
this.resourceModel = resourceModel;
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void update(final ResourceRepresentation rep) {
|
||||
public void update(final ApplicationRepresentation rep) {
|
||||
new Transaction() {
|
||||
@Override
|
||||
protected void runImpl() {
|
||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||
resourceManager.updateResource(rep, resourceModel);
|
||||
resourceManager.updateResource(rep, applicationModel);
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
|
@ -57,12 +49,12 @@ public class RealmResourceResource {
|
|||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ResourceRepresentation getResource(final @PathParam("id") String id) {
|
||||
public ApplicationRepresentation getResource(final @PathParam("id") String id) {
|
||||
return new Transaction() {
|
||||
@Override
|
||||
protected ResourceRepresentation callImpl() {
|
||||
protected ApplicationRepresentation callImpl() {
|
||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||
return resourceManager.toRepresentation(resourceModel);
|
||||
return resourceManager.toRepresentation(applicationModel);
|
||||
}
|
||||
}.call();
|
||||
}
|
|
@ -2,11 +2,11 @@ package org.keycloak.services.resources.admin;
|
|||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.representations.idm.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.ResourceManager;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.keycloak.services.resources.Transaction;
|
||||
|
||||
|
@ -14,7 +14,6 @@ import javax.ws.rs.Consumes;
|
|||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@ -29,12 +28,12 @@ import java.util.List;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmResourcesResource {
|
||||
public class ApplicationsResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
|
||||
protected UserModel admin;
|
||||
protected RealmModel realm;
|
||||
|
||||
public RealmResourcesResource(UserModel admin, RealmModel realm) {
|
||||
public ApplicationsResource(UserModel admin, RealmModel realm) {
|
||||
this.admin = admin;
|
||||
this.realm = realm;
|
||||
}
|
||||
|
@ -42,15 +41,15 @@ public class RealmResourcesResource {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@NoCache
|
||||
public List<ResourceRepresentation> getResources() {
|
||||
public List<ApplicationRepresentation> getResources() {
|
||||
return new Transaction() {
|
||||
@Override
|
||||
protected List<ResourceRepresentation> callImpl() {
|
||||
List<ResourceRepresentation> rep = new ArrayList<ResourceRepresentation>();
|
||||
List<ResourceModel> resourceModels = realm.getResources();
|
||||
protected List<ApplicationRepresentation> callImpl() {
|
||||
List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
|
||||
List<ApplicationModel> applicationModels = realm.getApplications();
|
||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||
for (ResourceModel resourceModel : resourceModels) {
|
||||
rep.add(resourceManager.toRepresentation(resourceModel));
|
||||
for (ApplicationModel applicationModel : applicationModels) {
|
||||
rep.add(resourceManager.toRepresentation(applicationModel));
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
@ -59,27 +58,27 @@ public class RealmResourcesResource {
|
|||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response createResource(final @Context UriInfo uriInfo, final ResourceRepresentation rep) {
|
||||
public Response createResource(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
|
||||
return new Transaction() {
|
||||
@Override
|
||||
protected Response callImpl() {
|
||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||
ResourceModel resourceModel = resourceManager.createResource(realm, rep);
|
||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(resourceModel.getId()).build()).build();
|
||||
ApplicationModel applicationModel = resourceManager.createResource(realm, rep);
|
||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build();
|
||||
}
|
||||
}.call();
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
public RealmResourceResource getResource(final @PathParam("id") String id) {
|
||||
public ApplicationResource getResource(final @PathParam("id") String id) {
|
||||
return new Transaction(false) {
|
||||
@Override
|
||||
protected RealmResourceResource callImpl() {
|
||||
ResourceModel resourceModel = realm.getResourceById(id);
|
||||
if (resourceModel == null) {
|
||||
protected ApplicationResource callImpl() {
|
||||
ApplicationModel applicationModel = realm.getApplicationById(id);
|
||||
if (applicationModel == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return new RealmResourceResource(admin, realm, resourceModel);
|
||||
return new ApplicationResource(admin, realm, applicationModel);
|
||||
}
|
||||
}.call();
|
||||
|
|
@ -9,14 +9,11 @@ import org.keycloak.services.managers.RealmManager;
|
|||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.keycloak.services.resources.PublicRealmResource;
|
||||
import org.keycloak.services.resources.Transaction;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.ForbiddenException;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.InternalServerErrorException;
|
||||
import javax.ws.rs.NotAuthorizedException;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
|
@ -24,15 +21,10 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -48,9 +40,9 @@ public class RealmAdminResource {
|
|||
this.realm = realm;
|
||||
}
|
||||
|
||||
@Path("resources")
|
||||
public RealmResourcesResource getResources() {
|
||||
return new RealmResourcesResource(admin, realm);
|
||||
@Path("applications")
|
||||
public ApplicationsResource getResources() {
|
||||
return new ApplicationsResource(admin, realm);
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -60,21 +52,12 @@ public class RealmAdminResource {
|
|||
return new Transaction() {
|
||||
@Override
|
||||
protected RealmRepresentation callImpl() {
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
rep.setId(realm.getId());
|
||||
rep.setRealm(realm.getName());
|
||||
rep.setEnabled(realm.isEnabled());
|
||||
rep.setSslNotRequired(realm.isSslNotRequired());
|
||||
rep.setCookieLoginAllowed(realm.isCookieLoginAllowed());
|
||||
rep.setPublicKey(realm.getPublicKeyPem());
|
||||
rep.setTokenLifespan(realm.getTokenLifespan());
|
||||
rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
|
||||
return rep;
|
||||
return new RealmManager(session).toRepresentation(realm);
|
||||
}
|
||||
}.call();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Path("roles")
|
||||
@GET
|
||||
@NoCache
|
||||
|
@ -94,6 +77,19 @@ public class RealmAdminResource {
|
|||
}.call();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Consumes("application/json")
|
||||
public void updateRealm(final RealmRepresentation rep) {
|
||||
new Transaction() {
|
||||
@Override
|
||||
protected void runImpl() {
|
||||
logger.info("updating realm: " + rep.getRealm());
|
||||
new RealmManager(session).updateRealm(rep, realm);
|
||||
}
|
||||
}.run();
|
||||
|
||||
}
|
||||
|
||||
@Path("roles/{id}")
|
||||
@GET
|
||||
@NoCache
|
||||
|
|
|
@ -28,6 +28,7 @@ import javax.ws.rs.core.Response;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -52,18 +53,18 @@ public class RealmsAdminResource {
|
|||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Response getRealms() {
|
||||
public List<RealmRepresentation> getRealms() {
|
||||
return new Transaction() {
|
||||
@Override
|
||||
protected Response callImpl() {
|
||||
protected List<RealmRepresentation> callImpl() {
|
||||
logger.info(("getRealms()"));
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
List<RealmModel> realms = session.getRealms(admin);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
|
||||
for (RealmModel realm : realms) {
|
||||
map.put(realm.getId(), realm.getName());
|
||||
reps.add(realmManager.toRepresentation(realm));
|
||||
}
|
||||
return Response.ok(new GenericEntity<Map<String, String>>(map){})
|
||||
.cacheControl(noCache).build();
|
||||
return reps;
|
||||
}
|
||||
}.call();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.junit.Before;
|
|||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.models.KeycloakSession;
|
||||
import org.keycloak.services.models.KeycloakSessionFactory;
|
||||
|
@ -18,7 +18,10 @@ import org.keycloak.services.models.UserCredentialModel;
|
|||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -52,6 +55,16 @@ public class AdapterTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMe() {
|
||||
String hello = "Bill Burke";
|
||||
StringTokenizer tokenizer = new StringTokenizer(hello, " ");
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
System.out.println("token: " + tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test1CreateRealm() throws Exception {
|
||||
realmModel = adapter.createRealm("JUGGLER");
|
||||
|
@ -77,26 +90,29 @@ public class AdapterTest {
|
|||
@Test
|
||||
public void test2RequiredCredential() throws Exception {
|
||||
test1CreateRealm();
|
||||
RequiredCredentialModel creds = new RequiredCredentialModel();
|
||||
creds.setSecret(true);
|
||||
creds.setType(RequiredCredentialRepresentation.PASSWORD);
|
||||
creds.setInput(true);
|
||||
realmModel.addRequiredCredential(creds);
|
||||
creds = new RequiredCredentialModel();
|
||||
creds.setSecret(true);
|
||||
creds.setType(RequiredCredentialRepresentation.TOTP);
|
||||
creds.setInput(true);
|
||||
realmModel.addRequiredCredential(creds);
|
||||
realmModel.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
List<RequiredCredentialModel> storedCreds = realmModel.getRequiredCredentials();
|
||||
Assert.assertEquals(1, storedCreds.size());
|
||||
|
||||
Set<String> creds = new HashSet<String>();
|
||||
creds.add(CredentialRepresentation.PASSWORD);
|
||||
creds.add(CredentialRepresentation.TOTP);
|
||||
realmModel.updateRequiredCredentials(creds);
|
||||
storedCreds = realmModel.getRequiredCredentials();
|
||||
Assert.assertEquals(2, storedCreds.size());
|
||||
boolean totp = false;
|
||||
boolean password = false;
|
||||
for (RequiredCredentialModel cred : storedCreds) {
|
||||
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) password = true;
|
||||
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true;
|
||||
Assert.assertTrue(cred.isInput());
|
||||
if (cred.getType().equals(CredentialRepresentation.PASSWORD)) {
|
||||
password = true;
|
||||
Assert.assertTrue(cred.isSecret());
|
||||
}
|
||||
else if (cred.getType().equals(CredentialRepresentation.TOTP)) {
|
||||
totp = true;
|
||||
Assert.assertFalse(cred.isSecret());
|
||||
}
|
||||
}
|
||||
Assert.assertTrue(totp);
|
||||
Assert.assertTrue(password);
|
||||
}
|
||||
|
@ -106,7 +122,7 @@ public class AdapterTest {
|
|||
test1CreateRealm();
|
||||
UserModel user = realmModel.addUser("bburke");
|
||||
UserCredentialModel cred = new UserCredentialModel();
|
||||
cred.setType(RequiredCredentialRepresentation.PASSWORD);
|
||||
cred.setType(CredentialRepresentation.PASSWORD);
|
||||
cred.setValue("geheim");
|
||||
realmModel.updateCredential(user, cred);
|
||||
Assert.assertTrue(realmModel.validatePassword(user, "geheim"));
|
||||
|
|
|
@ -6,18 +6,18 @@ import org.junit.Before;
|
|||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.models.KeycloakSession;
|
||||
import org.keycloak.services.models.KeycloakSessionFactory;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RequiredCredentialModel;
|
||||
import org.keycloak.services.models.ResourceModel;
|
||||
import org.keycloak.services.models.ApplicationModel;
|
||||
import org.keycloak.services.models.RoleModel;
|
||||
import org.keycloak.services.models.UserModel;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
import org.keycloak.services.resources.SaasService;
|
||||
import org.keycloak.services.resources.SaasService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -59,7 +59,7 @@ public class ImportTest {
|
|||
defaultRealm.setCookieLoginAllowed(true);
|
||||
defaultRealm.setRegistrationAllowed(true);
|
||||
manager.generateRealmKeys(defaultRealm);
|
||||
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
|
||||
defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
RoleModel role = defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE);
|
||||
UserModel admin = defaultRealm.addUser("admin");
|
||||
defaultRealm.grantRole(admin, role);
|
||||
|
@ -70,19 +70,44 @@ public class ImportTest {
|
|||
realm.addRealmAdmin(admin);
|
||||
List<RequiredCredentialModel> creds = realm.getRequiredCredentials();
|
||||
Assert.assertEquals(1, creds.size());
|
||||
RequiredCredentialModel cred = creds.get(0);
|
||||
Assert.assertEquals("Password", cred.getFormLabel());
|
||||
|
||||
UserModel user = realm.getUser("loginclient");
|
||||
Assert.assertNotNull(user);
|
||||
Set<String> scopes = realm.getScope(user);
|
||||
System.out.println("Scopes size: " + scopes.size());
|
||||
Assert.assertTrue(scopes.contains("*"));
|
||||
List<ResourceModel> resources = realm.getResources();
|
||||
List<ApplicationModel> resources = realm.getApplications();
|
||||
Assert.assertEquals(2, resources.size());
|
||||
List<RealmModel> realms = identitySession.getRealms(admin);
|
||||
Assert.assertEquals(1, realms.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void install2() throws Exception {
|
||||
RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
|
||||
defaultRealm.setName(RealmModel.DEFAULT_REALM);
|
||||
defaultRealm.setEnabled(true);
|
||||
defaultRealm.setTokenLifespan(300);
|
||||
defaultRealm.setAccessCodeLifespan(60);
|
||||
defaultRealm.setSslNotRequired(false);
|
||||
defaultRealm.setCookieLoginAllowed(true);
|
||||
defaultRealm.setRegistrationAllowed(true);
|
||||
manager.generateRealmKeys(defaultRealm);
|
||||
defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
RoleModel role = defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE);
|
||||
UserModel admin = defaultRealm.addUser("admin");
|
||||
defaultRealm.grantRole(admin, role);
|
||||
|
||||
RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm-demo.json");
|
||||
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
||||
manager.importRealm(rep, realm);
|
||||
realm.addRealmAdmin(admin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.test;
|
||||
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RequiredCredentialModel;
|
||||
|
@ -21,7 +22,7 @@ public class InstallationManager {
|
|||
defaultRealm.setCookieLoginAllowed(true);
|
||||
defaultRealm.setRegistrationAllowed(true);
|
||||
manager.generateRealmKeys(defaultRealm);
|
||||
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
|
||||
defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue