Skip to content

Commit

Permalink
Add support for "plain groups"
Browse files Browse the repository at this point in the history
In this mode the Grouper resource is seen as a set of groups,
each consisting of a set of members IDs.
  • Loading branch information
mederly committed Jun 11, 2019
1 parent 50c46ab commit 00e9021
Show file tree
Hide file tree
Showing 10 changed files with 500 additions and 81 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</parent>

<artifactId>connector-grouper-rest</artifactId>
<version>0.2</version>
<version>0.3</version>
<packaging>jar</packaging>

<name>Grouper REST Connector</name>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
/*******************************************************************************
* Copyright 2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/
package com.evolveum.polygon.connector.grouper.rest;

import org.apache.http.client.methods.HttpPost;
Expand All @@ -26,33 +13,20 @@
import static com.evolveum.polygon.connector.grouper.rest.Processor.*;

/**
* @author surmanek
* @author mederly
*
*/
class GroupProcessor {
public abstract class AbstractGroupProcessor {

private final Processor processor;
protected static final String ATTR_EXTENSION = "extension";
protected final Processor processor;

private static final String ATTR_EXTENSION = "extension";

GroupProcessor(Processor processor) {
public AbstractGroupProcessor(Processor processor) {
this.processor = processor;
}

ObjectClassInfoBuilder buildSchema() {
ObjectClassInfoBuilder builder = new ObjectClassInfoBuilder();

builder.setType(ObjectClass.GROUP_NAME);
AttributeInfoBuilder extension = new AttributeInfoBuilder(ATTR_EXTENSION, String.class);
builder.addAttributeInfo(extension.build());

return builder;
}

void read(Filter filter, ResultsHandler handler, OperationOptions options) {
if (filter == null) {
getAllGroups(handler);
getAllGroups(handler, options);
} else if (filter instanceof EqualsFilter && ((EqualsFilter) filter).getAttribute() instanceof Name) {
Attribute name = ((EqualsFilter) filter).getAttribute();
if (name != null) {
Expand All @@ -61,7 +35,7 @@ void read(Filter filter, ResultsHandler handler, OperationOptions options) {
} else if (name.getValue().size() > 1) {
throw new IllegalArgumentException("More than one group name to look for: " + name.getValue());
} else {
getGroupByName((String) name.getValue().get(0), handler);
getGroupByName((String) name.getValue().get(0), handler, options);
}
} else {
processor.throwNullAttrException(filter);
Expand All @@ -74,7 +48,7 @@ void read(Filter filter, ResultsHandler handler, OperationOptions options) {
} else if (name.getValue().size() > 1) {
throw new IllegalArgumentException("More than one group UUID to look for: " + name.getValue());
} else {
getGroupByUuid((String) name.getValue().get(0), handler);
getGroupByUuid((String) name.getValue().get(0), handler, options);
}
} else {
processor.throwNullAttrException(filter);
Expand All @@ -84,37 +58,32 @@ void read(Filter filter, ResultsHandler handler, OperationOptions options) {
}
}

private void getAllGroups(ResultsHandler handler) {
URIBuilder uriBuilder = processor.getURIBuilder()
.setPath(URI_BASE_PATH + PATH_GROUPS);
try {
HttpPost request = new HttpPost(uriBuilder.build());
JSONObject body = new JSONObject()
.put("WsRestGetMembersRequest", new JSONObject()
.put("wsGroupLookups", new JSONObject[] { new JSONObject()
.put("groupName", getConfiguration().getSuperGroup()) })
.put("includeSubjectDetail", true)
.put("memberFilter", "Immediate"));
executeFindGroupsAsMembersResponse(request, body, handler);
} catch (RuntimeException | URISyntaxException e) {
throw processor.processException(e, uriBuilder, "Get all groups");
}
void getGroupByUuid(String uuid, ResultsHandler handler, OperationOptions options) {
getGroupByUuid(uuid, handler);
}

void getGroupByName(String name, ResultsHandler handler, OperationOptions options) {
getGroupByName(name, handler);
}

private void executeFindGroupsResponse(HttpPost request, JSONObject body, ResultsHandler handler) {
abstract void getAllGroups(ResultsHandler handler, OperationOptions options);

void executeFindGroupsResponse(HttpPost request, JSONObject body, ResultsHandler handler) {
System.out.println("Request = " + body.toString());
JSONObject response = processor.callRequest(request, body, true, CONTENT_TYPE_JSON);
System.out.println("Got response: " + response);
processor.checkSuccess(response, "WsFindGroupsResults");
JSONArray groups = processor.getArray(response, "WsFindGroupsResults", "groupResults");
for (Object group : groups) {
if (!handleGroupJsonObject(group, handler)) {
return;
JSONArray groups = processor.getArray(response, false, "WsFindGroupsResults", "groupResults");
if (groups != null) {
for (Object group : groups) {
if (!handleGroupJsonObject(group, handler)) {
return;
}
}
}
}

private void executeFindGroupsAsMembersResponse(HttpPost request, JSONObject body, ResultsHandler handler) {
void executeFindGroupsAsMembersResponse(HttpPost request, JSONObject body, ResultsHandler handler) {
System.out.println("Request = " + body.toString());
JSONObject response = processor.callRequest(request, body, true, CONTENT_TYPE_JSON);
System.out.println("Got response: " + response);
Expand All @@ -127,7 +96,7 @@ private void executeFindGroupsAsMembersResponse(HttpPost request, JSONObject bod
}
}

private void getGroupByName(String groupName, ResultsHandler handler) {
void getGroupByName(String groupName, ResultsHandler handler) {
URIBuilder uriBuilder = processor.getURIBuilder()
.setPath(URI_BASE_PATH + PATH_GROUPS);
try {
Expand All @@ -142,7 +111,7 @@ private void getGroupByName(String groupName, ResultsHandler handler) {
}
}

private void getGroupByUuid(String groupUuid, ResultsHandler handler) {
void getGroupByUuid(String groupUuid, ResultsHandler handler) {
URIBuilder uriBuilder = processor.getURIBuilder()
.setPath(URI_BASE_PATH + PATH_GROUPS);
try {
Expand All @@ -164,7 +133,7 @@ private boolean handleGroupJsonObject(Object group, ResultsHandler handler) {
String extension = processor.getStringOrNull(gObject, "extension");
String uuid = processor.getStringOrNull(gObject, "uuid");
ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
builder.setObjectClass(ObjectClass.GROUP);
builder.setObjectClass(getObjectClass());
builder.setUid(uuid);
builder.setName(name);
builder.addAttribute(ATTR_EXTENSION, extension);
Expand All @@ -185,7 +154,7 @@ private boolean handleGroupAsMemberJsonObject(Object group, ResultsHandler handl
String name = processor.getStringOrNull(gObject, "name");
String id = processor.getStringOrNull(gObject, "id");
ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
builder.setObjectClass(ObjectClass.GROUP);
builder.setObjectClass(getObjectClass());
builder.setUid(id);
builder.setName(name);
return handler.handle(builder.build());
Expand All @@ -194,7 +163,9 @@ private boolean handleGroupAsMemberJsonObject(Object group, ResultsHandler handl
}
}

private GrouperConfiguration getConfiguration() {
protected abstract ObjectClass getObjectClass();

protected GrouperConfiguration getConfiguration() {
return processor.configuration;
}

Expand All @@ -218,5 +189,4 @@ void test() {
throw processor.processException(e, uriBuilder, "Test");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class GrouperConfiguration extends AbstractConfiguration implements State
private Boolean ignoreSslValidation;
private String subjectSource;
private String groupSource;
private String exportStem;

// getter and setter methods for "baseUrl" attribute:
@ConfigurationProperty(order = 1, displayMessageKey = "baseUrl.display", helpMessageKey = "baseUrl.help", required = true)
Expand Down Expand Up @@ -88,6 +89,11 @@ public void access(char[] clearChars) {
return stringPassword;
}

/**
* "Super group" that marks groups and users that are to be visible through this connector.
*
* Used for Account and Group object classes; ignored for PlainGroup object class.
*/
@ConfigurationProperty(order = 4, displayMessageKey = "superGroup.display", helpMessageKey = "superGroup.help", required = true)
public String getSuperGroup() {
return superGroup;
Expand All @@ -97,6 +103,9 @@ public void setSuperGroup(String superGroup) {
this.superGroup = superGroup;
}

/**
* Used to limit group membership to a subset of all groups. Applicable to Account object class.
*/
@ConfigurationProperty(order = 5, displayMessageKey = "groupIncludePattern.display", helpMessageKey = "groupIncludePattern.help", required = true)
public String[] getGroupIncludePattern() {
return groupIncludePattern;
Expand All @@ -106,11 +115,15 @@ public void setGroupIncludePattern(String[] groupIncludePattern) {
this.groupIncludePattern = groupIncludePattern;
}

/**
* Used to limit group membership to a subset of all groups. Applicable to Account object class.
*/
@ConfigurationProperty(order = 6, displayMessageKey = "groupExcludePattern.display", helpMessageKey = "groupExcludePattern.help", required = true)
public String[] getGroupExcludePattern() {
return groupExcludePattern;
}

@SuppressWarnings("unused")
public void setGroupExcludePattern(String[] groupExcludePattern) {
this.groupExcludePattern = groupExcludePattern;
}
Expand All @@ -124,6 +137,9 @@ public void setIgnoreSslValidation(Boolean ignoreSslValidation) {
this.ignoreSslValidation = ignoreSslValidation;
}

/**
* Used to limit subjects returned by this connector. Applicable to Account and PlainGroup object class.
*/
@ConfigurationProperty(order = 8, displayMessageKey = "subjectSource.display", helpMessageKey = "subjectSource.help", required = true)
public String getSubjectSource() {
return subjectSource;
Expand All @@ -133,15 +149,31 @@ public void setSubjectSource(String subjectSource) {
this.subjectSource = subjectSource;
}

/**
* Used to limit groups returned by this connector. Applicable to Group object class. Usually not needed to change.
*/
@ConfigurationProperty(order = 9, displayMessageKey = "groupSource.display", helpMessageKey = "groupSource.help")
public String getGroupSource() {
return groupSource != null ? groupSource : DEFAULT_GROUP_SOURCE_ID;
}

@SuppressWarnings("unused")
public void setGroupSource(String groupSource) {
this.groupSource = groupSource;
}

/**
* Used to specify root stem for groups returned by this connector. Applicable to PlainGroup object class.
*/
@ConfigurationProperty(order = 10, displayMessageKey = "exportStem.display", helpMessageKey = "exportStem.help")
public String getExportStem() {
return exportStem;
}

public void setExportStem(String exportStem) {
this.exportStem = exportStem;
}

@Override
public void validate() {
String exceptionMsg;
Expand Down Expand Up @@ -175,6 +207,7 @@ public void release() {
this.groupExcludePattern = null;
this.subjectSource = null;
this.groupSource = null;
this.exportStem = null;
}

@Override
Expand All @@ -188,6 +221,7 @@ public String toString() {
", ignoreSslValidation=" + ignoreSslValidation +
", subjectSource='" + subjectSource + '\'' +
", groupSource='" + groupSource + '\'' +
", exportStem='" + exportStem + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public class GrouperConnector implements TestOp, SchemaOp, Connector, SearchOp<F
private GrouperConfiguration configuration;
private Processor processor;
private AccountProcessor accountProcessor;
private GroupProcessor groupProcessor;
private StandardGroupProcessor standardGroupProcessor;
private PlainGroupProcessor plainGroupProcessor;

private static final String PROJECT_NAME = "PROJECT";
private static final String ATTR_GROUPS = "groups";
Expand All @@ -61,37 +62,33 @@ public void init(Configuration configuration) {
this.configuration.validate();
this.processor = new Processor(this.configuration);
this.accountProcessor = new AccountProcessor(processor);
this.groupProcessor = new GroupProcessor(processor);
this.standardGroupProcessor = new StandardGroupProcessor(processor);
this.plainGroupProcessor = new PlainGroupProcessor(processor);
}

@Override
public void dispose() {
configuration = null;
processor = null;
accountProcessor = null;
groupProcessor = null;
standardGroupProcessor = null;
plainGroupProcessor = null;
}

@Override
public void test() {
LOG.info("Testing connection...");
groupProcessor.test();
standardGroupProcessor.test();
LOG.ok("Testing finished successfully.");
}

@Override
public Schema schema() {
SchemaBuilder schemaBuilder = new SchemaBuilder(GrouperConnector.class);

// build user schema:
AccountProcessor user = new AccountProcessor(processor);
ObjectClassInfoBuilder userBuilder = user.buildSchema();
schemaBuilder.defineObjectClass(userBuilder.build());

// build group schema:
GroupProcessor group = new GroupProcessor(processor);
ObjectClassInfoBuilder groupBuilder = group.buildSchema();
schemaBuilder.defineObjectClass(groupBuilder.build());
schemaBuilder.defineObjectClass(accountProcessor.buildSchema().build());
schemaBuilder.defineObjectClass(standardGroupProcessor.buildSchema().build());
schemaBuilder.defineObjectClass(plainGroupProcessor.buildSchema().build());

return schemaBuilder.build();
}
Expand Down Expand Up @@ -133,7 +130,9 @@ public void executeQuery(ObjectClass objClass, Filter filter, ResultsHandler han
if (objClass.is(ObjectClass.ACCOUNT_NAME)) {
accountProcessor.read(filter, handler, options);
} else if (objClass.is(ObjectClass.GROUP_NAME)) {
groupProcessor.read(filter, handler, options);
standardGroupProcessor.read(filter, handler, options);
} else if (objClass.is(plainGroupProcessor.getObjectClass().getObjectClassValue())) {
plainGroupProcessor.read(filter, handler, options);
}
}

Expand Down
Loading

0 comments on commit 00e9021

Please sign in to comment.