Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/Evolveum/midpoint
- Loading branch information
Showing
4 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import org.identityconnectors.framework.common.objects.ObjectClass | ||
|
||
class BaseScript extends Script { | ||
|
||
public static final String GROUP_NAME = "Group" | ||
|
||
public static final ObjectClass GROUP = new ObjectClass(BaseScript.GROUP_NAME) | ||
|
||
public static final String ORGANIZATION_NAME = "Organization" | ||
|
||
public static final ObjectClass ORGANIZATION = new ObjectClass(BaseScript.ORGANIZATION_NAME) | ||
|
||
@Override | ||
Object run() { | ||
return null | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import groovy.sql.Sql | ||
import org.forgerock.openicf.connectors.scriptedsql.ScriptedSQLConfiguration | ||
import org.forgerock.openicf.misc.scriptedcommon.OperationType | ||
import org.identityconnectors.common.logging.Log | ||
import org.identityconnectors.framework.common.exceptions.ConnectorException | ||
import org.identityconnectors.framework.common.objects.Attribute | ||
import org.identityconnectors.framework.common.objects.ObjectClass | ||
import org.identityconnectors.framework.common.objects.OperationOptions | ||
import org.identityconnectors.framework.common.objects.Uid | ||
import org.identityconnectors.framework.common.objects.AttributeUtil | ||
|
||
import java.sql.Connection | ||
|
||
def log = log as Log | ||
def operation = operation as OperationType | ||
def options = options as OperationOptions | ||
def objectClass = objectClass as ObjectClass | ||
def attributes = attributes as Set<Attribute> | ||
def connection = connection as Connection | ||
def id = id as String | ||
def configuration = configuration as ScriptedSQLConfiguration | ||
|
||
log.info("Entering " + operation + " Script") | ||
|
||
def sql = new Sql(connection) | ||
|
||
switch (objectClass) { | ||
case ObjectClass.ACCOUNT: | ||
return handleAccount(sql) | ||
case BaseScript.GROUP: | ||
return handleGroup(sql) | ||
case BaseScript.ORGANIZATION: | ||
return handleOrganization(sql) | ||
default: | ||
throw new ConnectorException("Unknown object class " + objectClass) | ||
} | ||
|
||
Uid handleAccount(Sql sql) { | ||
def keys = sql.executeInsert("INSERT INTO Users (login, firstname,lastname,fullname,email,organization,password,disabled) values (?,?,?,?,?,?,?,?)", | ||
[ | ||
id, | ||
AttributeUtil.getSingleValue("firstname"), | ||
AttributeUtil.getSingleValue("lastname"), | ||
AttributeUtil.getSingleValue("fullname"), | ||
AttributeUtil.getSingleValue("email"), | ||
AttributeUtil.getSingleValue("organization"), | ||
// decrypt password | ||
SecurityUtil.decrypt(AttributeUtil.getPasswordValue(attributes)), | ||
// negate __ENABLE__ attribute | ||
!(AttributeUtil.getSingleValue("__ENABLE__") as Boolean) | ||
|
||
//attributes.get("firstname") ? attributes.get("firstname").get(0) : "", | ||
//attributes.get("lastname") ? attributes.get("lastname").get(0) : "", | ||
//attributes.get("fullname") ? attributes.get("fullname").get(0) : "", | ||
//attributes.get("email") ? attributes.get("email").get(0) : "", | ||
//attributes.get("organization") ? attributes.get("organization").get(0) : "" | ||
]) | ||
|
||
return new Uid(keys[0][0]) | ||
} | ||
|
||
Uid handleGroup(Sql sql) { | ||
def keys = sql.executeInsert("INSERT INTO Groups (name,description) values (?,?)", | ||
[ | ||
id, | ||
AttributeUtil.getSingleValue("description") | ||
]) | ||
|
||
return new Uid(keys[0][0]) | ||
} | ||
|
||
Uid handleOrganization(Sql sql) { | ||
def keys = sql.executeInsert("INSERT INTO Organizations (name,description) values (?,?)", | ||
[ | ||
id, | ||
AttributeUtil.getSingleValue("description") | ||
]) | ||
|
||
return new Uid(keys[0][0]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import org.forgerock.openicf.connectors.scriptedsql.ScriptedSQLConfiguration | ||
import org.forgerock.openicf.misc.scriptedcommon.ICFObjectBuilder | ||
import org.forgerock.openicf.misc.scriptedcommon.OperationType | ||
import org.identityconnectors.common.logging.Log | ||
import org.identityconnectors.framework.common.objects.ObjectClass | ||
import org.identityconnectors.framework.common.objects.OperationOptionInfoBuilder | ||
import org.identityconnectors.framework.spi.operations.SearchOp | ||
import org.identityconnectors.framework.common.objects.OperationalAttributeInfos | ||
|
||
import static org.identityconnectors.framework.common.objects.AttributeInfo.Flags.MULTIVALUED | ||
|
||
def log = log as Log | ||
def operation = operation as OperationType | ||
def builder = builder as ICFObjectBuilder | ||
def configuration = configuration as ScriptedSQLConfiguration | ||
|
||
log.info("Entering " + operation + " Script") | ||
|
||
builder.schema({ | ||
objectClass { | ||
type ObjectClass.ACCOUNT_NAME | ||
attributes { | ||
firstname() | ||
lastname() | ||
fullname() | ||
email() | ||
organization() | ||
OperationalAttributeInfos.ENABLE | ||
OperationalAttributeInfos.PASSWORD | ||
OperationalAttributeInfos.LOCK_OUT | ||
} | ||
} | ||
objectClass { | ||
type BaseScript.GROUP | ||
attributes { | ||
name String.class, MULTIVALUED | ||
description() | ||
} | ||
} | ||
objectClass { | ||
type BaseScript.ORGANIZATION | ||
attributes { | ||
name() | ||
description() | ||
} | ||
} | ||
|
||
defineOperationOption OperationOptionInfoBuilder.buildPagedResultsOffset(), SearchOp | ||
defineOperationOption OperationOptionInfoBuilder.buildPageSize(), SearchOp | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import groovy.sql.Sql | ||
import org.forgerock.openicf.connectors.scriptedsql.ScriptedSQLConfiguration | ||
import org.forgerock.openicf.misc.scriptedcommon.ICFObjectBuilder | ||
import org.forgerock.openicf.misc.scriptedcommon.MapFilterVisitor | ||
import org.forgerock.openicf.misc.scriptedcommon.OperationType | ||
import org.identityconnectors.common.logging.Log | ||
import org.identityconnectors.framework.common.exceptions.ConnectorException | ||
import org.identityconnectors.framework.common.objects.ObjectClass | ||
import org.identityconnectors.framework.common.objects.OperationOptions | ||
import org.identityconnectors.framework.common.objects.ResultsHandler | ||
import org.identityconnectors.framework.common.objects.SearchResult | ||
import org.identityconnectors.framework.common.objects.filter.Filter | ||
|
||
import java.sql.Connection | ||
|
||
def log = log as Log | ||
def operation = operation as OperationType | ||
def options = options as OperationOptions | ||
def objectClass = objectClass as ObjectClass | ||
def configuration = configuration as ScriptedSQLConfiguration | ||
def filter = filter as Filter | ||
def connection = connection as Connection | ||
def query = query as Closure | ||
def handler = handler as ResultsHandler | ||
|
||
log.info("Entering " + operation + " Script") | ||
|
||
def sql = new Sql(connection) | ||
|
||
switch (objectClass) { | ||
case ObjectClass.ACCOUNT: | ||
handleAccount(sql) | ||
break | ||
case BaseScript.GROUP: | ||
handleGroup(sql) | ||
break | ||
case BaseScript.ORGANIZATION: | ||
handleOrganization(sql) | ||
break | ||
default: | ||
throw new ConnectorException("Unknown object class " + objectClass) | ||
} | ||
|
||
return new SearchResult() | ||
|
||
// ================================================================================= | ||
|
||
void handleAccount(Sql sql) { | ||
Closure closure = { row -> | ||
ICFObjectBuilder.co { | ||
uid row.id as String | ||
id row.login | ||
attribute '__ENABLE__', !row.disabled | ||
attribute 'fullname', row.fullname | ||
attribute 'firstname', row.firstname | ||
attribute 'lastname', row.lastname | ||
attribute 'email', row.email | ||
attribute 'organization', row.organization | ||
} | ||
} | ||
|
||
Map params = [:] | ||
String where = buildWhereClause(filter, params, 'id', 'login') | ||
|
||
sql.eachRow(params, "SELECT * FROM Users " + where, closure); | ||
} | ||
|
||
|
||
void handleGroup(Sql sql) { | ||
Closure closure = { row -> | ||
ICFObjectBuilder.co { | ||
uid row.id as String | ||
id row.name | ||
attribute 'description', row.description | ||
} | ||
} | ||
|
||
Map params = [:] | ||
String where = buildWhereClause(filter, params, 'id', 'name') | ||
|
||
sql.eachRow(params, "SELECT * FROM Groups " + where, closure) | ||
} | ||
|
||
void handleOrganization(Sql sql) { | ||
Closure closure = { row -> | ||
ICFObjectBuilder.co { | ||
uid row.id as String | ||
id row.name | ||
attribute 'description', row.description | ||
} | ||
} | ||
|
||
Map params = [:] | ||
String where = buildWhereClause(filter, params, 'id', 'name') | ||
|
||
sql.eachRow(params, "SELECT * FROM Organizations " + where, closure) | ||
} | ||
|
||
static String buildWhereClause(Filter filter, Map sqlParams, String uidColumn, String nameColumn) { | ||
if (filter == null) { | ||
log.info("Returning empty where clause") | ||
return "" | ||
} | ||
|
||
Map query = filter.accept(MapFilterVisitor.INSTANCE, null) | ||
|
||
log.info("Building where clause, query {0}, uidcolumn {1}, nameColumn {2}", query, uidColumn, nameColumn) | ||
|
||
String columnName = uidColumn.replaceFirst("[\\w]+\\.", "") | ||
|
||
String left = query.get("left") | ||
if (Uid.NAME.equals(left)) { | ||
left = uidColumn | ||
} else if (Name.NAME.equals(left)) { | ||
left = nameColumn | ||
} | ||
|
||
String right = query.get("right") | ||
|
||
String operation = query.get("operation") | ||
switch (operation) { | ||
case "CONTAINS": | ||
right = '%' + right + '%' | ||
break; | ||
case "ENDSWITH": | ||
right = '%' + right | ||
break; | ||
case "STARTSWITH": | ||
right = right + '%' | ||
break; | ||
} | ||
|
||
sqlParams.put(columnName, right) | ||
right = ":" + columnName | ||
|
||
def engine = new groovy.text.SimpleTemplateEngine() | ||
|
||
def whereTemplates = [ | ||
CONTAINS : ' $left ${not ? "not " : ""}like $right', | ||
ENDSWITH : ' $left ${not ? "not " : ""}like $right', | ||
STARTSWITH : ' $left ${not ? "not " : ""}like $right', | ||
EQUALS : ' $left ${not ? "<>" : "="} $right', | ||
GREATERTHAN : ' $left ${not ? "<=" : ">"} $right', | ||
GREATERTHANOREQUAL: ' $left ${not ? "<" : ">="} $right', | ||
LESSTHAN : ' $left ${not ? ">=" : "<"} $right', | ||
LESSTHANOREQUAL : ' $left ${not ? ">" : "<="} $right' | ||
] | ||
|
||
def wt = whereTemplates.get(operation) | ||
def binding = [left: left, right: right, not: query.get("not")] | ||
def template = engine.createTemplate(wt).make(binding) | ||
def where = template.toString() | ||
|
||
log.info("Where clause: {0}, with parameters {1}", where, sqlParams) | ||
|
||
return where | ||
} | ||
|