diff --git a/pom.xml b/pom.xml
index 7729bb4..04c607c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -115,7 +115,7 @@
ossrh
https://oss.sonatype.org/
- false
+ true
@@ -194,7 +194,7 @@
com.evolveum.midpoint.gui
admin-gui
- 4.4.1
+ 4.4.2
jar
classes
provided
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0Client.java b/src/main/java/jp/openstandia/connector/auth0/Auth0Client.java
index fe75545..31b4d0c 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0Client.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0Client.java
@@ -61,15 +61,9 @@ public void initClient(Auth0Configuration configuration) throws Auth0Exception {
HttpOptions httpOptions = new HttpOptions();
- if (configuration.getConnectionTimeoutInSeconds() != null) {
- httpOptions.setConnectTimeout(configuration.getConnectionTimeoutInSeconds());
- }
- if (configuration.getReadTimeoutInSeconds() != null) {
- httpOptions.setReadTimeout(configuration.getReadTimeoutInSeconds());
- }
- if (configuration.getMaxRetries() != null) {
- httpOptions.setManagementAPIMaxRetries(configuration.getMaxRetries());
- }
+ httpOptions.setConnectTimeout(configuration.getConnectionTimeoutInSeconds());
+ httpOptions.setReadTimeout(configuration.getReadTimeoutInSeconds());
+ httpOptions.setManagementAPIMaxRetries(configuration.getMaxRetries());
// HTTP Proxy
applyProxyIfNecessary(httpOptions);
@@ -107,8 +101,12 @@ private void checkClient() throws Auth0Exception {
}
protected void refreshToken() throws Auth0Exception {
+ refreshToken(false);
+ }
+
+ protected void refreshToken(boolean force) throws Auth0Exception {
if (configuration.getClientId() != null && configuration.getClientSecret() != null) {
- if (isExpired(tokenHolder)) {
+ if (force || isExpired(tokenHolder, new Date())) {
final AuthAPI[] authAPI = new AuthAPI[1];
configuration.getClientSecret().access(c -> {
HttpOptions httpOptions = new HttpOptions();
@@ -130,14 +128,14 @@ protected void refreshToken() throws Auth0Exception {
}
}
- protected boolean isExpired(TokenHolder holder) {
+ protected boolean isExpired(TokenHolder holder, Date now) {
if (holder == null) {
return true;
}
long expiresAt = holder.getExpiresAt().getTime();
- long now = new Date().getTime();
+ long nowTime = now.getTime();
- if (expiresAt + (60 * 1000) > now) {
+ if (nowTime + (60 * 1000) > expiresAt) {
LOG.ok("Detected the token is expired");
return true;
}
@@ -149,7 +147,7 @@ protected boolean isExpired(TokenHolder holder) {
public List getConnection(ConnectionFilter connectionFilter) throws Auth0Exception {
List conns = new ArrayList<>();
- withAuthPaging(connectionFilter, 0, 50, (filter) -> {
+ withAuthPaging(connectionFilter, 0, 50, (filter, ignore) -> {
Request request = internalClient.connections().listAll(filter);
ConnectionsPage response = request.execute();
@@ -230,15 +228,21 @@ public List getUserByEmail(String email, FieldsFilter filter) throws Auth0
});
}
- public void getUsers(UserFilter userFilter, OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
+ public int getUsers(UserFilter userFilter, OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
int pageInitialOffset = resolvePageOffset(options);
int pageSize = resolvePageSize(configuration, options);
- withAuthPaging(userFilter, pageInitialOffset, pageSize, (filter) -> {
+ return withAuthPaging(userFilter, pageInitialOffset, pageSize, (filter, skipCount) -> {
Request request = internalClient.users().list(filter);
UsersPage response = request.execute();
+ int count = 0;
for (User u : response.getItems()) {
+ if (count < skipCount) {
+ count++;
+ continue;
+ }
+
Boolean next = resultsHandler.apply(u);
if (!next) {
break;
@@ -266,7 +270,7 @@ public void removeRolesToUser(Uid uid, List roleIds) throws Auth0Excepti
public List getRolesForUser(String userId) throws Auth0Exception {
List roles = new ArrayList<>();
- withAuthPaging(new PageFilter(), 0, 50, (filter) -> {
+ withAuthPaging(new PageFilter(), 0, 50, (filter, ignore) -> {
Request request = internalClient.users().listRoles(userId, filter);
RolesPage response = request.execute();
@@ -303,7 +307,7 @@ public void removeOrganizationsToUser(Uid uid, List orgIds) throws Auth0
public List getOrganizationsForUser(String userId) throws Auth0Exception {
List orgs = new ArrayList<>();
- withAuthPaging(new PageFilter(), 0, 50, (filter) -> {
+ withAuthPaging(new PageFilter(), 0, 50, (filter, ignore) -> {
Request request = internalClient.users().getOrganizations(userId, filter);
OrganizationsPage response = request.execute();
@@ -340,7 +344,7 @@ public Map> getOrganizationRolesForUser(String userId) thro
List orgs = getOrganizationsForUser(userId);
for (Organization org : orgs) {
- withAuthPaging(new PageFilter(), 0, 50, (filter) -> {
+ withAuthPaging(new PageFilter(), 0, 50, (filter, ignore) -> {
Request request = internalClient.organizations().getRoles(org.getId(), userId, filter);
RolesPage response = request.execute();
@@ -371,7 +375,7 @@ public void removePermissionsToUser(Uid uid, List permissions) throw
public List getPermissionsForUser(String userId) throws Auth0Exception {
List permissions = new ArrayList<>();
- withAuthPaging(new PageFilter(), 0, 50, (filter) -> {
+ withAuthPaging(new PageFilter(), 0, 50, (filter, ignore) -> {
Request request = internalClient.users().listPermissions(userId, filter);
PermissionsPage response = request.execute();
@@ -426,17 +430,23 @@ public List getRoleByName(String roleName) throws Auth0Exception {
});
}
- public void getRoles(OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
+ public int getRoles(OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
int pageInitialOffset = resolvePageOffset(options);
int pageSize = resolvePageSize(configuration, options);
RolesFilter rolesFilter = new RolesFilter();
- withAuthPaging(rolesFilter, pageInitialOffset, pageSize, (filter) -> {
+ return withAuthPaging(rolesFilter, pageInitialOffset, pageSize, (filter, skipCount) -> {
Request request = internalClient.roles().list(filter);
RolesPage response = request.execute();
+ int count = 0;
for (Role u : response.getItems()) {
+ if (count < skipCount) {
+ count++;
+ continue;
+ }
+
Boolean next = resultsHandler.apply(u);
if (!next) {
break;
@@ -464,7 +474,7 @@ public void removePermissionsToRole(Uid uid, List permissions) throw
public List getPermissionsForRole(String roleId) throws Auth0Exception {
List permissions = new ArrayList<>();
- withAuthPaging(new PageFilter(), 0, 50, (filter) -> {
+ withAuthPaging(new PageFilter(), 0, 50, (filter, ignore) -> {
Request request = internalClient.roles().listPermissions(roleId, filter);
PermissionsPage response = request.execute();
@@ -516,17 +526,23 @@ public Organization getOrganizationByName(String orgName) throws Auth0Exception
});
}
- public void getOrganizations(OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
+ public int getOrganizations(OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
int pageInitialOffset = resolvePageOffset(options);
int pageSize = resolvePageSize(configuration, options);
- PageFilter rolesFilter = new PageFilter();
+ PageFilter orgsFilter = new PageFilter();
- withAuthPaging(rolesFilter, pageInitialOffset, pageSize, (filter) -> {
+ return withAuthPaging(orgsFilter, pageInitialOffset, pageSize, (filter, skipCount) -> {
Request request = internalClient.organizations().list(filter);
OrganizationsPage response = request.execute();
+ int count = 0;
for (Organization u : response.getItems()) {
+ if (count < skipCount) {
+ count++;
+ continue;
+ }
+
Boolean next = resultsHandler.apply(u);
if (!next) {
break;
@@ -538,72 +554,129 @@ public void getOrganizations(OperationOptions options, ResultHandlerFunction int withAuthPaging(T filter, int pageOffset, int pageSize, PageFunction> callback) throws Auth0Exception {
+ withTotals(filter, true);
- private void withAuthPaging(T filter, int initialOffset, int pageSize, PageFunction> callback) throws Auth0Exception {
- int offset = initialOffset;
- boolean retried = false;
+ PageInfo pageInfo = newPageInfo(pageOffset, pageSize);
- filter.withTotals(true);
+ if (pageInfo.isRequestedFullPage()) {
+ // Start from page 0 in Auth0
+ int pageNumber = 0;
+ int total = 0;
- while (true) {
- filter.withPage(offset, pageSize);
+ while (true) {
+ withPage(filter, pageNumber, pageSize);
- Page> result = withAuth(() -> {
- Page> response = callback.apply(filter);
- return response;
- });
+ Page> result = withAuth(() -> {
+ Page> response = callback.apply(filter, 0);
+ return response;
+ });
+
+ total = result.getTotal();
+ if (total == 0) {
+ // Not found
+ break;
+ }
+
+ if (hasNextPage(result)) {
+ pageNumber++;
+ continue;
+ }
+ break;
+ }
+ return total;
+
+ } else {
+ // Start from page 0 in Auth0, so need -1
+ int pageNumber = pageInfo.initPage - 1;
+ int total = 0;
- if (hasNextPage(result)) {
- offset++;
- continue;
+ for (int i = 0; i < pageInfo.times; i++) {
+ withPage(filter, pageNumber, pageSize);
+
+ final int skipCount = i == 0 ? pageInfo.skipCount : 0;
+
+ Page> result = withAuth(() -> {
+ Page> response = callback.apply(filter, skipCount);
+ return response;
+ });
+
+ total = result.getTotal();
+ if (total == 0) {
+ // Not found
+ break;
+ }
+
+ if (hasNextPage(result)) {
+ pageNumber++;
+ continue;
+ }
+ break;
}
- break;
+ return total;
}
}
- private void withAuthPaging(T filter, int initialOffset, int pageSize, PageFunction> callback) throws Auth0Exception {
- int offset = initialOffset;
+ protected static class PageInfo {
+ public final int pageOffset;
+ public final int initPage;
+ public final int skipCount;
+ public final int times;
- filter.withTotals(true);
+ public PageInfo(int pageOffset, int initPage, int skipCount, int times) {
+ this.pageOffset = pageOffset;
+ this.initPage = initPage;
+ this.skipCount = skipCount;
+ this.times = times;
+ }
- while (true) {
- filter.withPage(offset, pageSize);
+ public boolean isRequestedFullPage() {
+ return pageOffset == 0;
+ }
+ }
- Page> result = withAuth(() -> {
- Page> response = callback.apply(filter);
- return response;
- });
+ protected static PageInfo newPageInfo(int pageOffset, int pageSize) {
+ if (pageOffset == 0) {
+ // Requested full page
+ return new PageInfo(pageOffset, 1, 0, -1);
- if (hasNextPage(result)) {
- offset++;
- continue;
- }
- break;
+ } else if ((pageOffset + pageSize - 1) % pageSize == 0) {
+ int initPage = (pageOffset + pageSize - 1) / pageSize;
+ return new PageInfo(pageOffset, initPage, 0, 1);
+
+ } else {
+ int initPage = ((pageOffset + pageSize - 1) / pageSize);
+ int skipCount = pageOffset - ((initPage - 1) * pageSize) -1;
+
+ return new PageInfo(pageOffset, initPage, skipCount, 2);
}
}
- private void withAuthPaging(T filter, int initialOffset, int pageSize, PageFunction> callback) throws Auth0Exception {
- int offset = initialOffset;
+ private void withTotals(BaseFilter filter, boolean includesTotal) {
+ if (filter instanceof PageFilter) {
+ ((PageFilter) filter).withTotals(includesTotal);
- filter.withTotals(true);
+ } else if (filter instanceof QueryFilter) {
+ ((QueryFilter) filter).withTotals(includesTotal);
- while (true) {
- filter.withPage(offset, pageSize);
+ } else if (filter instanceof ConnectionFilter) {
+ ((ConnectionFilter) filter).withTotals(includesTotal);
+ }
+ }
- Page> result = withAuth(() -> {
- Page> response = callback.apply(filter);
- return response;
- });
+ private void withPage(BaseFilter filter, int pageNumber, int pageSize) {
+ if (filter instanceof PageFilter) {
+ ((PageFilter) filter).withPage(pageNumber, pageSize);
- if (hasNextPage(result)) {
- offset++;
- continue;
- }
- break;
+ } else if (filter instanceof QueryFilter) {
+ ((QueryFilter) filter).withPage(pageNumber, pageSize);
+
+ } else if (filter instanceof ConnectionFilter) {
+ ((ConnectionFilter) filter).withPage(pageNumber, pageSize);
}
}
- private T withAuth(APIFunction callback) throws Auth0Exception {
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
boolean retried = false;
// Refresh token if expired in advance
@@ -615,8 +688,8 @@ private T withAuth(APIFunction callback) throws Auth0Exception {
return response;
} catch (APIException e) {
// If the api token is expired during paging process, refresh the token then retry
- if (!retried && e.getStatusCode() == 401 && e.getError().equals("Invalid tokens.")) {
- refreshToken();
+ if (!retried && e.getStatusCode() == 401) {
+ refreshToken(true);
retried = true;
continue;
}
@@ -632,7 +705,7 @@ interface APIFunction {
@FunctionalInterface
interface PageFunction {
- public Result apply(One one) throws Auth0Exception;
+ public Result apply(One one, int skipCount) throws Auth0Exception;
}
@FunctionalInterface
@@ -641,7 +714,11 @@ public interface ResultHandlerFunction {
}
private static boolean hasNextPage(Page> page) {
- int remains = (page.getTotal() - page.getStart() + page.getLimit());
+ Integer length = page.getLength();
+ if (length == null) {
+ return false;
+ }
+ int remains = (page.getTotal() - (page.getStart() + length));
return remains > 0;
}
}
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0Configuration.java b/src/main/java/jp/openstandia/connector/auth0/Auth0Configuration.java
index 8785a0b..5fb2def 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0Configuration.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0Configuration.java
@@ -24,14 +24,14 @@ public class Auth0Configuration extends AbstractConfiguration {
private String domain;
private String clientId;
private GuardedString clientSecret;
- private Integer connectionTimeoutInSeconds = 10;
- private Integer readTimeoutInSeconds = 10;
- private Integer maxRetries = 3;
+ private int connectionTimeoutInSeconds = 10;
+ private int readTimeoutInSeconds = 10;
+ private int maxRetries = 3;
private String httpProxyHost;
private int httpProxyPort;
private String httpProxyUser;
private GuardedString httpProxyPassword;
- private Integer defaultQueryPageSize = 50;
+ private int defaultQueryPageSize = 50;
private String[] connectionFilter = new String[]{};
@ConfigurationProperty(
@@ -96,11 +96,11 @@ public void setConnectionFilter(String[] connectionFilter) {
helpMessageKey = "Connection timeout when connecting to Auth0. (Default: 10)",
required = false,
confidential = false)
- public Integer getConnectionTimeoutInSeconds() {
+ public int getConnectionTimeoutInSeconds() {
return connectionTimeoutInSeconds;
}
- public void setConnectionTimeoutInSeconds(Integer connectionTimeoutInSeconds) {
+ public void setConnectionTimeoutInSeconds(int connectionTimeoutInSeconds) {
this.connectionTimeoutInSeconds = connectionTimeoutInSeconds;
}
@@ -110,11 +110,11 @@ public void setConnectionTimeoutInSeconds(Integer connectionTimeoutInSeconds) {
helpMessageKey = "Read timeout when fetching data from Auth0. (Default: 10)",
required = false,
confidential = false)
- public Integer getReadTimeoutInSeconds() {
+ public int getReadTimeoutInSeconds() {
return readTimeoutInSeconds;
}
- public void setReadTimeoutInSeconds(Integer readTimeoutInSeconds) {
+ public void setReadTimeoutInSeconds(int readTimeoutInSeconds) {
this.readTimeoutInSeconds = readTimeoutInSeconds;
}
@@ -124,11 +124,11 @@ public void setReadTimeoutInSeconds(Integer readTimeoutInSeconds) {
helpMessageKey = "Sets the maximum number of consecutive retries for Auth0 Management API requests that fail due to rate-limits being reached. (Default: 3)",
required = false,
confidential = false)
- public Integer getMaxRetries() {
+ public int getMaxRetries() {
return maxRetries;
}
- public void setMaxRetries(Integer maxRetries) {
+ public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
@@ -194,11 +194,11 @@ public void setHttpProxyPassword(GuardedString httpProxyPassword) {
helpMessageKey = "Set default query page size. Default: 50",
required = false,
confidential = false)
- public Integer getDefaultQueryPageSize() {
+ public int getDefaultQueryPageSize() {
return defaultQueryPageSize;
}
- public void setDefaultQueryPageSize(Integer defaultQueryPageSize) {
+ public void setDefaultQueryPageSize(int defaultQueryPageSize) {
this.defaultQueryPageSize = defaultQueryPageSize;
}
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0Connector.java b/src/main/java/jp/openstandia/connector/auth0/Auth0Connector.java
index d084988..d478704 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0Connector.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0Connector.java
@@ -23,10 +23,7 @@
import org.identityconnectors.framework.common.exceptions.*;
import org.identityconnectors.framework.common.objects.*;
import org.identityconnectors.framework.common.objects.filter.FilterTranslator;
-import org.identityconnectors.framework.spi.Configuration;
-import org.identityconnectors.framework.spi.ConnectorClass;
-import org.identityconnectors.framework.spi.InstanceNameAware;
-import org.identityconnectors.framework.spi.PoolableConnector;
+import org.identityconnectors.framework.spi.*;
import org.identityconnectors.framework.spi.operations.*;
import java.util.*;
@@ -35,6 +32,8 @@
import static jp.openstandia.connector.auth0.Auth0OrganizationHandler.ORGANIZATION_OBJECT_CLASS;
import static jp.openstandia.connector.auth0.Auth0RoleHandler.ROLE_OBJECT_CLASS;
import static jp.openstandia.connector.auth0.Auth0UserHandler.USER_OBJECT_CLASS_PREFIX;
+import static jp.openstandia.connector.auth0.Auth0Utils.resolvePageOffset;
+import static jp.openstandia.connector.auth0.Auth0Utils.resolvePageSize;
@ConnectorClass(configurationClass = Auth0Configuration.class, displayNameKey = "Auth0 Connector")
public class Auth0Connector implements PoolableConnector, CreateOp, UpdateDeltaOp, DeleteOp, SchemaOp, TestOp, SearchOp, InstanceNameAware {
@@ -105,7 +104,8 @@ public Schema schema() {
schemaBuilder.defineOperationOption(OperationOptionInfoBuilder.buildAttributesToGet(), SearchOp.class);
schemaBuilder.defineOperationOption(OperationOptionInfoBuilder.buildReturnDefaultAttributes(), SearchOp.class);
-
+ schemaBuilder.defineOperationOption(OperationOptionInfoBuilder.buildPageSize(), SearchOp.class);
+ schemaBuilder.defineOperationOption(OperationOptionInfoBuilder.buildPagedResultsOffset(), SearchOp.class);
Map roleSchemaMap = new HashMap<>();
for (AttributeInfo a : roleSchemaInfo.getAttributeInfo()) {
@@ -231,21 +231,36 @@ public FilterTranslator createFilterTranslator(ObjectClass objectCl
@Override
public void executeQuery(ObjectClass objectClass, Auth0Filter filter, ResultsHandler resultsHandler, OperationOptions options) {
try {
+ int pageSize = resolvePageSize(configuration, options);
+ int pageOffset = resolvePageOffset(options);
+
+ int total = 0;
+
if (objectClass.getObjectClassValue().startsWith(USER_OBJECT_CLASS_PREFIX)) {
Auth0UserHandler userHandler = new Auth0UserHandler(configuration, client, getSchemaMap(objectClass), resolveDatabaseConnection(objectClass));
- userHandler.getUsers(filter, resultsHandler, options);
+ total = userHandler.getUsers(filter, resultsHandler, options);
} else if (objectClass.equals(ROLE_OBJECT_CLASS)) {
Auth0RoleHandler roleHandler = new Auth0RoleHandler(configuration, client, getSchemaMap(objectClass));
- roleHandler.getRoles(filter, resultsHandler, options);
+ total = roleHandler.getRoles(filter, resultsHandler, options);
} else if (objectClass.equals(ORGANIZATION_OBJECT_CLASS)) {
Auth0OrganizationHandler organizationHandler = new Auth0OrganizationHandler(configuration, client, getSchemaMap(objectClass));
- organizationHandler.query(filter, resultsHandler, options);
+ total = organizationHandler.query(filter, resultsHandler, options);
} else {
throw new InvalidAttributeValueException("Unsupported object class " + objectClass);
}
+
+ if (resultsHandler instanceof SearchResultsHandler &&
+ pageOffset > 0) {
+
+ int remaining = total - (pageSize * pageOffset);
+
+ SearchResultsHandler searchResultsHandler = (SearchResultsHandler) resultsHandler;
+ SearchResult searchResult = new SearchResult(null, remaining);
+ searchResultsHandler.handleResult(searchResult);
+ }
} catch (Exception e) {
throw processException(e);
}
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0OrganizationHandler.java b/src/main/java/jp/openstandia/connector/auth0/Auth0OrganizationHandler.java
index c681ab6..a74653d 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0OrganizationHandler.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0OrganizationHandler.java
@@ -239,10 +239,11 @@ public void delete(Uid uid, OperationOptions options) throws Auth0Exception {
* @param filter
* @param resultsHandler
* @param options
+ * @return
* @throws Auth0Exception
*/
- public void query(Auth0Filter filter,
- ResultsHandler resultsHandler, OperationOptions options) throws Auth0Exception {
+ public int query(Auth0Filter filter,
+ ResultsHandler resultsHandler, OperationOptions options) throws Auth0Exception {
// Create full attributesToGet by RETURN_DEFAULT_ATTRIBUTES + ATTRIBUTES_TO_GET
Set attributesToGet = createFullAttributesToGet(schema, options);
boolean allowPartialAttributeValues = shouldAllowPartialAttributeValues(options);
@@ -250,29 +251,32 @@ public void query(Auth0Filter filter,
if (filter != null) {
if (filter.isByName()) {
// Filter by __NANE__
- getOrganizationByName(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getOrganizationByName(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
} else {
// Filter by __UID__
- getOrganizationByUid(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getOrganizationByUid(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
}
- return;
}
- client.getOrganizations(options, (org) -> resultsHandler.handle(toConnectorObject(org, attributesToGet, allowPartialAttributeValues)));
+ return client.getOrganizations(options, (org) -> resultsHandler.handle(toConnectorObject(org, attributesToGet, allowPartialAttributeValues)));
}
- private void getOrganizationByName(String orgName,
- ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getOrganizationByName(String orgName,
+ ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
Organization org = client.getOrganizationByName(orgName);
resultsHandler.handle(toConnectorObject(org, attributesToGet, allowPartialAttributeValues));
+
+ return 1;
}
- private void getOrganizationByUid(String orgId,
- ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getOrganizationByUid(String orgId,
+ ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
Organization org = client.getOrganizationByUid(orgId);
resultsHandler.handle(toConnectorObject(org, attributesToGet, allowPartialAttributeValues));
+
+ return 1;
}
private ConnectorObject toConnectorObject(Organization org, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0RoleHandler.java b/src/main/java/jp/openstandia/connector/auth0/Auth0RoleHandler.java
index cfe3f36..0e48d76 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0RoleHandler.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0RoleHandler.java
@@ -212,9 +212,10 @@ public void deleteRole(Uid uid, OperationOptions options) throws Auth0Exception
* @param resultsHandler
* @param options
* @throws Auth0Exception
+ * @return
*/
- public void getRoles(Auth0Filter filter,
- ResultsHandler resultsHandler, OperationOptions options) throws Auth0Exception {
+ public int getRoles(Auth0Filter filter,
+ ResultsHandler resultsHandler, OperationOptions options) throws Auth0Exception {
// Create full attributesToGet by RETURN_DEFAULT_ATTRIBUTES + ATTRIBUTES_TO_GET
Set attributesToGet = createFullAttributesToGet(schema, options);
boolean allowPartialAttributeValues = shouldAllowPartialAttributeValues(options);
@@ -222,31 +223,34 @@ public void getRoles(Auth0Filter filter,
if (filter != null) {
if (filter.isByName()) {
// Filter by __NANE__
- getRoleByName(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getRoleByName(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
} else {
// Filter by __UID__
- getRoleByUid(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getRoleByUid(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
}
- return;
}
- client.getRoles(options, (role) -> resultsHandler.handle(toConnectorObject(role, attributesToGet, allowPartialAttributeValues)));
+ return client.getRoles(options, (role) -> resultsHandler.handle(toConnectorObject(role, attributesToGet, allowPartialAttributeValues)));
}
- private void getRoleByName(String roleName,
- ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getRoleByName(String roleName,
+ ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
List response = client.getRoleByName(roleName);
for (Role role : response) {
resultsHandler.handle(toConnectorObject(role, attributesToGet, allowPartialAttributeValues));
}
+
+ return response.size();
}
- private void getRoleByUid(String roleId,
- ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getRoleByUid(String roleId,
+ ResultsHandler resultsHandler, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
Role role = client.getRoleByUid(roleId);
resultsHandler.handle(toConnectorObject(role, attributesToGet, allowPartialAttributeValues));
+
+ return 1;
}
private ConnectorObject toConnectorObject(Role role, Set attributesToGet, boolean allowPartialAttributeValues) throws Auth0Exception {
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0UserHandler.java b/src/main/java/jp/openstandia/connector/auth0/Auth0UserHandler.java
index ce078bb..56f201a 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0UserHandler.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0UserHandler.java
@@ -564,7 +564,7 @@ public void deleteUser(Uid uid, OperationOptions options) throws Auth0Exception
client.deleteUser(uid);
}
- public void getUsers(Auth0Filter filter, ResultsHandler resultsHandler, OperationOptions options) throws
+ public int getUsers(Auth0Filter filter, ResultsHandler resultsHandler, OperationOptions options) throws
Auth0Exception {
// Create full attributesToGet by RETURN_DEFAULT_ATTRIBUTES + ATTRIBUTES_TO_GET
Set attributesToGet = createFullAttributesToGet(schema, options);
@@ -574,33 +574,34 @@ public void getUsers(Auth0Filter filter, ResultsHandler resultsHandler, Operatio
if (filter.isByName()) {
// Filter by __NANE__
if (isSMS()) {
- getUserByPhoneNumber(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getUserByPhoneNumber(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
} else {
- getUserByEmail(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getUserByEmail(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
}
} else {
// Filter by __UID__
- getUserByUid(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
+ return getUserByUid(filter.attributeValue, resultsHandler, attributesToGet, allowPartialAttributeValues);
}
- return;
}
UserFilter userFilter = applyFieldsFilter(attributesToGet, new UserFilter(), ADDITIONAL_ALLOWED_FIELDS_SET)
.withQuery("identities.connection:\"" + connection + "\"");
- client.getUsers(userFilter, options, (user) -> resultsHandler.handle(toConnectorObject(user, attributesToGet, allowPartialAttributeValues)));
+ return client.getUsers(userFilter, options, (user) -> resultsHandler.handle(toConnectorObject(user, attributesToGet, allowPartialAttributeValues)));
}
- private void getUserByUid(String userId, ResultsHandler resultsHandler, Set attributesToGet,
- boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getUserByUid(String userId, ResultsHandler resultsHandler, Set attributesToGet,
+ boolean allowPartialAttributeValues) throws Auth0Exception {
UserFilter filter = applyFieldsFilter(attributesToGet, new UserFilter(), Collections.emptySet());
User user = client.getUserByUid(userId, filter);
resultsHandler.handle(toConnectorObject(user, attributesToGet, allowPartialAttributeValues));
+
+ return 1;
}
- private void getUserByPhoneNumber(String attrValue, ResultsHandler resultsHandler, Set attributesToGet,
- boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getUserByPhoneNumber(String attrValue, ResultsHandler resultsHandler, Set attributesToGet,
+ boolean allowPartialAttributeValues) throws Auth0Exception {
attrValue = attrValue.replace("\"", "\\\"");
UserFilter filter = new UserFilter()
.withPage(0, 1)
@@ -612,10 +613,12 @@ private void getUserByPhoneNumber(String attrValue, ResultsHandler resultsHandle
for (User user : response) {
resultsHandler.handle(toConnectorObject(user, attributesToGet, allowPartialAttributeValues));
}
+
+ return response.size();
}
- private void getUserByEmail(String email, ResultsHandler resultsHandler, Set attributesToGet,
- boolean allowPartialAttributeValues) throws Auth0Exception {
+ private int getUserByEmail(String email, ResultsHandler resultsHandler, Set attributesToGet,
+ boolean allowPartialAttributeValues) throws Auth0Exception {
email = email.replace("\"", "\\\"");
UserFilter filter = new UserFilter()
.withPage(0, 1)
@@ -628,6 +631,8 @@ private void getUserByEmail(String email, ResultsHandler resultsHandler, Set attributesToGet,
@@ -662,7 +667,9 @@ private ConnectorObject toConnectorObject(User user, Set attributesToGet
builderWrapper.apply(ATTR_NICKNAME, user.getNickname());
builderWrapper.apply(ATTR_GIVEN_NAME, user.getGivenName());
builderWrapper.apply(ATTR_FAMILY_NAME, user.getFamilyName());
- builderWrapper.apply(ATTR_CONNECTION, user.getIdentities().stream().map(i -> i.getConnection()).collect(Collectors.toList()));
+ builderWrapper.apply(ATTR_CONNECTION, user.getIdentities() != null ?
+ user.getIdentities().stream().map(i -> i.getConnection()).collect(Collectors.toList()) :
+ null);
if (allowPartialAttributeValues) {
// Suppress fetching association
diff --git a/src/main/java/jp/openstandia/connector/auth0/Auth0Utils.java b/src/main/java/jp/openstandia/connector/auth0/Auth0Utils.java
index 91a17ea..a6d77da 100644
--- a/src/main/java/jp/openstandia/connector/auth0/Auth0Utils.java
+++ b/src/main/java/jp/openstandia/connector/auth0/Auth0Utils.java
@@ -202,6 +202,7 @@ public static Set createFullAttributesToGet(Map s
for (String a : options.getAttributesToGet()) {
attributesToGet.add(a);
}
+ attributesToGet.add(Uid.NAME);
}
return attributesToGet;
}
diff --git a/src/test/java/jp/openstandia/connector/auth0/Auth0ClientTest.java b/src/test/java/jp/openstandia/connector/auth0/Auth0ClientTest.java
new file mode 100644
index 0000000..dec30ed
--- /dev/null
+++ b/src/test/java/jp/openstandia/connector/auth0/Auth0ClientTest.java
@@ -0,0 +1,419 @@
+package jp.openstandia.connector.auth0;
+
+import com.auth0.client.mgmt.filter.PageFilter;
+import com.auth0.exception.Auth0Exception;
+import com.auth0.json.auth.TokenHolder;
+import com.auth0.json.mgmt.Page;
+import com.auth0.json.mgmt.users.User;
+import com.auth0.json.mgmt.users.UsersPage;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class Auth0ClientTest {
+
+ @Test
+ void expiredAuth0Token() {
+ Auth0Client client = new Auth0Client();
+
+ // Given
+ // 1655111797586 = 2022/06/13 18:16:37.586 GMT+09:00
+ // 1655111737586 = 2022/06/13 18:15:37.586 GMT+09:00
+ // 1655111737587 = 2022/06/13 18:15:37.587 GMT+09:00
+ TokenHolder holder = new TokenHolder(null, null, null, "Bearer", 864000L, "openid", new Date(1655111797586L));
+ Date now1 = new Date(1655111737586L);
+ Date now2 = new Date(1655111737587L);
+
+ // When
+ boolean expired1 = client.isExpired(holder, now1);
+ boolean expired2 = client.isExpired(holder, now2);
+
+ // Then
+ assertFalse(expired1);
+ assertTrue(expired2);
+ }
+
+ @Test
+ void zeroWithFullPage() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 50;
+
+ // When
+ int i = client.withAuthPaging(filter, 0, limit, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ Page response = new UsersPage(0, users.size(), users.size(), limit, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(0, i);
+ }
+
+ @Test
+ void oneWithFullPage() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 50;
+
+ // When
+ int i = client.withAuthPaging(filter, 0, limit, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("1"));
+ Page response = new UsersPage(0, users.size(), users.size(), limit, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(1, i);
+ }
+
+ @Test
+ void twoWithFullPage() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 50;
+
+ // When
+ int i = client.withAuthPaging(filter, 0, limit, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("1"));
+ users.add(newUser("2"));
+ Page response = new UsersPage(0, users.size(), users.size(), limit, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(2, i);
+ }
+
+ @Test
+ void nextPageWithFullPage() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 2;
+
+ // When
+ AtomicInteger count = new AtomicInteger(0);
+ int i = client.withAuthPaging(filter, 0, limit, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+
+ switch (count.incrementAndGet()) {
+ case 1: {
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("1"));
+ users.add(newUser("2"));
+ Page response = new UsersPage(0, users.size(), 3, limit, null, users);
+ return response;
+ }
+ case 2: {
+ assertEquals(1, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("3"));
+ Page response = new UsersPage(2, users.size(), 3, limit, null, users);
+ return response;
+ }
+ }
+ fail("Unexpected called");
+ return null;
+ });
+
+ // Then
+ assertEquals(3, i);
+ assertEquals(2, count.get());
+ }
+
+ @Test
+ void countZero() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+
+ // When
+ // For count requested, pageOffset and pageSize are 1
+ int i = client.withAuthPaging(filter, 1, 1, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(1, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ Page response = new UsersPage(0, users.size(), users.size(), 1, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(0, i);
+ }
+
+ @Test
+ void countOne() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+
+ // When
+ // For count requested, pageOffset and pageSize are 1
+ int i = client.withAuthPaging(filter, 1, 1, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(1, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("1"));
+ Page response = new UsersPage(0, users.size(), users.size(), 1, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(1, i);
+ }
+
+ @Test
+ void zeroWithOffset() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 2;
+
+ // When
+ int i = client.withAuthPaging(filter, 1, limit, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ Page response = new UsersPage(0, users.size(), 0, limit, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(0, i);
+ }
+
+ @Test
+ void oneWithOffset() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 2;
+
+ // When
+ int i = client.withAuthPaging(filter, 1, limit, (f, skipCount) -> {
+ assertEquals(0, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("1"));
+ Page response = new UsersPage(0, users.size(), 1, limit, null, users);
+ return response;
+ });
+
+ // Then
+ assertEquals(1, i);
+ }
+
+ @Test
+ void oneWithOffset2() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 2;
+
+ // When
+ AtomicInteger count = new AtomicInteger(0);
+ int i = client.withAuthPaging(filter, 2, limit, (f, skipCount) -> {
+ switch (count.incrementAndGet()) {
+ case 1: {
+ assertEquals(1, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ // skipped by skipCount
+ // users.add(newUser("1"));
+ Page response = new UsersPage(1, users.size(), 1, limit, null, users);
+ return response;
+ }
+ }
+ fail("Unexpected called");
+ return null;
+ });
+
+ // Then
+ assertEquals(1, i);
+ assertEquals(1, count.get());
+ }
+
+ @Test
+ void threeWithOffset2() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 2;
+
+ // When
+ AtomicInteger count = new AtomicInteger(0);
+ int i = client.withAuthPaging(filter, 2, limit, (f, skipCount) -> {
+ switch (count.incrementAndGet()) {
+ case 1: {
+ assertEquals(1, skipCount);
+ assertEquals(0, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ // skipped by skipCount
+ // users.add(newUser("1"));
+ users.add(newUser("2"));
+ Page response = new UsersPage(1, users.size(), 3, limit, null, users);
+ return response;
+ }
+ case 2: {
+ assertEquals(0, skipCount);
+ assertEquals(1, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("3"));
+ Page response = new UsersPage(1, users.size(), 3, limit, null, users);
+ return response;
+ }
+ }
+ fail("Unexpected called");
+ return null;
+ });
+
+ // Then
+ assertEquals(3, i);
+ assertEquals(2, count.get());
+ }
+
+ @Test
+ void threeWithOffset3() throws Auth0Exception {
+ Auth0Client client = new Auth0Client() {
+ @Override
+ protected T withAuth(APIFunction callback) throws Auth0Exception {
+ return callback.apply();
+ }
+ };
+
+ // Given
+ PageFilter filter = new PageFilter();
+ int limit = 2;
+
+ // When
+ AtomicInteger count = new AtomicInteger(0);
+ int i = client.withAuthPaging(filter, 3, limit, (f, skipCount) -> {
+ switch (count.incrementAndGet()) {
+ case 1: {
+ assertEquals(0, skipCount);
+ assertEquals(1, filter.getAsMap().get("page"));
+ assertEquals(limit, filter.getAsMap().get("per_page"));
+
+ List users = new ArrayList<>();
+ users.add(newUser("3"));
+ Page response = new UsersPage(2, users.size(), 3, limit, null, users);
+ return response;
+ }
+ }
+ fail("Unexpected called");
+ return null;
+ });
+
+ // Then
+ assertEquals(3, i);
+ assertEquals(1, count.get());
+ }
+
+ private User newUser(String id) {
+ User user = new User("test");
+ user.setId(id);
+ return user;
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/jp/openstandia/connector/auth0/testutil/MockClient.java b/src/test/java/jp/openstandia/connector/auth0/testutil/MockClient.java
index d3ae62f..c8552a9 100644
--- a/src/test/java/jp/openstandia/connector/auth0/testutil/MockClient.java
+++ b/src/test/java/jp/openstandia/connector/auth0/testutil/MockClient.java
@@ -108,8 +108,9 @@ public List getUsersByFilter(UserFilter filter) throws Auth0Exception {
}
@Override
- public void getUsers(UserFilter userFilter, OperationOptions options, Auth0Client.ResultHandlerFunction resultsHandler) throws Auth0Exception {
+ public int getUsers(UserFilter userFilter, OperationOptions options, ResultHandlerFunction resultsHandler) throws Auth0Exception {
getUsers.accept(userFilter, options, resultsHandler);
+ return 0;
}
@Override