Skip to content

Commit

Permalink
feat(jans-config-api): user mgmt endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
pujavs committed Mar 31, 2022
1 parent 0ea10fd commit f98c59e
Show file tree
Hide file tree
Showing 7 changed files with 723 additions and 97 deletions.
6 changes: 3 additions & 3 deletions jans-config-api/profiles/local/test.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#LOCAL
test.scopes=https://jans.io/oauth/config/acrs.readonly https://jans.io/oauth/config/acrs.write https://jans.io/oauth/config/attributes.readonly https://jans.io/oauth/config/attributes.write https://jans.io/oauth/config/attributes.delete https://jans.io/oauth/config/cache.readonly https://jans.io/oauth/config/cache.write https://jans.io/oauth/config/openid/clients.readonly https://jans.io/oauth/config/openid/clients.write https://jans.io/oauth/config/openid/clients.delete https://jans.io/oauth/jans-auth-server/config/properties.readonly https://jans.io/oauth/jans-auth-server/config/properties.write https://jans.io/oauth/config/smtp.readonly https://jans.io/oauth/config/smtp.write https://jans.io/oauth/config/smtp.delete https://jans.io/oauth/config/database/couchbase.readonly https://jans.io/oauth/config/database/couchbase.write https://jans.io/oauth/config/database/couchbase.delete https://jans.io/oauth/config/scripts.readonly https://jans.io/oauth/config/scripts.write https://jans.io/oauth/config/scripts.delete https://jans.io/oauth/config/fido2.readonly https://jans.io/oauth/config/fido2.write https://jans.io/oauth/config/jwks.readonly https://jans.io/oauth/config/jwks.write https://jans.io/oauth/config/database/ldap.readonly https://jans.io/oauth/config/database/ldap.write https://jans.io/oauth/config/database/ldap.delete https://jans.io/oauth/config/logging.readonly https://jans.io/oauth/config/logging.write https://jans.io/oauth/config/scopes.readonly https://jans.io/oauth/config/scopes.write https://jans.io/oauth/config/scopes.delete https://jans.io/oauth/config/uma/resources.readonly https://jans.io/oauth/config/uma/resources.write https://jans.io/oauth/config/uma/resources.delete https://jans.io/oauth/config/database/sql.readonly https://jans.io/oauth/config/database/sql.write https://jans.io/oauth/config/database/sql.delete https://jans.io/oauth/config/stats.readonly jans_stat https://jans.io/scim/users.read https://jans.io/scim/users.write https://jans.io/oauth/config/scim/users.read https://jans.io/oauth/config/scim/users.write https://jans.io/scim/config.readonly https://jans.io/scim/config.write https://jans.io/oauth/config/organization.readonly https://jans.io/oauth/config/organization.write
test.scopes=https://jans.io/oauth/config/acrs.readonly https://jans.io/oauth/config/acrs.write https://jans.io/oauth/config/attributes.readonly https://jans.io/oauth/config/attributes.write https://jans.io/oauth/config/attributes.delete https://jans.io/oauth/config/cache.readonly https://jans.io/oauth/config/cache.write https://jans.io/oauth/config/openid/clients.readonly https://jans.io/oauth/config/openid/clients.write https://jans.io/oauth/config/openid/clients.delete https://jans.io/oauth/jans-auth-server/config/properties.readonly https://jans.io/oauth/jans-auth-server/config/properties.write https://jans.io/oauth/config/smtp.readonly https://jans.io/oauth/config/smtp.write https://jans.io/oauth/config/smtp.delete https://jans.io/oauth/config/database/couchbase.readonly https://jans.io/oauth/config/database/couchbase.write https://jans.io/oauth/config/database/couchbase.delete https://jans.io/oauth/config/scripts.readonly https://jans.io/oauth/config/scripts.write https://jans.io/oauth/config/scripts.delete https://jans.io/oauth/config/fido2.readonly https://jans.io/oauth/config/fido2.write https://jans.io/oauth/config/jwks.readonly https://jans.io/oauth/config/jwks.write https://jans.io/oauth/config/database/ldap.readonly https://jans.io/oauth/config/database/ldap.write https://jans.io/oauth/config/database/ldap.delete https://jans.io/oauth/config/logging.readonly https://jans.io/oauth/config/logging.write https://jans.io/oauth/config/scopes.readonly https://jans.io/oauth/config/scopes.write https://jans.io/oauth/config/scopes.delete https://jans.io/oauth/config/uma/resources.readonly https://jans.io/oauth/config/uma/resources.write https://jans.io/oauth/config/uma/resources.delete https://jans.io/oauth/config/database/sql.readonly https://jans.io/oauth/config/database/sql.write https://jans.io/oauth/config/database/sql.delete https://jans.io/oauth/config/stats.readonly jans_stat https://jans.io/scim/users.read https://jans.io/scim/users.write https://jans.io/oauth/config/scim/users.read https://jans.io/oauth/config/scim/users.write https://jans.io/scim/config.readonly https://jans.io/scim/config.write https://jans.io/oauth/config/organization.readonly https://jans.io/oauth/config/organization.write https://jans.io/oauth/config/user.readonly https://jans.io/oauth/config/user.write https://jans.io/oauth/config/user.delete

# Test env Setting
#token.endpoint=https://jenkins-config-api.gluu.org/jans-auth/restv1/token
Expand Down Expand Up @@ -70,6 +70,6 @@ test.scopes=https://jans.io/oauth/config/acrs.readonly https://jans.io/oauth/con
# jans.server
token.endpoint=https://jans.server/jans-auth/restv1/token
token.grant.type=client_credentials
test.client.id=1800.77e9a8e6-8fee-4b86-b294-017ba6ab2112
test.client.secret=dobHjXDhH6zh
test.client.id=1800.579122e0-7c35-4a68-80ad-a3121a5abf1e
test.client.secret=ljVYGAQUzUol
test.issuer=https://jans.server
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public Set<Class<?>> getClasses() {
classes.add(HealthCheckResource.class);
classes.add(OrganizationResource.class);
classes.add(SqlConfigurationResource.class);
classes.add(UserResource.class);

return classes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,44 @@

import com.github.fge.jsonpatch.JsonPatchException;
import static io.jans.as.model.util.Util.escapeLog;
import io.jans.as.common.model.common.User;
//import io.jans.configapi.rest.model.user.User;
import io.jans.as.common.service.common.EncryptionService;
import io.jans.as.common.service.common.InumService;
import io.jans.as.common.model.common.User;
import io.jans.configapi.core.rest.ProtectedApi;
import io.jans.configapi.rest.model.SearchRequest;
import io.jans.configapi.service.auth.UserService;
import io.jans.configapi.service.auth.ConfigurationService;
import io.jans.configapi.util.ApiAccessConstants;
import io.jans.configapi.util.ApiConstants;
import io.jans.configapi.util.AttributeNames;
import io.jans.configapi.core.util.Jackson;
import io.jans.orm.PersistenceEntryManager;
import io.jans.orm.model.PagedResult;
import io.jans.util.StringHelper;
import io.jans.util.security.StringEncrypter.EncryptionException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.slf4j.Logger;

import org.slf4j.Logger;

@Path(ApiConstants.USER)
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApplicationScoped
public class UserResource extends BaseResource {

private static final String USER = "user";

@Inject
Logger logger;

@Inject
UserService userSrv;

@Inject
ConfigurationService configurationService;

@Inject
private InumService inumService;

@Inject
EncryptionService encryptionService;

@GET
@ProtectedApi(scopes = { ApiAccessConstants.USER_READ_ACCESS })
Expand All @@ -76,107 +60,73 @@ public Response getOpenIdConnectClients(
escapeLog(limit), escapeLog(pattern), escapeLog(startIndex), escapeLog(sortBy),
escapeLog(sortOrder));
}
logger.error("User serach param - limit:{}, pattern:{}, startIndex:{}, sortBy:{}, sortOrder:{}",
escapeLog(limit), escapeLog(pattern), escapeLog(startIndex), escapeLog(sortBy), escapeLog(sortOrder));

SearchRequest searchReq = createSearchRequest(userSrv.getPeopleBaseDn(), pattern, sortBy, sortOrder,
startIndex, limit, null, null);
SearchRequest searchReq = createSearchRequest(userSrv.getPeopleBaseDn(), pattern, sortBy, sortOrder, startIndex,
limit, null, null);

final List<User> users = this.doSearch(searchReq);
logger.trace("User serach result:{}", users);
return Response.ok(getUsers(users)).build();
logger.error("User serach result:{}", users);
return Response.ok(users).build();
}

@GET
@ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_READ_ACCESS })
@ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS })
@Path(ApiConstants.INUM_PATH)
public Response getUserByInum(@PathParam(ApiConstants.INUM) @NotNull String inum) {
if (logger.isDebugEnabled()) {
logger.debug("User serach by inum:{}", escapeLog(inum));
}
User user = userSrv.getUserByInum(inum);
checkResourceNotNull(user, USER);
logger.error("Based on inum:{}, user:{}", inum, user);
return Response.ok(user).build();
}

/* @POST
@ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_WRITE_ACCESS })
@POST
@ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS })
public Response createOpenIdConnect(@Valid User user) throws EncryptionException {
if (logger.isDebugEnabled()) {
logger.debug("User details to be added - user:{}", escapeLog(user));
}
String inum = user.getUserId();
if (inum == null || inum.isEmpty() || inum.isBlank()) {
inum = inumService.generateClientInum();
user.setUserId(inum);
}
checkNotNull(user., AttributeNames.DISPLAY_NAME);
String clientSecret = client.getClientSecret();
if (StringHelper.isEmpty(clientSecret)) {
clientSecret = generatePassword();
}

client.setClientSecret(encryptionService.encrypt(clientSecret));
client.setDn(userSrv.getDnForClient(inum));
client.setDeletable(client.getClientSecretExpiresAt() != null);
ignoreCustomObjectClassesForNonLDAP(client);
logger.debug("Final Client details to be added - client:{}", client);
userSrv.addClient(user);
User result = userSrv.getUserByInum(inum);
result.setClientSecret(encryptionService.decrypt(result.getClientSecret()));
return Response.status(Response.Status.CREATED).entity(result).build();
user = userSrv.addUser(user, true);
logger.error("User created {}", user);
return Response.status(Response.Status.CREATED).entity(user).build();
}

@PUT
@ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_WRITE_ACCESS })
@ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS })
public Response updateUser(@Valid User user) throws EncryptionException {
if (logger.isDebugEnabled()) {
logger.debug("User details to be updated - user:{}", escapeLog(user));
}
String inum = client.getClientId();
checkNotNull(inum, AttributeNames.INUM);
checkNotNull(client.getClientName(), AttributeNames.DISPLAY_NAME);
Client existingClient = userSrv.getClientByInum(inum);
checkResourceNotNull(existingClient, USER);
client.setClientId(existingClient.getClientId());
client.setBaseDn(userSrv.getDnForClient(inum));
client.setDeletable(client.getExpirationDate() != null);
if (client.getClientSecret() != null) {
client.setClientSecret(encryptionService.encrypt(client.getClientSecret()));
}
ignoreCustomObjectClassesForNonLDAP(client);
logger.debug("Final Client details to be updated - user:{}", user);
userSrv.updateClient(client);
User result = userSrv.getClientByInum(existingClient.getClientId());
result.setClientSecret(encryptionService.decrypt(client.getClientSecret()));
return Response.ok(result).build();
}
user = userSrv.updateUser(user);
logger.debug("Updated user:{}", user);

return Response.ok(user).build();
}

@PATCH
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
@ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_WRITE_ACCESS })
@ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS })
@Path(ApiConstants.INUM_PATH)
public Response patchUser(@PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString)
throws JsonPatchException, IOException {
if (logger.isDebugEnabled()) {
logger.debug("User details to be patched - inum:{}, pathString:{}", escapeLog(inum),
escapeLog(pathString));
logger.debug("User details to be patched - inum:{}, pathString:{}", escapeLog(inum), escapeLog(pathString));
}
User existingUser = userSrv.getClientByInum(inum);
User existingUser = userSrv.getUserByInum(inum);
checkResourceNotNull(existingUser, USER);

existingUser = Jackson.applyPatch(pathString, existingUser);
userSrv.updateClient(existingUser);
userSrv.updateUser(existingUser);
return Response.ok(existingUser).build();
}

*/
@DELETE
@Path(ApiConstants.INUM_PATH)
@ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_DELETE_ACCESS })
@ProtectedApi(scopes = { ApiAccessConstants.USER_DELETE_ACCESS })
public Response deleteUser(@PathParam(ApiConstants.INUM) @NotNull String inum) {
if (logger.isDebugEnabled()) {
logger.debug("User to be deleted - inum:{} ", escapeLog(inum));
Expand All @@ -187,19 +137,6 @@ public Response deleteUser(@PathParam(ApiConstants.INUM) @NotNull String inum) {
return Response.noContent().build();
}

private List<User> getUsers(List<User> users) throws EncryptionException {
if (users != null && !users.isEmpty()) {
for (User user : users) {
//user.setClientSecret(encryptionService.decrypt(user.));
}
}
return users;
}

private String generatePassword() {
return UUID.randomUUID().toString();
}

private List<User> doSearch(SearchRequest searchReq) {
if (logger.isDebugEnabled()) {
logger.debug("User search params - searchReq:{} ", escapeLog(searchReq));
Expand All @@ -220,6 +157,5 @@ private List<User> doSearch(SearchRequest searchReq) {
}
return users;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,29 @@
]
}
]
},
{
"path":"/jans-config-api/api/v1/user",
"conditions":[
{
"httpMethods":["GET"],
"scopes":[
"https://jans.io/oauth/config/user.readonly"
]
},
{
"httpMethods":["PATCH","POST","PUT"],
"scopes":[
"https://jans.io/oauth/config/user.write"
]
},
{
"httpMethods":["DELETE"],
"scopes":[
"https://jans.io/oauth/config/user.delete"
]
}
]
}
]
}
Loading

0 comments on commit f98c59e

Please sign in to comment.