commit
7f08717dfb
10 changed files with 132 additions and 5 deletions
|
@ -206,6 +206,18 @@ public class RealmAdminResource {
|
|||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base path for managing components under this realm.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Path("components")
|
||||
public ComponentResource getComponents() {
|
||||
ComponentResource resource = new ComponentResource(realm, auth, adminEvent);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* base path for managing realm-level roles of this realm
|
||||
*
|
||||
|
|
|
@ -52,7 +52,7 @@ public class UserPropertyFileStorage implements UserLookupProvider, UserStorageP
|
|||
this.session = session;
|
||||
this.model = model;
|
||||
this.userPasswords = userPasswords;
|
||||
this.federatedStorageEnabled = model.getConfig().containsKey("USER_FEDERATED_STORAGE");
|
||||
this.federatedStorageEnabled = model.getConfig().containsKey("federatedStorage") && Boolean.valueOf(model.getConfig().getFirst("federatedStorage")).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,9 +20,12 @@ import org.keycloak.Config;
|
|||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.storage.UserStorageProviderFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +41,7 @@ public class UserPropertyFileStorageFactory implements UserStorageProviderFactor
|
|||
public UserPropertyFileStorage create(KeycloakSession session, ComponentModel model) {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(getClass().getResourceAsStream(model.getConfig().getFirst("property.file")));
|
||||
props.load(getClass().getResourceAsStream(model.getConfig().getFirst("propertyFile")));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -50,6 +53,19 @@ public class UserPropertyFileStorageFactory implements UserStorageProviderFactor
|
|||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
static List<ProviderConfigProperty> OPTIONS = new LinkedList<>();
|
||||
static {
|
||||
ProviderConfigProperty prop = new ProviderConfigProperty("propertyFile", "Property File", "file that contains name value pairs", ProviderConfigProperty.STRING_TYPE, null);
|
||||
OPTIONS.add(prop);
|
||||
prop = new ProviderConfigProperty("federatedStorage", "User Federated Storage", "use federated storage?", ProviderConfigProperty.BOOLEAN_TYPE, null);
|
||||
OPTIONS.add(prop);
|
||||
|
||||
}
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return OPTIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
|
|
|
@ -67,15 +67,15 @@ public class UserStorageTest {
|
|||
model.setPriority(1);
|
||||
model.setProviderId(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
model.setParentId(appRealm.getId());
|
||||
model.getConfig().putSingle("property.file", "/storage-test/read-only-user-password.properties");
|
||||
model.getConfig().putSingle("propertyFile", "/storage-test/read-only-user-password.properties");
|
||||
appRealm.addComponentModel(model);
|
||||
model = new UserStorageProviderModel();
|
||||
model.setName("user-props");
|
||||
model.setPriority(2);
|
||||
model.setParentId(appRealm.getId());
|
||||
model.setProviderId(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
model.getConfig().putSingle("property.file", "/storage-test/user-password.properties");
|
||||
model.getConfig().putSingle("USER_FEDERATED_STORAGE", "true");
|
||||
model.getConfig().putSingle("propertyFile", "/storage-test/user-password.properties");
|
||||
model.getConfig().putSingle("federatedStorage", "true");
|
||||
appRealm.addComponentModel(model);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -585,6 +585,7 @@ add-client-template=Add client template
|
|||
manage=Manage
|
||||
authentication=Authentication
|
||||
user-federation=User Federation
|
||||
user-storage=User Storage
|
||||
events=Events
|
||||
realm-settings=Realm Settings
|
||||
configure=Configure
|
||||
|
@ -687,6 +688,7 @@ create-user-federation-mapper=Create user federation mapper
|
|||
add-user-federation-mapper=Add user federation mapper
|
||||
provider-name=Provider Name
|
||||
no-user-federation-providers-configured=No user federation providers configured
|
||||
no-user-storage-providers-configured=No user storage providers configured
|
||||
add-identity-provider=Add identity provider
|
||||
add-identity-provider-link=Add identity provider link
|
||||
identity-provider=Identity Provider
|
||||
|
|
|
@ -1338,6 +1338,18 @@ module.config([ '$routeProvider', function($routeProvider) {
|
|||
},
|
||||
controller : 'RealmSessionStatsCtrl'
|
||||
})
|
||||
.when('/realms/:realm/user-storage', {
|
||||
templateUrl : resourceUrl + '/partials/user-storage.html',
|
||||
resolve : {
|
||||
realm : function(RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
serverInfo : function(ServerInfoLoader) {
|
||||
return ServerInfoLoader();
|
||||
}
|
||||
},
|
||||
controller : 'UserStorageCtrl'
|
||||
})
|
||||
.when('/realms/:realm/user-federation', {
|
||||
templateUrl : resourceUrl + '/partials/user-federation.html',
|
||||
resolve : {
|
||||
|
|
|
@ -592,6 +592,34 @@ module.controller('UserCredentialsCtrl', function($scope, realm, user, RequiredA
|
|||
};
|
||||
});
|
||||
|
||||
module.controller('UserStorageCtrl', function($scope, $location, $route, realm, serverInfo, Components, Notifications, Dialog) {
|
||||
console.log('UserStorageCtrl ++++****');
|
||||
$scope.realm = realm;
|
||||
$scope.providers = serverInfo.componentTypes['org.keycloak.storage.UserStorageProvider'];
|
||||
|
||||
$scope.addProvider = function(provider) {
|
||||
console.log('Add provider: ' + provider.id);
|
||||
$location.url("/create/user-storage/" + realm.realm + "/providers/" + provider.id);
|
||||
};
|
||||
|
||||
$scope.instances = Components.query({realm: realm.realm,
|
||||
parent: realm.id,
|
||||
type: 'org.keycloak.storage.UserStorageProvider'
|
||||
});
|
||||
|
||||
$scope.removeUserStorage = function(instance) {
|
||||
Dialog.confirmDelete(instance.name, 'user storage provider', function() {
|
||||
Components.remove({
|
||||
realm : realm.realm,
|
||||
componentId : instance.id
|
||||
}, function() {
|
||||
$route.reload();
|
||||
Notifications.success("The provider has been deleted.");
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.controller('UserFederationCtrl', function($scope, $location, $route, realm, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
|
||||
console.log('UserFederationCtrl ++++****');
|
||||
$scope.realm = realm;
|
||||
|
|
|
@ -1629,3 +1629,16 @@ module.factory('DefaultGroups', function($resource) {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('Components', function($resource) {
|
||||
return $resource(authUrl + '/admin/realms/:realm/components/:componentId', {
|
||||
realm : '@realm',
|
||||
componentId : '@componentId'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
|
||||
<h1>
|
||||
<span>{{:: 'user-federation' | translate}}</span>
|
||||
</h1>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr ng-show="providers.length > 0 && access.manageUsers">
|
||||
<th colspan="5" class="kc-table-actions">
|
||||
<div class="pull-right">
|
||||
<div>
|
||||
<select class="form-control" ng-model="selectedProvider"
|
||||
ng-options="p.id for p in providers"
|
||||
data-ng-change="addProvider(selectedProvider); selectedProvider = null">
|
||||
<option value="" disabled selected>{{:: 'add-provider.placeholder' | translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr data-ng-show="instances && instances.length > 0">
|
||||
<th>{{:: 'id' | translate}}</th>
|
||||
<th>{{:: 'provider-name' | translate}}</th>
|
||||
<th>{{:: 'priority' | translate}}</th>
|
||||
<th colspan="2">{{:: 'actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="instance in instances">
|
||||
<td><a href="#/realms/{{realm.realm}}/user-storage/providers/{{instance.providerId}}/{{instance.id}}">{{instance.name}}</a></td>
|
||||
<td>{{instance.providerId|capitalize}}</td>
|
||||
<td>{{instance.config['priority'][0]}}</td>
|
||||
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/user-storage/providers/{{instance.providerId}}/{{instance.id}}">{{:: 'edit' | translate}}</td>
|
||||
<td class="kc-action-cell" data-ng-click="removeUserStorage(instance)">{{:: 'delete' | translate}}</td>
|
||||
</tr>
|
||||
<tr data-ng-show="!instances || instances.length == 0">
|
||||
<td class="text-muted">{{:: 'no-user-storage-providers-configured' | translate}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<kc-menu></kc-menu>
|
|
@ -34,6 +34,7 @@
|
|||
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || path[2] == 'default-roles' || (path[1] == 'role' && path[3] != 'clients')) && 'active'"><a href="#/realms/{{realm.realm}}/roles"><i class="fa fa-tasks"></i> {{:: 'roles' | translate}}</a></li>
|
||||
<li data-ng-show="access.viewIdentityProviders" data-ng-class="(path[2] == 'identity-provider-settings' || path[2] == 'identity-provider-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> {{:: 'identity-providers' | translate}}</a></li>
|
||||
<li data-ng-show="access.viewUsers" data-ng-class="(path[1] == 'user-federation' || path[2] == 'user-federation') && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> {{:: 'user-federation' | translate}}</a></li>
|
||||
<!-- <li data-ng-show="access.viewUsers" data-ng-class="(path[1] == 'user-storage' || path[2] == 'user-storage') && 'active'"><a href="#/realms/{{realm.realm}}/user-storage"><i class="fa fa-database"></i> {{:: 'user-storage' | translate}}</a></li> -->
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'authentication' || path[2] == 'authentication') && 'active'"><a href="#/realms/{{realm.realm}}/authentication/flows"><i class="fa fa-lock"></i> {{:: 'authentication' | translate}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue