GHTeam.java
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.github.internal.EnumUtils;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import javax.annotation.Nonnull;
import static org.kohsuke.github.GitHubRequest.transformEnum;
// TODO: Auto-generated Javadoc
/**
* A team in GitHub organization.
*
* @author Kohsuke Kawaguchi
*/
public class GHTeam extends GHObject implements Refreshable {
/**
* Create default GHTeam instance
*/
public GHTeam() {
}
/**
* Path for external group-related operations
*/
private static final String EXTERNAL_GROUPS = "/external-groups";
private String html_url;
private String name;
private String permission;
private String slug;
private String description;
private String privacy;
private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together
/**
* The Enum Privacy.
*/
public enum Privacy {
/** The secret. */
SECRET,
/** The closed. */
// only visible to organization owners and members of this team.
CLOSED, // visible to all members of this organization.
/** Unknown privacy value */
UNKNOWN
}
/**
* Member's role in a team.
*/
public enum Role {
/** A normal member of the team. */
MEMBER,
/**
* Able to add/remove other team members, promote other team members to team maintainer, and edit the team's
* name and description.
*/
MAINTAINER
}
/**
* Wrap up.
*
* @param owner
* the owner
* @return the GH team
*/
GHTeam wrapUp(GHOrganization owner) {
this.organization = owner;
return this;
}
/**
* Wrap up.
*
* @param root
* the root
* @return the GH team
*/
GHTeam wrapUp(GitHub root) { // auto-wrapUp when organization is known from GET /user/teams
return wrapUp(organization);
}
/**
* Gets name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Gets permission.
*
* @return the permission
*/
public String getPermission() {
return permission;
}
/**
* Gets slug.
*
* @return the slug
*/
public String getSlug() {
return slug;
}
/**
* Gets description.
*
* @return the description
*/
public String getDescription() {
return description;
}
/**
* Gets the privacy state.
*
* @return the privacy state.
*/
public Privacy getPrivacy() {
return EnumUtils.getNullableEnumOrDefault(Privacy.class, privacy, Privacy.UNKNOWN);
}
/**
* Sets description.
*
* @param description
* the description
* @throws IOException
* the io exception
*/
public void setDescription(String description) throws IOException {
root().createRequest().method("PATCH").with("description", description).withUrlPath(api("")).send();
}
/**
* Updates the team's privacy setting.
*
* @param privacy
* the privacy
* @throws IOException
* the io exception
*/
public void setPrivacy(Privacy privacy) throws IOException {
root().createRequest().method("PATCH").with("privacy", privacy).withUrlPath(api("")).send();
}
/**
* Retrieves the discussions.
*
* @return the paged iterable
* @throws IOException
* the io exception
*/
@Nonnull
public PagedIterable<GHDiscussion> listDiscussions() throws IOException {
return GHDiscussion.readAll(this);
}
/**
* List members with specified role paged iterable.
*
* @param role
* the role
* @return the paged iterable
* @throws IOException
* the io exception
*/
public PagedIterable<GHUser> listMembers(String role) throws IOException {
return root().createRequest().withUrlPath(api("/members")).with("role", role).toIterable(GHUser[].class, null);
}
/**
* List members with specified role paged iterable.
*
* @param role
* the role
* @return the paged iterable
* @throws IOException
* the io exception
*/
public PagedIterable<GHUser> listMembers(Role role) throws IOException {
return listMembers(transformEnum(role));
}
/**
* Gets a single discussion by ID.
*
* @param discussionNumber
* id of the discussion that we want to query for
* @return the discussion
* @throws IOException
* the io exception
* @see <a href= "https://developer.github.com/v3/teams/discussions/#get-a-discussion">documentation</a>
*/
@Nonnull
public GHDiscussion getDiscussion(long discussionNumber) throws IOException {
return GHDiscussion.read(this, discussionNumber);
}
/**
* Retrieves the current members.
*
* @return the paged iterable
* @throws IOException
* the io exception
*/
public PagedIterable<GHUser> listMembers() throws IOException {
return listMembers("all");
}
/**
* Retrieves the teams that are children of this team.
*
* @return the paged iterable
* @throws IOException
* the io exception
*/
public PagedIterable<GHTeam> listChildTeams() throws IOException {
return root().createRequest()
.withUrlPath(api("/teams"))
.toIterable(GHTeam[].class, item -> item.wrapUp(this.organization));
}
/**
* Gets members.
*
* @return the members
* @throws IOException
* the io exception
*/
public Set<GHUser> getMembers() throws IOException {
return listMembers().toSet();
}
/**
* Checks if this team has the specified user as a member.
*
* @param user
* the user
* @return the boolean
*/
public boolean hasMember(GHUser user) {
try {
root().createRequest().withUrlPath(api("/memberships/" + user.getLogin())).send();
return true;
} catch (@SuppressWarnings("unused") IOException ignore) {
return false;
}
}
/**
* Gets repositories.
*
* @return the repositories
* @throws IOException
* the io exception
*/
public Map<String, GHRepository> getRepositories() throws IOException {
Map<String, GHRepository> m = new TreeMap<>();
for (GHRepository r : listRepositories()) {
m.put(r.getName(), r);
}
return m;
}
/**
* List repositories paged iterable.
*
* @return the paged iterable
*/
public PagedIterable<GHRepository> listRepositories() {
return root().createRequest().withUrlPath(api("/repos")).toIterable(GHRepository[].class, null);
}
/**
* Adds a member to the team.
* <p>
* The user will be invited to the organization if required.
*
* @param u
* the u
* @throws IOException
* the io exception
* @since 1.59
*/
public void add(GHUser u) throws IOException {
root().createRequest().method("PUT").withUrlPath(api("/memberships/" + u.getLogin())).send();
}
/**
* Adds a member to the team
* <p>
* The user will be invited to the organization if required.
*
* @param user
* github user
* @param role
* role for the new member
* @throws IOException
* the io exception
*/
public void add(GHUser user, Role role) throws IOException {
root().createRequest()
.method("PUT")
.with("role", role)
.withUrlPath(api("/memberships/" + user.getLogin()))
.send();
}
/**
* Removes a member to the team.
*
* @param u
* the u
* @throws IOException
* the io exception
*/
public void remove(GHUser u) throws IOException {
root().createRequest().method("DELETE").withUrlPath(api("/memberships/" + u.getLogin())).send();
}
/**
* Add.
*
* @param r
* the r
* @throws IOException
* the io exception
*/
public void add(GHRepository r) throws IOException {
add(r, (GHOrganization.RepositoryRole) null);
}
/**
* Add.
*
* @param r
* the r
* @param permission
* the permission
* @throws IOException
* the io exception
*/
public void add(GHRepository r, GHOrganization.RepositoryRole permission) throws IOException {
root().createRequest()
.method("PUT")
.with("permission",
Optional.ofNullable(permission).map(GHOrganization.RepositoryRole::toString).orElse(null))
.withUrlPath(api("/repos/" + r.getOwnerName() + '/' + r.getName()))
.send();
}
/**
* Remove.
*
* @param r
* the r
* @throws IOException
* the io exception
*/
public void remove(GHRepository r) throws IOException {
root().createRequest()
.method("DELETE")
.withUrlPath(api("/repos/" + r.getOwnerName() + '/' + r.getName()))
.send();
}
/**
* Deletes this team.
*
* @throws IOException
* the io exception
*/
public void delete() throws IOException {
root().createRequest().method("DELETE").withUrlPath(api("")).send();
}
private String api(String tail) {
if (organization == null) {
// Teams returned from pull requests to do not have an organization. Attempt to use url.
final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!");
return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/") + tail;
}
return "/organizations/" + organization.getId() + "/team/" + getId() + tail;
}
private String publicApi(String tail) throws IOException {
return "/orgs/" + getOrganization().login + "/teams/" + getSlug() + tail;
}
/**
* Begins the creation of a new instance.
*
* Consumer must call {@link GHDiscussion.Creator#done()} to commit changes.
*
* @param title
* title of the discussion to be created
* @return a {@link GHDiscussion.Creator}
* @throws IOException
* the io exception
*/
public GHDiscussion.Creator createDiscussion(String title) throws IOException {
return GHDiscussion.create(this).title(title);
}
/**
* Get the external groups connected to the team
*
* @return the external groups
* @throws IOException
* the io exception
* @see <a href=
* "https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups?apiVersion=2022-11-28#list-a-connection-between-an-external-group-and-a-team">documentation</a>
*/
public List<GHExternalGroup> getExternalGroups() throws IOException {
try {
return Collections.unmodifiableList(Arrays.asList(root().createRequest()
.method("GET")
.withUrlPath(publicApi(EXTERNAL_GROUPS))
.fetch(GHExternalGroupPage.class)
.getGroups()));
} catch (final HttpException e) {
throw EnterpriseManagedSupport.forOrganization(getOrganization())
.filterException(e, "Could not retrieve team external groups")
.orElse(e);
}
}
/**
* Connect an external group to the team
*
* @param group
* the group to connect
* @return the external group
* @throws IOException
* in case of failure
* @see <a href=
* "https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups?apiVersion=2022-11-28#update-the-connection-between-an-external-group-and-a-team">documentation</a>
*/
public GHExternalGroup connectToExternalGroup(final GHExternalGroup group) throws IOException {
return connectToExternalGroup(group.getId());
}
/**
* Connect an external group to the team
*
* @param group_id
* the identifier of the group to connect
* @return the external group
* @throws IOException
* in case of failure
* @see <a href=
* "https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups?apiVersion=2022-11-28#update-the-connection-between-an-external-group-and-a-team">documentation</a>
*/
public GHExternalGroup connectToExternalGroup(final long group_id) throws IOException {
try {
return root().createRequest()
.method("PATCH")
.with("group_id", group_id)
.withUrlPath(publicApi(EXTERNAL_GROUPS))
.fetch(GHExternalGroup.class)
.wrapUp(getOrganization());
} catch (final HttpException e) {
throw EnterpriseManagedSupport.forOrganization(getOrganization())
.filterException(e, "Could not connect team to external group")
.orElse(e);
}
}
/**
* Remove the connection of the team to an external group
*
* @throws IOException
* in case of failure
* @see <a href=
* "https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups?apiVersion=2022-11-28#remove-the-connection-between-an-external-group-and-a-team">documentation</a>
*/
public void deleteExternalGroupConnection() throws IOException {
root().createRequest().method("DELETE").withUrlPath(publicApi(EXTERNAL_GROUPS)).send();
}
/**
* Gets organization.
*
* @return the organization
* @throws IOException
* the io exception
*/
@SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior")
public GHOrganization getOrganization() throws IOException {
refresh(organization);
return organization;
}
/**
* Refresh.
*
* @throws IOException
* Signals that an I/O exception has occurred.
*/
@Override
public void refresh() throws IOException {
root().createRequest().withUrlPath(api("")).fetchInto(this).wrapUp(root());
}
/**
* Gets the html url.
*
* @return the html url
*/
public URL getHtmlUrl() {
return GitHubClient.parseURL(html_url);
}
/**
* Equals.
*
* @param o
* the o
* @return true, if successful
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GHTeam ghTeam = (GHTeam) o;
return Objects.equals(name, ghTeam.name) && Objects.equals(getUrl(), ghTeam.getUrl())
&& Objects.equals(permission, ghTeam.permission) && Objects.equals(slug, ghTeam.slug)
&& Objects.equals(description, ghTeam.description) && Objects.equals(privacy, ghTeam.privacy);
}
/**
* Hash code.
*
* @return the int
*/
@Override
public int hashCode() {
return Objects.hash(name, getUrl(), permission, slug, description, privacy);
}
}