user panels and query

This commit is contained in:
Bill Burke 2013-08-12 09:41:55 -04:00
parent 5b03b56c4a
commit 38300f3e7f
14 changed files with 298 additions and 81 deletions

View file

@ -55,9 +55,6 @@ module.config([ '$routeProvider', function($routeProvider) {
resolve : {
realm : function(RealmLoader) {
return RealmLoader();
},
users : function(UserListLoader) {
return UserListLoader();
}
},
controller : 'UserListCtrl'

View file

@ -181,15 +181,39 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $ht
});
module.controller('UserListCtrl', function($scope, realm, users) {
module.controller('UserListCtrl', function($scope, realm, User) {
$scope.realm = realm;
$scope.users = users;
$scope.users = [];
$scope.query = "*";
$scope.attribute = {};
var params = {};
$scope.addAttribute = function() {
console.log('queryAttribute');
params[$scope.attribute.name] = $scope.attribute.value;
for (var key in params) {
$scope.query = " " + key + "=" +params[key];
}
};
$scope.executeQuery = function() {
console.log('executeQuery');
var parameters = angular.copy(params);
parameters["realm"] = realm.id;
$scope.users = User.query(parameters);
};
$scope.clearQuery = function() {
params = {};
$scopre.query = "*";
$scope.users = [];
};
});
module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) {
$scope.realm = realm;
$scope.user = angular.copy(user);
$scope.create = !user.userId;
$scope.create = !user.username;
$scope.changed = $scope.create;
@ -201,22 +225,27 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
$scope.save = function() {
if ($scope.userForm.$valid) {
if ($scope.create) {
User.save({
realm : realm.id
}, $scope.user, function() {
realm: realm.id
}, $scope.user, function () {
$scope.changed = false;
user = angular.copy($scope.user);
if ($scope.create) {
$location.url("/realms/" + realm.id + "/users/" + $scope.user.userId);
$location.url("/realms/" + realm.id + "/users/" + $scope.user.username);
Notifications.success("Created user");
} else {
Notifications.success("Saved changes to user");
}
});
} else {
User.update({
realm: realm.id,
userId: $scope.user.username
}, $scope.user, function () {
$scope.changed = false;
user = angular.copy($scope.user);
Notifications.success("Saved changes to user");
});
}
} else {
$scope.userForm.showErrors = true;
}
@ -236,7 +265,7 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
Dialog.confirmDelete($scope.user.userId, 'user', function() {
$scope.user.$remove({
realm : realm.id,
userId : $scope.user.userId
userId : $scope.user.username
}, function() {
$location.url("/realms/" + realm.id + "/users");
Notifications.success("Deleted user");

View file

@ -110,11 +110,11 @@ module.factory('RoleMapping', function($resource) {
});
module.factory('User', function($resource) {
return $resource('/keycloak-server/ui/api/realms/:realm/users/:userId', {
return $resource('/auth-server/rest/saas/admin/realms/:realm/users/:userId', {
realm : '@realm',
userId : '@userId'
}, {
save : {
update : {
method : 'PUT'
}
});

View file

@ -6,7 +6,7 @@
<li data-ng-class="path[0] == 'create' && path[1] == 'user' && 'active'"><a
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>
href="#/realms/{{realm.id}}/users">Find User</a></li>
</ul>
</li>
<li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{realm.id}}/roles">Roles</a>

View file

@ -13,13 +13,13 @@
<div data-ng-show="roleForm.showErrors && roleForm.$error.required" class="alert alert-error">Please fill in
all required fields
</div>
<p class="subtitle subtitle-right"><span class="required">*</span> Required fields</p>
<p class="subtitle subtitle-right" data-ng-show="create"><span class="required">*</span> Required fields</p>
<form class="form-horizontal" name="roleForm" novalidate>
<fieldset>
<legend>Details</legend>
<div class="control-group">
<label class="control-label" for="name">Role name <span class="required">*</span></label>
<label class="control-label" for="name">Role name <span class="required" data-ng-show="create">*</span></label>
<div class="controls">
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="role.name"

View file

@ -4,8 +4,6 @@
<div id="actions-bg"></div>
<div id="container-right" class="span9">
<a class="btn btn-small pull-right" href="#/create/role/{{realm.id}}">Add Role</a>
<h1>
<span class="gray">Realm Roles</span>
</h1>

View file

@ -7,26 +7,35 @@
<h1 data-ng-show="create"><span class="gray">New User</span></h1>
<h1 data-ng-hide="create">
<span class="gray">{{user.userId}}</span> configuration
<span class="gray">User {{user.username}}</span>
</h1>
<div data-ng-show="userForm.showErrors && userForm.$error.required" class="alert alert-error">Please fill in
all required fields
</div>
<p class="subtitle subtitle-right"><span class="required">*</span> Required fields</p>
<p class="subtitle subtitle-right" data-ng-show="create"><span class="required">*</span> Required fields</p>
<form class="form-horizontal" name="userForm" novalidate>
<fieldset>
<legend>Details</legend>
<div class="control-group">
<label class="control-label" for="name">Username <span class="required">*</span></label>
<label class="control-label" for="name">Username <span class="required" data-ng-show="create">*</span></label>
<div class="controls">
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="user.userId"
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="user.username"
autofocus required data-ng-readonly="!create">
</div>
</div>
<div class="control-group">
<label class="control-label">Enabled</label>
<div class="controls">
<input class="input-xlarge" type="checkbox" name="enabled"
data-ng-model="realm.enabled">
</div>
</div>
<div class="control-group">
<label class="control-label" for="email">Email </label>
@ -52,15 +61,6 @@
<input type="text" class="input-xlarge" id="lastName" data-ng-model="user.lastName">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">Password <span class="required">*</span></label>
<div class="controls">
<input type="password" class="input-xlarge" id="password" name="password"
data-ng-model="user.password" data-ng-required="create">
</div>
</div>
</fieldset>
<fieldset data-ng-show="user.attributes.length > 0">
@ -94,7 +94,6 @@
</button>
<button type="submit" data-ng-click="reset()" class="btn" data-ng-show="changed">Clear changes
</button>
<a href="#/realms/{{realm.id}}/users" data-ng-hide="changed">View users &#187;</a>
<button type="submit" data-ng-click="remove()" class="btn btn-danger" data-ng-hide="changed">
Delete
</button>

View file

@ -3,13 +3,42 @@
<aside class="span3" data-ng-include data-src="'partials/realm-menu.html'"></aside>
<div id="actions-bg"></div>
<div id="container-right" class="span9">
<a class="btn btn-small pull-right" href="#/create/user/{{realm.id}}">Add User</a>
<form class="form-horizontal" name="queryForm" novalidate>
<div class="control-group">
<label class="control-label">Query </label>
<h1>
<span class="gray">{{realm.name}}</span> users
</h1>
<div class="controls">
<input type="text" class="input-xlarge" id="query" name="query" data-ng-model="query"
autofocus required readonly>
<button type="submit" data-ng-click="executeQuery()" class="btn btn-primary">Execute Query
</button>
</div>
</div>
</form>
<form class="form-horizontal" name="queryAttribute" novalidate>
<fieldset>
<div class="control-group">
<label class="control-label">Predefined Attribute</label>
<div class="controls">
<select style="width: auto;" name="name"
data-ng-model="attribute.name">
<option value="loginName">Login name</option>
<option value="lastName">Last name</option>
<option value="firstName">First name</option>
<option value="email">Email</option>
</select>
<input class="input-small" type="text" name="value"
data-ng-model="attribute.value">
<button type="submit" data-ng-click="addAttribute()" class="btn btn-primary">Add Attribute
</button>
</div>
</div>
</fieldset>
</form>
<table class="table table-striped table-bordered">
<thead>
<tr>
@ -20,7 +49,7 @@
</tr>
</thead>
<tr data-ng-repeat="user in users">
<td><a href="#/realms/{{realm.id}}/users/{{user.userId}}">{{user.userId}}</a></td>
<td><a href="#/realms/{{realm.id}}/users/{{user.username}}">{{user.username}}</a></td>
<td>{{user.firstName}}</td>
<td>{{user.lastName}}</td>
<td>{{user.email}}</td>

View file

@ -131,10 +131,10 @@ public class RealmManager {
}
UserManager userManager = new UserManager();
if (rep.getUsers() != null) {
for (UserRepresentation userRep : rep.getUsers()) {
UserModel user = createUser(newRealm, userRep);
UserModel user = userManager.createUser(newRealm, userRep);
userMap.put(user.getLoginName(), user);
}
}
@ -182,24 +182,6 @@ public class RealmManager {
if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
}
public UserModel createUser(RealmModel newRealm, UserRepresentation userRep) {
UserModel user = newRealm.addUser(userRep.getUsername());
user.setEnabled(userRep.isEnabled());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(entry.getKey(), entry.getValue());
}
}
if (userRep.getCredentials() != null) {
for (CredentialRepresentation cred : userRep.getCredentials()) {
UserCredentialModel credential = new UserCredentialModel();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
newRealm.updateCredential(user, credential);
}
}
return user;
}
public void addRequiredCredential(RealmModel newRealm, String requiredCred) {
newRealm.addRequiredCredential(requiredCred);

View file

@ -0,0 +1,89 @@
package org.keycloak.services.managers;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.UserModel;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserManager {
public static UserRepresentation toRepresentation(UserModel user) {
UserRepresentation rep = new UserRepresentation();
rep.setEmail(user.getEmail());
rep.setLastName(user.getLastName());
rep.setFirstName(user.getFirstName());
rep.setEnabled(user.isEnabled());
rep.setUsername(user.getLoginName());
for (Map.Entry<String, String> entry : user.getAttributes().entrySet()) {
rep.attribute(entry.getKey(), entry.getValue());
}
return rep;
}
public UserModel createUser(RealmModel newRealm, UserRepresentation userRep) {
UserModel user = newRealm.addUser(userRep.getUsername());
user.setEnabled(userRep.isEnabled());
user.setEmail(userRep.getEmail());
user.setFirstName(userRep.getFirstName());
user.setLastName(userRep.getLastName());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(entry.getKey(), entry.getValue());
}
}
if (userRep.getCredentials() != null) {
for (CredentialRepresentation cred : userRep.getCredentials()) {
UserCredentialModel credential = new UserCredentialModel();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
newRealm.updateCredential(user, credential);
}
}
return user;
}
/**
* Doesn't allow you to change loginname.
*
* @param user
* @param userRep
*/
public void updateUserAsAdmin(UserModel user, UserRepresentation userRep) {
user.setEnabled(userRep.isEnabled());
user.setEmail(userRep.getEmail());
user.setFirstName(userRep.getFirstName());
user.setLastName(userRep.getLastName());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(entry.getKey(), entry.getValue());
}
}
}
/**
* Doesn't allow you to change loginname.
* Doesn't allow you to change enable
*
* @param user
* @param userRep
*/
public void updateUserAsUser(UserModel user, UserRepresentation userRep) {
user.setEmail(userRep.getEmail());
user.setFirstName(userRep.getFirstName());
user.setLastName(userRep.getLastName());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(entry.getKey(), entry.getValue());
}
}
}
}

View file

@ -124,4 +124,6 @@ public interface RealmModel {
boolean isSocial();
void setSocial(boolean social);
List<UserModel> queryUsers(Map<String, String> parameters);
}

View file

@ -7,6 +7,10 @@ import java.util.Map;
* @version $Revision: 1 $
*/
public interface UserModel {
public static final String LAST_NAME = "lastName";
public static final String FIRST_NAME = "firstName";
public static final String EMAIL = "email";
String getLoginName();
boolean isEnabled();

View file

@ -25,6 +25,7 @@ import org.picketlink.idm.credential.TOTPCredential;
import org.picketlink.idm.credential.TOTPCredentials;
import org.picketlink.idm.credential.UsernamePasswordCredentials;
import org.picketlink.idm.credential.X509CertificateCredentials;
import org.picketlink.idm.model.AttributedType;
import org.picketlink.idm.model.IdentityType;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.sample.Grant;
@ -476,6 +477,21 @@ public class RealmAdapter implements RealmModel {
return new UserAdapter(user, getIdm());
}
@Override
public List<UserModel> queryUsers(Map<String, String> parameters) {
IdentityQuery<User> userQuery = getIdm().createIdentityQuery(User.class);
for (Map.Entry<String, String> entry : parameters.entrySet()) {
userQuery.setParameter(AttributedType.QUERY_ATTRIBUTE.byName(entry.getKey()), entry.getValue());
}
List<User> users = userQuery.getResultList();
List<UserModel> userModels = new ArrayList<UserModel>();
for (User user : users) {
userModels.add(new UserAdapter(user, getIdm()));
}
return userModels;
}
@Override
public RoleAdapter getRole(String name) {
Role role = SampleModel.getRole(getIdm(), name);

View file

@ -6,25 +6,21 @@ import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.UserManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
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.InternalServerErrorException;
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.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
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>
@ -62,7 +58,7 @@ public class RealmAdminResource {
@GET
@NoCache
@Produces("application/json")
public List<RoleRepresentation> getRoles() {
public List<RoleRepresentation> queryRoles() {
return new Transaction() {
@Override
protected List<RoleRepresentation> callImpl() {
@ -70,6 +66,7 @@ public class RealmAdminResource {
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
for (RoleModel roleModel : roleModels) {
RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
role.setId(roleModel.getId());
roles.add(role);
}
return roles;
@ -154,11 +151,86 @@ public class RealmAdminResource {
@GET
@NoCache
@Produces("application/json")
public List<UserRepresentation> getUsers() {
return null;
public List<UserRepresentation> queryUsers(final @Context UriInfo uriInfo) {
return new Transaction() {
@Override
protected List<UserRepresentation> callImpl() {
logger.info("queryUsers");
Map<String, String> params = new HashMap<String, String>();
MultivaluedMap<String,String> queryParameters = uriInfo.getQueryParameters();
for (String key : queryParameters.keySet()) {
logger.info(" " + key + "=" + queryParameters.getFirst(key));
params.put(key, queryParameters.getFirst(key));
}
List<UserModel> userModels = realm.queryUsers(params);
List<UserRepresentation> users = new ArrayList<UserRepresentation>();
for (UserModel userModel : userModels) {
users.add(UserManager.toRepresentation(userModel));
}
logger.info(" resultSet: " + users.size());
return users;
}
}.call();
}
@Path("users/{loginName}")
@GET
@NoCache
@Produces("application/json")
public UserRepresentation getUser(final @PathParam("loginName") String loginName) {
return new Transaction() {
@Override
protected UserRepresentation callImpl() {
UserModel userModel = realm.getUser(loginName);
if (userModel == null) {
throw new NotFoundException();
}
return UserManager.toRepresentation(userModel);
}
}.call();
}
@Path("users")
@POST
@NoCache
@Consumes("application/json")
public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) {
return new Transaction() {
@Override
protected Response callImpl() {
if (realm.getUser(rep.getUsername()) != null) {
return Response.status(Response.Status.FOUND).build();
}
rep.setCredentials(null); // don't allow credential creation
UserManager userManager = new UserManager();
UserModel userModel = userManager.createUser(realm, rep);
return Response.created(uriInfo.getAbsolutePathBuilder().path(userModel.getLoginName()).build()).build();
}
}.call();
}
@Path("users/{loginName}")
@PUT
@NoCache
@Consumes("application/json")
public void updateUser(final @PathParam("loginName") String loginName, final UserRepresentation rep) {
new Transaction() {
@Override
protected void runImpl() {
UserModel userModel = realm.getUser(loginName);
if (userModel == null) {
throw new NotFoundException();
}
UserManager userManager = new UserManager();
userManager.updateUserAsAdmin(userModel, rep);
}
}.run();
}
}