From 1d51136baddb4f97defdff19d0c49227ffa35c31 Mon Sep 17 00:00:00 2001 From: nmcorrea Date: Thu, 14 Aug 2025 14:35:56 -0300 Subject: [PATCH] add read-only support for GitHub Copilot Enterprise plan seats --- pom.xml | 6 +- .../connector/github/GitHubClient.java | 19 +- .../github/GitHubCopilotSeatHandler.java | 195 ++++++++++++++++++ .../connector/github/GitHubEMUSchema.java | 4 +- .../github/rest/GitHubEMURESTClient.java | 48 ++++- .../org/kohsuke/github/GHEnterpriseExt.java | 31 +++ .../org/kohsuke/github/GitHubCopilotSeat.java | 34 +++ .../github/GitHubCopilotSeatAssignee.java | 26 +++ .../GitHubCopilotSeatAssigningTeam.java | 24 +++ .../github/GitHubCopilotSeatPageIterator.java | 114 ++++++++++ .../GitHubCopilotSeatPagedSearchIterable.java | 69 +++++++ .../GitHubCopilotSeatsSearchBuilder.java | 52 +++++ .../GitHubCopilotSeatsSearchResult.java | 11 + .../connector/github/CreateUserOpTest.java | 34 +++ .../connector/github/DeleteUsersOpTest.java | 19 ++ .../connector/github/EMUSchemaTest.java | 4 +- .../connector/github/ListResultHandler.java | 19 ++ .../connector/github/SearchGroupsOpTest.java | 54 +++++ .../connector/github/SearchSeatsOpTest.java | 54 +++++ .../connector/github/SearchUsersOpTest.java | 54 +++++ .../connector/github/TestOpTest.java | 14 ++ .../connector/github/UpdateGroupsOpTest.java | 80 +++++++ .../connector/github/UpdateUsersOpTest.java | 92 +++++++++ .../github/testutil/AbstractEMUTest.java | 9 +- 24 files changed, 1056 insertions(+), 10 deletions(-) create mode 100644 src/main/java/jp/openstandia/connector/github/GitHubCopilotSeatHandler.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeat.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeatAssignee.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeatAssigningTeam.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeatPageIterator.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeatPagedSearchIterable.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchBuilder.java create mode 100644 src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchResult.java create mode 100644 src/test/java/jp/openstandia/connector/github/CreateUserOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/DeleteUsersOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/ListResultHandler.java create mode 100644 src/test/java/jp/openstandia/connector/github/SearchGroupsOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/SearchSeatsOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/SearchUsersOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/TestOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/UpdateGroupsOpTest.java create mode 100644 src/test/java/jp/openstandia/connector/github/UpdateUsersOpTest.java diff --git a/pom.xml b/pom.xml index afc396a..e869143 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ jp.openstandia.connector connector-github - 1.2.5-SNAPSHOT + 1.2.6-SNAPSHOT jar GitHub Connector @@ -73,6 +73,10 @@ org.apache.maven.plugins maven-compiler-plugin + + 9 + 9 + org.apache.maven.plugins diff --git a/src/main/java/jp/openstandia/connector/github/GitHubClient.java b/src/main/java/jp/openstandia/connector/github/GitHubClient.java index 14ff6cf..7629d1a 100644 --- a/src/main/java/jp/openstandia/connector/github/GitHubClient.java +++ b/src/main/java/jp/openstandia/connector/github/GitHubClient.java @@ -27,10 +27,7 @@ import org.identityconnectors.framework.common.objects.OperationOptions; import org.identityconnectors.framework.common.objects.ResultsHandler; import org.identityconnectors.framework.common.objects.Uid; -import org.kohsuke.github.SCIMEMUGroup; -import org.kohsuke.github.SCIMEMUUser; -import org.kohsuke.github.SCIMPatchOperations; -import org.kohsuke.github.SCIMUser; +import org.kohsuke.github.*; import java.net.InetSocketAddress; import java.net.Proxy; @@ -205,5 +202,19 @@ default SCIMEMUGroup getEMUGroup(Uid uid, OperationOptions options, Set default SCIMEMUGroup getEMUGroup(Name name, OperationOptions options, Set attributesToGet) { throw new UnsupportedOperationException(); } + + // Copilot Seats + + default GitHubCopilotSeat getCopilotSeat(Uid uid, OperationOptions options, Set attributesToGet) { + throw new UnsupportedOperationException(); + } + + default GitHubCopilotSeat getCopilotSeat(Name name, OperationOptions options, Set attributesToGet) { + throw new UnsupportedOperationException(); + } + + default int getCopilotSeats(QueryHandler handler, OperationOptions options, Set fetchFieldsSet, int pageSize, int pageOffset) { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/jp/openstandia/connector/github/GitHubCopilotSeatHandler.java b/src/main/java/jp/openstandia/connector/github/GitHubCopilotSeatHandler.java new file mode 100644 index 0000000..71f376b --- /dev/null +++ b/src/main/java/jp/openstandia/connector/github/GitHubCopilotSeatHandler.java @@ -0,0 +1,195 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.util.SchemaDefinition; +import org.identityconnectors.common.logging.Log; +import org.identityconnectors.framework.common.objects.*; +import org.kohsuke.github.GitHubCopilotSeat; +import org.kohsuke.github.SCIMPatchOperations; + +import java.util.Set; + +import static jp.openstandia.connector.util.Utils.toZoneDateTime; +import static jp.openstandia.connector.util.Utils.toZoneDateTimeForISO8601OffsetDateTime; +import static org.identityconnectors.framework.common.objects.AttributeInfo.Flags.*; + +public class GitHubCopilotSeatHandler extends AbstractGitHubEMUHandler { + + public static final ObjectClass SEAT_OBJECT_CLASS = new ObjectClass("GitHubCopilotSeat"); + + private static final Log LOGGER = Log.getLog(GitHubCopilotSeatHandler.class); + + public GitHubCopilotSeatHandler(GitHubEMUConfiguration configuration, GitHubClient client, + GitHubEMUSchema schema, SchemaDefinition schemaDefinition) { + super(configuration, client, schema, schemaDefinition); + } + + public static SchemaDefinition.Builder createSchema(AbstractGitHubConfiguration configuration, GitHubClient client) { + SchemaDefinition.Builder sb + = SchemaDefinition.newBuilder(SEAT_OBJECT_CLASS, GitHubCopilotSeat.class, SCIMPatchOperations.class, GitHubCopilotSeat.class); + + // __UID__ + // The id for the seat. Must be unique and unchangeable. + sb.addUid("id", + SchemaDefinition.Types.UUID, + null, + (source) -> source.assignee.id, + "id", + NOT_CREATABLE, NOT_UPDATEABLE + ); + + // code (__NAME__) + // The name for the seat. Must be unique and changeable. + sb.addName("displayName", + SchemaDefinition.Types.STRING_CASE_IGNORE, + (source, dest) -> dest.assignee.login = source, + (source, dest) -> dest.replace("displayName", source), + (source) -> source.assignee.login, + null, + REQUIRED + ); + + // Metadata (readonly) + sb.add("created_at", + SchemaDefinition.Types.DATETIME, + null, + (source) -> source.created_at != null ? toZoneDateTimeForISO8601OffsetDateTime(source.created_at) : null, + null, + NOT_CREATABLE, NOT_UPDATEABLE + ); + + sb.add("last_authenticated_at", + SchemaDefinition.Types.DATETIME, + null, + (source) -> source.last_authenticated_at != null ? toZoneDateTimeForISO8601OffsetDateTime(source.last_authenticated_at) : null, + null, + NOT_CREATABLE, NOT_UPDATEABLE + ); + + sb.add("updated_at", + SchemaDefinition.Types.DATETIME, + null, + (source) -> source.updated_at != null ? toZoneDateTimeForISO8601OffsetDateTime(source.updated_at) : null, + null, + NOT_CREATABLE, NOT_UPDATEABLE + ); + + sb.add("last_activity_at", + SchemaDefinition.Types.DATETIME, + null, + (source) -> source.last_activity_at != null ? toZoneDateTimeForISO8601OffsetDateTime(source.last_activity_at) : null, + null, + NOT_CREATABLE, NOT_UPDATEABLE + ); + + sb.add("pending_cancellation_date", + SchemaDefinition.Types.DATETIME, + null, + (source) -> source.pending_cancellation_date != null ? toZoneDateTime(source.pending_cancellation_date) : null, + null, + NOT_CREATABLE, NOT_UPDATEABLE + ); + + sb.add("last_activity_editor", + SchemaDefinition.Types.STRING, + (source, dest) -> { + dest.last_activity_editor = source; + }, + (source, dest) -> dest.replace("last_activity_editor", source), + (source) -> source.last_activity_editor, + null + ); + + sb.add("plan_type", + SchemaDefinition.Types.STRING, + (source, dest) -> { + dest.plan_type = source; + }, + (source, dest) -> dest.replace("plan_type", source), + (source) -> source.plan_type, + null + ); + + sb.add("assignee.type", + SchemaDefinition.Types.STRING, + (source, dest) -> { + dest.assignee.type = source; + }, + (source, dest) -> dest.replace("assignee.type", source), + (source) -> source.assignee.type, + null + ); + + sb.add("assigning_team.slug", + SchemaDefinition.Types.STRING, + (source, dest) -> { + if (source != null) { + dest.assigning_team.slug = source; + } + }, + (source, dest) -> dest.replace("assigning_team.slug", source), + (source) -> source != null && source.assigning_team != null ? source.assigning_team.slug : null, + null + ); + + LOGGER.ok("The constructed GitHub EMU Seat schema"); + + return sb; + } + + @Override + public Uid create(Set attributes) { + return null; + } + + @Override + public Set updateDelta(Uid uid, Set modifications, OperationOptions options) { + return Set.of(); + } + + @Override + public void delete(Uid uid, OperationOptions options) { + } + + @Override + public int getByUid(Uid uid, ResultsHandler resultsHandler, OperationOptions options, Set returnAttributesSet, Set fetchFieldsSet, boolean allowPartialAttributeValues, int pageSize, int pageOffset) { + GitHubCopilotSeat seat = client.getCopilotSeat(uid, options, fetchFieldsSet); + + if (seat != null) { + resultsHandler.handle(toConnectorObject(schemaDefinition, seat, returnAttributesSet, allowPartialAttributeValues)); + return 1; + } + return 0; + } + + @Override + public int getByName(Name name, ResultsHandler resultsHandler, OperationOptions options, Set returnAttributesSet, Set fetchFieldsSet, boolean allowPartialAttributeValues, int pageSize, int pageOffset) { + GitHubCopilotSeat seat = client.getCopilotSeat(name, options, fetchFieldsSet); + + if (seat != null) { + resultsHandler.handle(toConnectorObject(schemaDefinition, seat, returnAttributesSet, allowPartialAttributeValues)); + return 1; + } + return 0; + } + + @Override + public int getByMembers(Attribute attribute, ResultsHandler resultsHandler, OperationOptions options, Set returnAttributesSet, Set fetchFieldSet, boolean allowPartialAttributeValues, int pageSize, int pageOffset) { + return super.getByMembers(attribute, resultsHandler, options, returnAttributesSet, fetchFieldSet, allowPartialAttributeValues, pageSize, pageOffset); + } + + @Override + public int getAll(ResultsHandler resultsHandler, OperationOptions options, Set returnAttributesSet, Set fetchFieldsSet, boolean allowPartialAttributeValues, int pageSize, int pageOffset) { + return client.getCopilotSeats((s) -> resultsHandler.handle(toConnectorObject(schemaDefinition, s, returnAttributesSet, allowPartialAttributeValues)), + options, fetchFieldsSet, pageSize, pageOffset); + } + + @Override + public void query(GitHubFilter filter, ResultsHandler resultsHandler, OperationOptions options) { + super.query(filter, resultsHandler, options); + } + + @Override + public ConnectorObject toConnectorObject(SchemaDefinition schema, T user, Set returnAttributesSet, boolean allowPartialAttributeValues) { + return super.toConnectorObject(schema, user, returnAttributesSet, allowPartialAttributeValues); + } +} \ No newline at end of file diff --git a/src/main/java/jp/openstandia/connector/github/GitHubEMUSchema.java b/src/main/java/jp/openstandia/connector/github/GitHubEMUSchema.java index ad65c50..269baae 100644 --- a/src/main/java/jp/openstandia/connector/github/GitHubEMUSchema.java +++ b/src/main/java/jp/openstandia/connector/github/GitHubEMUSchema.java @@ -32,12 +32,14 @@ public class GitHubEMUSchema extends AbstractGitHubSchema client) { super(configuration, client); - SchemaBuilder schemaBuilder = new SchemaBuilder(GitHubConnector.class); + SchemaBuilder schemaBuilder = new SchemaBuilder(GitHubEMUConnector.class); buildSchema(schemaBuilder, GitHubEMUUserHandler.createSchema(configuration, client).build(), (schema) -> new GitHubEMUUserHandler(configuration, client, this, schema)); buildSchema(schemaBuilder, GitHubEMUGroupHandler.createSchema(configuration, client).build(), (schema) -> new GitHubEMUGroupHandler(configuration, client, this, schema)); + buildSchema(schemaBuilder, GitHubCopilotSeatHandler.createSchema(configuration, client).build(), + (schema) -> new GitHubCopilotSeatHandler(configuration, client, this, schema)); // Define operation options schemaBuilder.defineOperationOption(OperationOptionInfoBuilder.buildAttributesToGet(), SearchOp.class); diff --git a/src/main/java/jp/openstandia/connector/github/rest/GitHubEMURESTClient.java b/src/main/java/jp/openstandia/connector/github/rest/GitHubEMURESTClient.java index eb6e5fa..cd3d0a3 100644 --- a/src/main/java/jp/openstandia/connector/github/rest/GitHubEMURESTClient.java +++ b/src/main/java/jp/openstandia/connector/github/rest/GitHubEMURESTClient.java @@ -52,7 +52,6 @@ public class GitHubEMURESTClient implements GitHubClient { public GitHubEMURESTClient(GitHubEMUConfiguration configuration) { this.configuration = configuration; - auth(); } @@ -286,6 +285,53 @@ public SCIMEMUGroup getEMUGroup(Name name, OperationOptions options, Set }); } + @Override + public GitHubCopilotSeat getCopilotSeat(Uid uid, OperationOptions options, Set attributesToGet) { + return withAuth(() -> { + GitHubCopilotSeat seat = enterpriseApiClient.getCopilotSeatByUid(uid.getUidValue()); + return seat; + }); + } + + @Override + public GitHubCopilotSeat getCopilotSeat(Name name, OperationOptions options, Set attributesToGet) { + return withAuth(() -> { + GitHubCopilotSeat seat = enterpriseApiClient.getCopilotSeatByDisplayName(name.getNameValue()); + return seat; + }); + } + + @Override + public int getCopilotSeats(QueryHandler handler, OperationOptions options, Set fetchFieldsSet, int pageSize, int pageOffset) { + return withAuth(() -> { + GitHubCopilotSeatPagedSearchIterable iterable = enterpriseApiClient.listAllSeats(pageSize, pageOffset); + + // 0 means no offset (requested all data) + if (pageOffset < 1) { + for (GitHubCopilotSeat next : iterable) { + if (!handler.handle(next)) { + break; + } + } + return iterable.getTotalSeats(); + } + + // Pagination + int count = 0; + for (GitHubCopilotSeat next : iterable) { + count++; + if (!handler.handle(next)) { + break; + } + if (count >= pageSize) { + break; + } + } + + return iterable.getTotalSeats(); + }); + } + @Override public int getEMUGroups(QueryHandler handler, OperationOptions options, Set fetchFieldsSet, int pageSize, int pageOffset) { return withAuth(() -> { diff --git a/src/main/java/org/kohsuke/github/GHEnterpriseExt.java b/src/main/java/org/kohsuke/github/GHEnterpriseExt.java index 95c0a9a..0803038 100644 --- a/src/main/java/org/kohsuke/github/GHEnterpriseExt.java +++ b/src/main/java/org/kohsuke/github/GHEnterpriseExt.java @@ -155,6 +155,28 @@ public SCIMEMUGroup getSCIMEMUGroupByDisplayName(String scimGroupDisplayName) th return list.get(0); } + public GitHubCopilotSeat getCopilotSeatByDisplayName(String copilotSeatDisplayName) throws IOException { + List allSeats = searchCopilotSeats() + .list() + .toList(); + + return allSeats.stream() + .filter(seat -> copilotSeatDisplayName.equals(seat.assignee.login)) + .findFirst() + .orElse(null); + } + + public GitHubCopilotSeat getCopilotSeatByUid(String copilotSeatUid) throws IOException { + List allSeats = searchCopilotSeats() + .list() + .toList(); + + return allSeats.stream() + .filter(seat -> copilotSeatUid.equals(seat.assignee.id)) + .findFirst() + .orElse(null); + } + /** * Search groups. * @@ -169,6 +191,15 @@ public SCIMPagedSearchIterable listSCIMGroups(int pageSize, int pa return searchSCIMGroups().list().withPageSize(pageSize).withPageOffset(pageOffset); } + public GitHubCopilotSeatsSearchBuilder searchCopilotSeats() { + return new GitHubCopilotSeatsSearchBuilder(root, this); + } + + public GitHubCopilotSeatPagedSearchIterable listAllSeats(int pageSize, int pageOffset) + throws IOException { + return searchCopilotSeats().list().withPageSize(pageSize).withPageOffset(pageOffset); + } + public void deleteSCIMGroup(String scimGroupId) throws IOException { root.createRequest() .method("DELETE") diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeat.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeat.java new file mode 100644 index 0000000..b1bdbc2 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeat.java @@ -0,0 +1,34 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GitHubCopilotSeat { + @JsonProperty("created_at") + public String created_at; + + @JsonProperty("assignee") + public GitHubCopilotSeatAssignee assignee; + + @JsonProperty("pending_cancellation_date") + public String pending_cancellation_date; + + @JsonProperty("plan_type") + public String plan_type; + + @JsonProperty("last_authenticated_at") + public String last_authenticated_at; + + @JsonProperty("updated_at") + public String updated_at; + + @JsonProperty("last_activity_at") + public String last_activity_at; + + @JsonProperty("last_activity_editor") + public String last_activity_editor; + + @JsonProperty("assigning_team") + public GitHubCopilotSeatAssigningTeam assigning_team; +} \ No newline at end of file diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeatAssignee.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeatAssignee.java new file mode 100644 index 0000000..0eb8a74 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeatAssignee.java @@ -0,0 +1,26 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GitHubCopilotSeatAssignee { + @JsonProperty("login") + public String login; + + @JsonProperty("id") + public String id; + + @JsonProperty("node_id") + public String node_id; + + @JsonProperty("url") + public String url; + + @JsonProperty("type") + public String type; + + @JsonProperty("user_view_type") + public String user_view_type; + + @JsonProperty("site_admin") + public String site_admin; +} \ No newline at end of file diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeatAssigningTeam.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeatAssigningTeam.java new file mode 100644 index 0000000..41c2941 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeatAssigningTeam.java @@ -0,0 +1,24 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GitHubCopilotSeatAssigningTeam { + + @JsonProperty("id") + public String id; + + @JsonProperty("name") + public String name; + + @JsonProperty("slug") + public String slug; + + @JsonProperty("group_name") + public String group_name; + + @JsonProperty("created_at") + public String created_at; + + @JsonProperty("updated_at") + public String updated_at; +} diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeatPageIterator.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeatPageIterator.java new file mode 100644 index 0000000..ea7993a --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeatPageIterator.java @@ -0,0 +1,114 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Used for seats pagination information. + *

+ * This class is not thread-safe. Any one instance should only be called from a single thread. + * + * @param the type parameter + * @author Hiroyuki Wada + * @author Nikolas Correa + */ +public class GitHubCopilotSeatPageIterator implements Iterator { + + private final GitHubClient client; + private final Class type; + + private T next; + + private GitHubRequest nextRequest; + + private GitHubResponse finalResponse = null; + + private GitHubCopilotSeatPageIterator(GitHubClient client, Class type, GitHubRequest request) { + if (!"GET".equals(request.method())) { + throw new IllegalStateException("Request method \"GET\" is required for page iterator."); + } + + this.client = client; + this.type = type; + this.nextRequest = request; + } + + static GitHubCopilotSeatPageIterator create(GitHubClient client, Class type, GitHubRequest request, int pageSize, int pageOffset) { + + try { + if (pageSize > 0) { + GitHubRequest.Builder builder = request.toBuilder().with("count", pageSize); + if (pageOffset > 0) { + builder.with("startIndex", pageOffset); + } + request = builder.build(); + } + + return new GitHubCopilotSeatPageIterator<>(client, type, request); + } catch (MalformedURLException e) { + throw new GHException("Unable to build GitHub SCIM API URL", e); + } + } + + public boolean hasNext() { + fetch(); + return next != null; + } + + public T next() { + fetch(); + T result = next; + if (result == null) + throw new NoSuchElementException(); + next = null; + return result; + } + + public GitHubResponse finalResponse() { + if (hasNext()) { + throw new GHException("Final response is not available until after iterator is done."); + } + return finalResponse; + } + + private void fetch() { + if (next != null || nextRequest == null) + return; + + URL url = nextRequest.url(); + try { + GitHubResponse nextResponse = client.sendRequest(nextRequest, + (responseInfo) -> GitHubResponse.parseBody(responseInfo, type)); + next = nextResponse.body(); + nextRequest = findNextURL(nextResponse); + if (nextRequest == null) { + finalResponse = nextResponse; + } + } catch (IOException e) { + throw new GHException("Failed to retrieve " + url, e); + } + } + + private GitHubRequest findNextURL(GitHubResponse response) { + String linkHeader = response.headerField("Link"); + if (linkHeader == null) return null; + + // Expressão para capturar: ; rel="next" + Pattern pattern = Pattern.compile("<([^>]+)>;\\s*rel=\"next\""); + Matcher matcher = pattern.matcher(linkHeader); + if (matcher.find()) { + String nextUrl = matcher.group(1); + try { + return GitHubRequest.newBuilder().withUrlPath(nextUrl).build(); + } catch (Exception e) { + throw new GHException("Malformed next URL: " + nextUrl, e); + } + } + return null; + } +} diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeatPagedSearchIterable.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeatPagedSearchIterable.java new file mode 100644 index 0000000..f442501 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeatPagedSearchIterable.java @@ -0,0 +1,69 @@ +package org.kohsuke.github; + +import java.util.Iterator; + +/** + * {@link PagedIterable} enhanced to report search result specific information. + * + * @param the type parameter + * @author Hiroyuki Wada + * @author Nikolas Correa + */ +public class GitHubCopilotSeatPagedSearchIterable extends PagedIterable { + private final transient GitHub root; + + private final GitHubRequest request; + + private final Class> receiverType; + + private GitHubCopilotSeatsSearchResult result; + private int pageOffset; + + public GitHubCopilotSeatPagedSearchIterable(GitHub root, GitHubRequest request, Class> receiverType) { + this.root = root; + this.request = request; + this.receiverType = receiverType; + } + + @Override + public GitHubCopilotSeatPagedSearchIterable withPageSize(int size) { + return (GitHubCopilotSeatPagedSearchIterable) super.withPageSize(size); + } + + public GitHubCopilotSeatPagedSearchIterable withPageOffset(int pageOffset) { + this.pageOffset = pageOffset; + return this; + } + + public int getTotalSeats() { + populate(); + return result.total_seats; + } + + private void populate() { + if (result == null) + iterator().hasNext(); // dispara a carga inicial + } + + @Override + public PagedIterator _iterator(int pageSize) { + final Iterator adapter = adapt( + GitHubCopilotSeatPageIterator.create(root.getClient(), receiverType, request, pageSize, pageOffset)); + return new PagedIterator<>(adapter, null); + } + + protected Iterator adapt(final Iterator> base) { + return new Iterator() { + public boolean hasNext() { + return base.hasNext(); + } + + public T[] next() { + GitHubCopilotSeatsSearchResult v = base.next(); + if (result == null) + result = v; + return v.seats; + } + }; + } +} diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchBuilder.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchBuilder.java new file mode 100644 index 0000000..d9cd9be --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchBuilder.java @@ -0,0 +1,52 @@ +package org.kohsuke.github; + +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; + +/** + * Search for GitHub Copilot seats - Enterprise plan. + * + * @author Hiroyuki Wada + * @author Nikolas Correa + */ + +public class GitHubCopilotSeatsSearchBuilder extends GHQueryBuilder { + protected final Map filter = new HashMap<>(); + + private final Class> receiverType; + + protected final GHEnterpriseExt enterprise; + + GitHubCopilotSeatsSearchBuilder(GitHub root, GHEnterpriseExt enterprise) { + super(root); + this.enterprise = enterprise; + this.receiverType = CopilotSeatSearchResult.class; + + req.withUrlPath(getApiUrl()); + req.withHeader(SCIMConstants.HEADER_ACCEPT, "application/json"); + req.withHeader(SCIMConstants.HEADER_API_VERSION, SCIMConstants.GITHUB_API_VERSION); + req.rateLimit(RateLimitTarget.SEARCH); + } + + public GitHubCopilotSeatsSearchBuilder eq(String key, String value) { + filter.put(key, value); + return this; + } + + @Override + public GitHubCopilotSeatPagedSearchIterable list() { + try { + return new GitHubCopilotSeatPagedSearchIterable<>(root, req.build(), receiverType); + } catch (MalformedURLException e) { + throw new GHException("", e); + } + } + + protected String getApiUrl() { + return String.format("/enterprises/%s/copilot/billing/seats", enterprise.login); + } + + private static class CopilotSeatSearchResult extends GitHubCopilotSeatsSearchResult { + } +} diff --git a/src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchResult.java b/src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchResult.java new file mode 100644 index 0000000..f421036 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GitHubCopilotSeatsSearchResult.java @@ -0,0 +1,11 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GitHubCopilotSeatsSearchResult { + @JsonProperty("total_seats") + public int total_seats; + + @JsonProperty("seats") + public T[] seats; +} \ No newline at end of file diff --git a/src/test/java/jp/openstandia/connector/github/CreateUserOpTest.java b/src/test/java/jp/openstandia/connector/github/CreateUserOpTest.java new file mode 100644 index 0000000..80470f6 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/CreateUserOpTest.java @@ -0,0 +1,34 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.*; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.HashSet; +import java.util.Set; + +import static jp.openstandia.connector.github.GitHubEMUUserHandler.USER_OBJECT_CLASS; + +public class CreateUserOpTest extends AbstractEMUTest { + + private Set userEntry() { + + Set attributeSet = new HashSet<>(); + attributeSet.add(AttributeBuilder.build(Name.NAME, "")); + attributeSet.add(AttributeBuilder.build("externalId", "")); + attributeSet.add(AttributeBuilder.build("displayName", "")); + attributeSet.add(AttributeBuilder.build("primaryEmail", "")); + attributeSet.add(AttributeBuilder.build("primaryRole", "User")); + attributeSet.add(AttributeBuilder.build(OperationalAttributes.ENABLE_NAME, true)); + return attributeSet; + } + + @Test() + public void shouldCreateOrReturnExistentUser() { + ConnectorFacade facade = newFacade(); + Uid uid = facade.create(USER_OBJECT_CLASS, userEntry(), null); + AssertJUnit.assertNotNull(uid); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/DeleteUsersOpTest.java b/src/test/java/jp/openstandia/connector/github/DeleteUsersOpTest.java new file mode 100644 index 0000000..8a7a61e --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/DeleteUsersOpTest.java @@ -0,0 +1,19 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.Uid; +import org.testng.annotations.Test; + +import static jp.openstandia.connector.github.GitHubEMUUserHandler.USER_OBJECT_CLASS; + +public class DeleteUsersOpTest extends AbstractEMUTest { + + String userUidToDelete = ""; + + @Test() + public void shouldDeleteUserIfExists() { + ConnectorFacade facade = newFacade(); + facade.delete(USER_OBJECT_CLASS, new Uid(userUidToDelete), null); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/EMUSchemaTest.java b/src/test/java/jp/openstandia/connector/github/EMUSchemaTest.java index 92dd9bf..793d4ac 100644 --- a/src/test/java/jp/openstandia/connector/github/EMUSchemaTest.java +++ b/src/test/java/jp/openstandia/connector/github/EMUSchemaTest.java @@ -31,12 +31,14 @@ void schema() { Schema schema = connector.schema(); assertNotNull(schema); - assertEquals(2, schema.getObjectClassInfo().size()); + assertEquals(3, schema.getObjectClassInfo().size()); Optional user = schema.getObjectClassInfo().stream().filter(o -> o.is("EMUUser")).findFirst(); Optional team = schema.getObjectClassInfo().stream().filter(o -> o.is("EMUGroup")).findFirst(); + Optional seat = schema.getObjectClassInfo().stream().filter(o -> o.is("GitHubCopilotSeat")).findFirst(); assertTrue(user.isPresent()); assertTrue(team.isPresent()); + assertTrue(seat.isPresent()); } } \ No newline at end of file diff --git a/src/test/java/jp/openstandia/connector/github/ListResultHandler.java b/src/test/java/jp/openstandia/connector/github/ListResultHandler.java new file mode 100644 index 0000000..e1653f8 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/ListResultHandler.java @@ -0,0 +1,19 @@ +package jp.openstandia.connector.github; + +import org.identityconnectors.framework.common.objects.ConnectorObject; +import org.identityconnectors.framework.common.objects.ResultsHandler; + +import java.util.ArrayList; +import java.util.List; + +public class ListResultHandler implements ResultsHandler { + + private final List objects = new ArrayList<>(); + @Override + public boolean handle(ConnectorObject connectorObject) { + objects.add(connectorObject); + return true; + } + + public List getObjects() { return objects; } +} diff --git a/src/test/java/jp/openstandia/connector/github/SearchGroupsOpTest.java b/src/test/java/jp/openstandia/connector/github/SearchGroupsOpTest.java new file mode 100644 index 0000000..6ba39c1 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/SearchGroupsOpTest.java @@ -0,0 +1,54 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.*; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.List; + +import static jp.openstandia.connector.github.GitHubEMUGroupHandler.GROUP_OBJECT_CLASS; + +public class SearchGroupsOpTest extends AbstractEMUTest { + + String groupUid = ""; + String groupName = ""; + + @Test() + public void shouldReturnAllGroups() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + facade.search(GROUP_OBJECT_CLASS, null, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertTrue("Size: " + objects.size(), objects.size() > 1); + } + + @Test() + public void shouldReturnGroupByUid() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + Attribute attribute = AttributeBuilder.build(Uid.NAME, groupUid); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(GROUP_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } + + @Test() + public void shouldReturnGroupByName() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + Attribute attribute = AttributeBuilder.build(Name.NAME, groupName); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(GROUP_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/SearchSeatsOpTest.java b/src/test/java/jp/openstandia/connector/github/SearchSeatsOpTest.java new file mode 100644 index 0000000..71c6083 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/SearchSeatsOpTest.java @@ -0,0 +1,54 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.*; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.List; + +import static jp.openstandia.connector.github.GitHubCopilotSeatHandler.SEAT_OBJECT_CLASS; + +public class SearchSeatsOpTest extends AbstractEMUTest { + + String seatUid = ""; + String seatName = ""; + + @Test() + public void shouldReturnAllSeats() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + facade.search(SEAT_OBJECT_CLASS, null, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertTrue("Size: " + objects.size(), objects.size() > 1); + } + + @Test() + public void shouldReturnSeatByUid() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + Attribute attribute = AttributeBuilder.build(Uid.NAME, seatUid); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(SEAT_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } + + @Test() + public void shouldReturnSeatByName() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + Attribute attribute = AttributeBuilder.build(Name.NAME, seatName); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(SEAT_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/SearchUsersOpTest.java b/src/test/java/jp/openstandia/connector/github/SearchUsersOpTest.java new file mode 100644 index 0000000..d8afc4c --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/SearchUsersOpTest.java @@ -0,0 +1,54 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.*; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.List; + +import static jp.openstandia.connector.github.GitHubEMUUserHandler.USER_OBJECT_CLASS; + +public class SearchUsersOpTest extends AbstractEMUTest { + + String userUid = ""; + String userName = ""; + + @Test() + public void shouldReturnAllUsers() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + facade.search(USER_OBJECT_CLASS, null, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertTrue("Size: " + objects.size(), objects.size() > 1); + } + + @Test() + public void shouldReturnUserByUid() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + Attribute attribute = AttributeBuilder.build(Uid.NAME, userUid); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(USER_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } + + @Test() + public void shouldReturnUserByUsername() { + ConnectorFacade facade = newFacade(); + ListResultHandler handler = new ListResultHandler(); + + Attribute attribute = AttributeBuilder.build(Name.NAME, userName); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(USER_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/TestOpTest.java b/src/test/java/jp/openstandia/connector/github/TestOpTest.java new file mode 100644 index 0000000..4b7d7f9 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/TestOpTest.java @@ -0,0 +1,14 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.testng.annotations.Test; + +public class TestOpTest extends AbstractEMUTest { + + @Test() + public void shouldInitializeConnection() { + ConnectorFacade facade = newFacade(); + facade.test(); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/UpdateGroupsOpTest.java b/src/test/java/jp/openstandia/connector/github/UpdateGroupsOpTest.java new file mode 100644 index 0000000..6257c06 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/UpdateGroupsOpTest.java @@ -0,0 +1,80 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.*; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static jp.openstandia.connector.github.GitHubEMUGroupHandler.GROUP_OBJECT_CLASS; + +public class UpdateGroupsOpTest extends AbstractEMUTest { + + String userUid = ""; + String groupUidToUpdate = ""; + + @Test() + public void shouldAddUserToGroup() { + // Create an AttributeDelta to add user uid + Set attributes = new HashSet<>(); + AttributeDeltaBuilder deltaBuilder = new AttributeDeltaBuilder(); + deltaBuilder.setName("members.User.value"); + deltaBuilder.addValueToAdd(userUid); + attributes.add(deltaBuilder.build()); + + // Call updateDelta to update the group + ConnectorFacade facade = newFacade(); + facade.updateDelta(GROUP_OBJECT_CLASS, new Uid(groupUidToUpdate), attributes, null); + + // Retrieve and verify the updated object + ListResultHandler handler = new ListResultHandler(); + Attribute attribute = AttributeBuilder.build(Uid.NAME, groupUidToUpdate); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(GROUP_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + + ConnectorObject object = objects.get(0); + Attribute memberOfAttr = object.getAttributeByName("members.User.value"); + AssertJUnit.assertNotNull(memberOfAttr); + + List grupos = memberOfAttr.getValue(); + AssertJUnit.assertTrue(grupos.contains(userUid)); + } + + @Test() + public void shouldRemoveUserFromGroup() { + // Create an AttributeDelta to add user uid + Set attributes = new HashSet<>(); + AttributeDeltaBuilder deltaBuilder = new AttributeDeltaBuilder(); + deltaBuilder.setName("members.User.value"); + deltaBuilder.addValueToRemove(userUid); + attributes.add(deltaBuilder.build()); + + // Call updateDelta to update the group + ConnectorFacade facade = newFacade(); + facade.updateDelta(GROUP_OBJECT_CLASS, new Uid(groupUidToUpdate), attributes, null); + + // Retrieve and verify the updated object + ListResultHandler handler = new ListResultHandler(); + Attribute attribute = AttributeBuilder.build(Uid.NAME, groupUidToUpdate); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(GROUP_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + + ConnectorObject object = objects.get(0); + Attribute memberOfAttr = object.getAttributeByName("members.User.value"); + AssertJUnit.assertNotNull(memberOfAttr); + + List grupos = memberOfAttr.getValue(); + AssertJUnit.assertFalse(grupos.contains(userUid)); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/UpdateUsersOpTest.java b/src/test/java/jp/openstandia/connector/github/UpdateUsersOpTest.java new file mode 100644 index 0000000..e9dc8d0 --- /dev/null +++ b/src/test/java/jp/openstandia/connector/github/UpdateUsersOpTest.java @@ -0,0 +1,92 @@ +package jp.openstandia.connector.github; + +import jp.openstandia.connector.github.testutil.AbstractEMUTest; +import org.identityconnectors.framework.api.ConnectorFacade; +import org.identityconnectors.framework.common.objects.*; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static jp.openstandia.connector.github.GitHubEMUUserHandler.USER_OBJECT_CLASS; + +public class UpdateUsersOpTest extends AbstractEMUTest { + + String userUid = ""; + String attrToUpdate = ""; + String attrNewValue = ""; + + @Test() + public void shouldActivateUser() { + Set attributes = new HashSet<>(); + + AttributeDeltaBuilder deltaBuilder = new AttributeDeltaBuilder(); + deltaBuilder.setName(OperationalAttributes.ENABLE_NAME); + deltaBuilder.addValueToReplace(true); + attributes.add(deltaBuilder.build()); + + ConnectorFacade facade = newFacade(); + facade.updateDelta(USER_OBJECT_CLASS, new Uid(userUid), attributes, null); + + ListResultHandler handler = new ListResultHandler(); + Attribute attribute = AttributeBuilder.build(Uid.NAME, userUid); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(USER_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } + + @Test() + public void shouldInactivateUser() { + Set attributes = new HashSet<>(); + + AttributeDeltaBuilder deltaBuilder = new AttributeDeltaBuilder(); + deltaBuilder.setName(OperationalAttributes.ENABLE_NAME); + deltaBuilder.addValueToReplace(false); + attributes.add(deltaBuilder.build()); + + ConnectorFacade facade = newFacade(); + facade.updateDelta(USER_OBJECT_CLASS, new Uid(userUid), attributes, null); + + ListResultHandler handler = new ListResultHandler(); + Attribute attribute = AttributeBuilder.build(Uid.NAME, userUid); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(USER_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + } + + @Test() + public void shouldUpdateAttrValue() { + ConnectorFacade facade = newFacade(); + + // Create an AttributeDelta to update the status of uid + Set attributes = new HashSet<>(); + AttributeDeltaBuilder deltaBuilder = new AttributeDeltaBuilder(); + deltaBuilder.setName(attrToUpdate); + deltaBuilder.addValueToReplace(attrNewValue); + attributes.add(deltaBuilder.build()); + + // Call updateDelta to update the status + facade.updateDelta(USER_OBJECT_CLASS, new Uid(userUid), attributes, null); + + // Retrieve and verify the updated object + ListResultHandler handler = new ListResultHandler(); + Attribute attribute = AttributeBuilder.build(Uid.NAME, userUid); + EqualsFilter filter = new EqualsFilter(attribute); + + facade.search(USER_OBJECT_CLASS, filter, handler, null); + List objects = handler.getObjects(); + AssertJUnit.assertEquals(1, objects.size()); + + ConnectorObject object = objects.get(0); + Attribute nameAttr = object.getAttributeByName(attrToUpdate); + AssertJUnit.assertNotNull(nameAttr); + AssertJUnit.assertEquals(attrNewValue, nameAttr.getValue().get(0)); + } +} diff --git a/src/test/java/jp/openstandia/connector/github/testutil/AbstractEMUTest.java b/src/test/java/jp/openstandia/connector/github/testutil/AbstractEMUTest.java index d41342c..5ebf906 100644 --- a/src/test/java/jp/openstandia/connector/github/testutil/AbstractEMUTest.java +++ b/src/test/java/jp/openstandia/connector/github/testutil/AbstractEMUTest.java @@ -16,11 +16,14 @@ package jp.openstandia.connector.github.testutil; import jp.openstandia.connector.github.GitHubEMUConfiguration; +import jp.openstandia.connector.github.GitHubEMUConnector; +import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.framework.api.APIConfiguration; import org.identityconnectors.framework.api.ConnectorFacade; import org.identityconnectors.framework.api.ConnectorFacadeFactory; import org.identityconnectors.test.common.TestHelpers; import org.junit.jupiter.api.BeforeEach; +import org.testng.annotations.Test; public abstract class AbstractEMUTest { @@ -29,13 +32,15 @@ public abstract class AbstractEMUTest { protected GitHubEMUConfiguration newConfiguration() { GitHubEMUConfiguration conf = new GitHubEMUConfiguration(); - conf.setEnterpriseSlug("localEnt"); + conf.setEnterpriseSlug(""); + conf.setAccessToken(new GuardedString("".toCharArray())); + conf.setEndpointURL(""); return conf; } protected ConnectorFacade newFacade() { ConnectorFacadeFactory factory = ConnectorFacadeFactory.getInstance(); - APIConfiguration impl = TestHelpers.createTestConfiguration(LocalGitHubEMUConnector.class, newConfiguration()); + APIConfiguration impl = TestHelpers.createTestConfiguration(GitHubEMUConnector.class, newConfiguration()); impl.getResultsHandlerConfiguration().setEnableAttributesToGetSearchResultsHandler(false); impl.getResultsHandlerConfiguration().setEnableNormalizingResultsHandler(false); impl.getResultsHandlerConfiguration().setEnableFilteredResultsHandler(false);