package org.gitlab4j.api; import java.io.File; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; import javax.ws.rs.core.Form; import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; import org.gitlab4j.api.GitLabApi.ApiVersion; import org.gitlab4j.api.models.CustomAttribute; import org.gitlab4j.api.models.Email; import org.gitlab4j.api.models.ImpersonationToken; import org.gitlab4j.api.models.ImpersonationToken.Scope; import org.gitlab4j.api.utils.EmailChecker; import org.gitlab4j.api.models.SshKey; import org.gitlab4j.api.models.User; /** * This class provides an entry point to all the GitLab API users calls. * * @see <a href="https://docs.gitlab.com/ce/api/users.html">Users API at GitLab</a> */ public class UserApi extends AbstractApi { private boolean customAttributesEnabled = false; public UserApi(GitLabApi gitLabApi) { super(gitLabApi); } /** * Enables custom attributes to be returned when fetching User instances. */ public void enableCustomAttributes() { customAttributesEnabled = true; } /** * Disables custom attributes to be returned when fetching User instances. */ public void disableCustomAttributes() { customAttributesEnabled = false; } /** * <p>Get a list of users.</p> * * <strong>WARNING:</strong> Do not use this method to fetch users from https://gitlab.com, * gitlab.com has many 1,000,000's of users and it will a long time to fetch all of them. * Instead use {@link #getUsers(int itemsPerPage)} which will return a Pager of Group instances. * * <pre><code>GitLab Endpoint: GET /users</code></pre> * * @return a list of Users * @throws GitLabApiException if any exception occurs */ public List<User> getUsers() throws GitLabApiException { String url = this.gitLabApi.getGitLabServerUrl(); if (url.startsWith("https://gitlab.com")) { GitLabApi.getLogger().warning("Fetching all users from " + url + " may take many minutes to complete, use Pager<User> getUsers(int) instead."); } return (getUsers(getDefaultPerPage()).all()); } /** * Get a list of users using the specified page and per page settings. * * <pre><code>GitLab Endpoint: GET /users</code></pre> * * @param page the page to get * @param perPage the number of users per page * @return the list of Users in the specified range * @throws GitLabApiException if any exception occurs */ public List<User> getUsers(int page, int perPage) throws GitLabApiException { Response response = get(Response.Status.OK, getPageQueryParams(page, perPage, customAttributesEnabled), "users"); return (response.readEntity(new GenericType<List<User>>() {})); } /** * Get a Pager of users. * * <pre><code>GitLab Endpoint: GET /users</code></pre> * * @param itemsPerPage the number of User instances that will be fetched per page * @return a Pager of User * @throws GitLabApiException if any exception occurs */ public Pager<User> getUsers(int itemsPerPage) throws GitLabApiException { return (new Pager<User>(this, User.class, itemsPerPage, createGitLabApiForm().asMap(), "users")); } /** * Get a Stream of users. * * <pre><code>GitLab Endpoint: GET /users</code></pre> * * @return a Stream of Users. * @throws GitLabApiException if any exception occurs */ public Stream<User> getUsersStream() throws GitLabApiException { return (getUsers(getDefaultPerPage()).stream()); } /** * Get a list of active users * * <pre><code>GitLab Endpoint: GET /users?active=true</code></pre> * * @return a list of active Users * @throws GitLabApiException if any exception occurs */ public List<User> getActiveUsers() throws GitLabApiException { return (getActiveUsers(getDefaultPerPage()).all()); } /** * Get a list of active users using the specified page and per page settings. * * <pre><code>GitLab Endpoint: GET /users?active=true</code></pre> * * @param page the page to get * @param perPage the number of users per page * @return the list of active Users in the specified range * @throws GitLabApiException if any exception occurs */ public List<User> getActiveUsers(int page, int perPage) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm() .withParam("active", true) .withParam(PAGE_PARAM, page) .withParam(PER_PAGE_PARAM, perPage); Response response = get(Response.Status.OK, formData.asMap(), "users"); return (response.readEntity(new GenericType<List<User>>() {})); } /** * Get a Pager of active users. * * <pre><code>GitLab Endpoint: GET /users?active=true</code></pre> * * @param itemsPerPage the number of active User instances that will be fetched per page * @return a Pager of active User * @throws GitLabApiException if any exception occurs */ public Pager<User> getActiveUsers(int itemsPerPage) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm().withParam("active", true); return (new Pager<User>(this, User.class, itemsPerPage, formData.asMap(), "users")); } /** * Get a Stream of active users * * <pre><code>GitLab Endpoint: GET /users?active=true</code></pre> * * @return a Stream of active Users * @throws GitLabApiException if any exception occurs */ public Stream<User> getActiveUsersStream() throws GitLabApiException { return (getActiveUsers(getDefaultPerPage()).stream()); } /** * Blocks the specified user. Available only for admin. * * <pre><code>GitLab Endpoint: POST /users/:id/block</code></pre> * * @param userId the ID of the user to block * @throws GitLabApiException if any exception occurs */ public void blockUser(Integer userId) throws GitLabApiException { if (userId == null) { throw new RuntimeException("userId cannot be null"); } if (isApiVersion(ApiVersion.V3)) { put(Response.Status.CREATED, null, "users", userId, "block"); } else { post(Response.Status.CREATED, (Form) null, "users", userId, "block"); } } /** * Unblocks the specified user. Available only for admin. * * <pre><code>GitLab Endpoint: POST /users/:id/unblock</code></pre> * * @param userId the ID of the user to unblock * @throws GitLabApiException if any exception occurs */ public void unblockUser(Integer userId) throws GitLabApiException { if (userId == null) { throw new RuntimeException("userId cannot be null"); } if (isApiVersion(ApiVersion.V3)) { put(Response.Status.CREATED, null, "users", userId, "unblock"); } else { post(Response.Status.CREATED, (Form) null, "users", userId, "unblock"); } } /** * Get a list of blocked users. * * <pre><code>GitLab Endpoint: GET /users?blocked=true</code></pre> * * @return a list of blocked Users * @throws GitLabApiException if any exception occurs */ public List<User> getBlockedUsers() throws GitLabApiException { return (getBlockedUsers(getDefaultPerPage()).all()); } /** * Get a list of blocked users using the specified page and per page settings. * * <pre><code>GitLab Endpoint: GET /users?blocked=true</code></pre> * * @param page the page to get * @param perPage the number of users per page * @return the list of blocked Users in the specified range * @throws GitLabApiException if any exception occurs */ public List<User> getblockedUsers(int page, int perPage) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm() .withParam("blocked", true) .withParam(PAGE_PARAM, page) .withParam(PER_PAGE_PARAM, perPage); Response response = get(Response.Status.OK, formData.asMap(), "users"); return (response.readEntity(new GenericType<List<User>>() {})); } /** * Get a Pager of blocked users. * * <pre><code>GitLab Endpoint: GET /users?blocked=true</code></pre> * * @param itemsPerPage the number of blocked User instances that will be fetched per page * @return a Pager of blocked User * @throws GitLabApiException if any exception occurs */ public Pager<User> getBlockedUsers(int itemsPerPage) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm().withParam("blocked", true); return (new Pager<User>(this, User.class, itemsPerPage, formData.asMap(), "users")); } /** * Get a Stream of blocked users. * * <pre><code>GitLab Endpoint: GET /users?blocked=true</code></pre> * * @return a Stream of blocked Users * @throws GitLabApiException if any exception occurs */ public Stream<User> getBlockedUsersStream() throws GitLabApiException { return (getBlockedUsers(getDefaultPerPage()).stream()); } /** * Get a single user. * * <pre><code>GitLab Endpoint: GET /users/:id</code></pre> * * @param userId the ID of the user to get * @return the User instance for the specified user ID * @throws GitLabApiException if any exception occurs */ public User getUser(Integer userId) throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm().withParam("with_custom_attributes", customAttributesEnabled); Response response = get(Response.Status.OK, formData.asMap(), "users", userId); return (response.readEntity(User.class)); } /** * Get a single user as an Optional instance. * * <pre><code>GitLab Endpoint: GET /users/:id</code></pre> * * @param userId the ID of the user to get * @return the User for the specified user ID as an Optional instance */ public Optional<User> getOptionalUser(Integer userId) { try { return (Optional.ofNullable(getUser(userId))); } catch (GitLabApiException glae) { return (GitLabApi.createOptionalFromException(glae)); } } /** * Lookup a user by username. Returns null if not found. * * <p>NOTE: This is for admin users only.</p> * * <pre><code>GitLab Endpoint: GET /users?username=:username</code></pre> * * @param username the username of the user to get * @return the User instance for the specified username, or null if not found * @throws GitLabApiException if any exception occurs */ public User getUser(String username) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm() .withParam("username", username, true) .withParam(PAGE_PARAM, 1) .withParam(PER_PAGE_PARAM, 1); Response response = get(Response.Status.OK, formData.asMap(), "users"); List<User> users = response.readEntity(new GenericType<List<User>>() {}); return (users.isEmpty() ? null : users.get(0)); } /** * Lookup a user by username and return an Optional instance. * * <p>NOTE: This is for admin users only.</p> * * <pre><code>GitLab Endpoint: GET /users?username=:username</code></pre> * * @param username the username of the user to get * @return the User for the specified username as an Optional instance */ public Optional<User> getOptionalUser(String username) { try { return (Optional.ofNullable(getUser(username))); } catch (GitLabApiException glae) { return (GitLabApi.createOptionalFromException(glae)); } } /** * Lookup a user by email address. Returns null if not found. * * <pre><code>GitLab Endpoint: GET /users?search=:email_or_username</code></pre> * * @param email the email of the user to get * @return the User instance for the specified email, or null if not found * @throws GitLabApiException if any exception occurs * @throws IllegalArgumentException if email is not valid */ public User getUserByEmail(String email) throws GitLabApiException { if (!EmailChecker.isValidEmail(email)) { throw new IllegalArgumentException("email is not valid"); } List<User> users = findUsers(email, 1, 1); return (users.isEmpty() ? null : users.get(0)); } /** * Lookup a user by email address and returns an Optional with the User instance as the value. * * <pre><code>GitLab Endpoint: GET /users?search=:email_or_username</code></pre> * * @param email the email of the user to get * @return the User for the specified email as an Optional instance */ public Optional<User> getOptionalUserByEmail(String email) { try { return (Optional.ofNullable(getUserByEmail(email))); } catch (GitLabApiException glae) { return (GitLabApi.createOptionalFromException(glae)); } } /** * Lookup a user by external UID. Returns null if not found. * * <p>NOTE: This is for admin users only.</p> * * <pre><code>GitLab Endpoint: GET /users?extern_uid=:externalUid&provider=:provider</code></pre> * * @param provider the provider of the external uid * @param externalUid the external UID of the user * @return the User instance for the specified external UID, or null if not found * @throws GitLabApiException if any exception occurs */ public User getUserByExternalUid(String provider, String externalUid) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm() .withParam("provider", provider, true) .withParam("extern_uid", externalUid, true) .withParam(PAGE_PARAM, 1) .withParam(PER_PAGE_PARAM, 1); Response response = get(Response.Status.OK, formData.asMap(), "users"); List<User> users = response.readEntity(new GenericType<List<User>>() {}); return (users.isEmpty() ? null : users.get(0)); } /** * Lookup a user by external UID and return an Optional instance. * * <p>NOTE: This is for admin users only.</p> * * <pre><code>GitLab Endpoint: GET /users?extern_uid=:externUid&provider=:provider</code></pre> * * @param provider the provider of the external uid * @param externalUid the external UID of the user * @return the User for the specified external UID as an Optional instance */ public Optional<User> getOptionalUserByExternalUid(String provider, String externalUid) { try { return (Optional.ofNullable(getUserByExternalUid(provider, externalUid))); } catch (GitLabApiException glae) { return (GitLabApi.createOptionalFromException(glae)); } } /** * Search users by Email or username * * <pre><code>GitLab Endpoint: GET /users?search=:email_or_username</code></pre> * * @param emailOrUsername the email or username to search for * @return the User List with the email or username like emailOrUsername * @throws GitLabApiException if any exception occurs */ public List<User> findUsers(String emailOrUsername) throws GitLabApiException { return (findUsers(emailOrUsername, getDefaultPerPage()).all()); } /** * Search users by Email or username in the specified page range. * * <pre><code>GitLab Endpoint: GET /users?search=:email_or_username</code></pre> * * @param emailOrUsername the email or username to search for * @param page the page to get * @param perPage the number of users per page * @return the User List with the email or username like emailOrUsername in the specified page range * @throws GitLabApiException if any exception occurs */ public List<User> findUsers(String emailOrUsername, int page, int perPage) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm() .withParam("search", emailOrUsername, true) .withParam(PAGE_PARAM, page) .withParam(PER_PAGE_PARAM, perPage); Response response = get(Response.Status.OK, formData.asMap(), "users"); return (response.readEntity(new GenericType<List<User>>() { })); } /** * Search users by Email or username and return a Pager * * <pre><code>GitLab Endpoint: GET /users?search=:email_or_username</code></pre> * * @param emailOrUsername the email or username to search for * @param itemsPerPage the number of Project instances that will be fetched per page * @return the User Pager with the email or username like emailOrUsername * @throws GitLabApiException if any exception occurs */ public Pager<User> findUsers(String emailOrUsername, int itemsPerPage) throws GitLabApiException { GitLabApiForm formData = createGitLabApiForm().withParam("search", emailOrUsername, true); return (new Pager<User>(this, User.class, itemsPerPage, formData.asMap(), "users")); } /** * Search users by Email or username. * * <pre><code>GitLab Endpoint: GET /users?search=:email_or_username</code></pre> * * @param emailOrUsername the email or username to search for * @return a Stream of User instances with the email or username like emailOrUsername * @throws GitLabApiException if any exception occurs */ public Stream<User> findUsersStream(String emailOrUsername) throws GitLabApiException { return (findUsers(emailOrUsername, getDefaultPerPage()).stream()); } /** * <p>Creates a new user. Note only administrators can create new users. * Either password or reset_password should be specified (reset_password takes priority).</p> * * <p>If both the User object's projectsLimit and the parameter projectsLimit is specified * the parameter will take precedence.</p> * * <pre><code>GitLab Endpoint: POST /users</code></pre> * * <p>The following properties of the provided User instance can be set during creation:<pre><code> email (required) - Email * username (required) - Username * name (required) - Name * skype (optional) - Skype ID * linkedin (optional) - LinkedIn * twitter (optional) - Twitter account * websiteUrl (optional) - Website URL * organization (optional) - Organization name * projectsLimit (optional) - Number of projects user can create * externUid (optional) - External UID * provider (optional) - External provider name * bio (optional) - User's biography * location (optional) - User's location * admin (optional) - User is admin - true or false (default) * canCreateGroup (optional) - User can create groups - true or false * skipConfirmation (optional) - Skip confirmation - true or false (default) * external (optional) - Flags the user as external - true or false(default) * sharedRunnersMinutesLimit (optional) - Pipeline minutes quota for this user * </code></pre> * * @param user the User instance with the user info to create * @param password the password for the new user * @param projectsLimit the maximum number of project * @return created User instance * @throws GitLabApiException if any exception occurs * @deprecated Will be removed in version 5.0, replaced by {@link #createUser(User, CharSequence, boolean)} */ public User createUser(User user, CharSequence password, Integer projectsLimit) throws GitLabApiException { Form formData = userToForm(user, projectsLimit, password, null, true); Response response = post(Response.Status.CREATED, formData, "users"); return (response.readEntity(User.class)); } /** * <p>Creates a new user. Note only administrators can create new users. * Either password or resetPassword should be specified (resetPassword takes priority).</p> * * <pre><code>GitLab Endpoint: POST /users</code></pre> * * <p>The following properties of the provided User instance can be set during creation:<pre><code> email (required) - Email * username (required) - Username * name (required) - Name * skype (optional) - Skype ID * linkedin (optional) - LinkedIn * twitter (optional) - Twitter account * websiteUrl (optional) - Website URL * organization (optional) - Organization name * projectsLimit (optional) - Number of projects user can create * externUid (optional) - External UID * provider (optional) - External provider name * bio (optional) - User's biography * location (optional) - User's location * admin (optional) - User is admin - true or false (default) * canCreateGroup (optional) - User can create groups - true or false * skipConfirmation (optional) - Skip confirmation - true or false (default) * external (optional) - Flags the user as external - true or false(default) * sharedRunnersMinutesLimit (optional) - Pipeline minutes quota for this user * </code></pre> * * @param user the User instance with the user info to create * @param password the password for the new user * @param resetPassword whether to send a password reset link * @return created User instance * @throws GitLabApiException if any exception occurs */ public User createUser(User user, CharSequence password, boolean resetPassword) throws GitLabApiException { Form formData = userToForm(user, null, password, resetPassword, true); Response response = post(Response.Status.CREATED, formData, "users"); return (response.readEntity(User.class)); } /** * <p>Modifies an existing user. Only administrators can change attributes of a user.</p> * * <pre><code>GitLab Endpoint: PUT /users</code></pre> * * <p>The following properties of the provided User instance can be set during update:<pre><code> email (required) - Email * username (required) - Username * name (required) - Name * skype (optional) - Skype ID * linkedin (optional) - LinkedIn * twitter (optional) - Twitter account * websiteUrl (optional) - Website URL * organization (optional) - Organization name * projectsLimit (optional) - Number of projects user can create * externUid (optional) - External UID * provider (optional) - External provider name * bio (optional) - User's biography * location (optional) - User's location * admin (optional) - User is admin - true or false (default) * canCreateGroup (optional) - User can create groups - true or false * skipConfirmation (optional) - Skip confirmation - true or false (default) * external (optional) - Flags the user as external - true or false(default) * sharedRunnersMinutesLimit (optional) - Pipeline minutes quota for this user * </code></pre> * * @param user the User instance with the user info to modify * @param password the new password for the user * @return the modified User instance * @throws GitLabApiException if any exception occurs */ public User updateUser(User user, CharSequence password) throws GitLabApiException { Form form = userToForm(user, null, password, false, false); Response response = put(Response.Status.OK, form.asMap(), "users", user.getId()); return (response.readEntity(User.class)); } /** * Modifies an existing user. Only administrators can change attributes of a user. * * <pre><code>GitLab Endpoint: PUT /users/:id</code></pre> * * <p>The following properties of the provided User instance can be set during update:<pre><code> email (required) - Email * username (required) - Username * name (required) - Name * skype (optional) - Skype ID * linkedin (optional) - LinkedIn * twitter (optional) - Twitter account * websiteUrl (optional) - Website URL * organization (optional) - Organization name * projectsLimit (optional) - Number of projects user can create * externUid (optional) - External UID * provider (optional) - External provider name * bio (optional) - User's biography * location (optional) - User's location * admin (optional) - User is admin - true or false (default) * canCreateGroup (optional) - User can create groups - true or false * skipConfirmation (optional) - Skip confirmation - true or false (default) * external (optional) - Flags the user as external - true or false(default) * sharedRunnersMinutesLimit (optional) - Pipeline minutes quota for this user * </code></pre> * * @param user the User instance with the user info to modify * @param password the new password for the user * @param projectsLimit the maximum number of project * @return the modified User instance * @throws GitLabApiException if any exception occurs * @deprecated Will be removed in version 5.0, replaced by {@link #updateUser(User, CharSequence)} */ @Deprecated public User modifyUser(User user, CharSequence password, Integer projectsLimit) throws GitLabApiException { Form form = userToForm(user, projectsLimit, password, false, false); Response response = put(Response.Status.OK, form.asMap(), "users", user.getId()); return (response.readEntity(User.class)); } /** * Deletes a user. Available only for administrators. * * <pre><code>GitLab Endpoint: DELETE /users/:id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @throws GitLabApiException if any exception occurs */ public void deleteUser(Object userIdOrUsername) throws GitLabApiException { deleteUser(userIdOrUsername, null); } /** * Deletes a user. Available only for administrators. * * <pre><code>GitLab Endpoint: DELETE /users/:id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param hardDelete If true, contributions that would usually be moved to the * ghost user will be deleted instead, as well as groups owned solely by this user * @throws GitLabApiException if any exception occurs */ public void deleteUser(Object userIdOrUsername, Boolean hardDelete) throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm().withParam("hard_delete ", hardDelete); Response.Status expectedStatus = (isApiVersion(ApiVersion.V3) ? Response.Status.OK : Response.Status.NO_CONTENT); delete(expectedStatus, formData.asMap(), "users", getUserIdOrUsername(userIdOrUsername)); } /** * Get currently authenticated user. * * <pre><code>GitLab Endpoint: GET /user</code></pre> * * @return the User instance for the currently authenticated user * @throws GitLabApiException if any exception occurs */ public User getCurrentUser() throws GitLabApiException { Response response = get(Response.Status.OK, null, "user"); return (response.readEntity(User.class)); } /** * Get a list of currently authenticated user's SSH keys. * * <pre><code>GitLab Endpoint: GET /user/keys</code></pre> * * @return a list of currently authenticated user's SSH keys * @throws GitLabApiException if any exception occurs */ public List<SshKey> getSshKeys() throws GitLabApiException { Response response = get(Response.Status.OK, getDefaultPerPageParam(), "user", "keys"); return (response.readEntity(new GenericType<List<SshKey>>() {})); } /** * Get a list of a specified user's SSH keys. Available only for admin users. * * <pre><code>GitLab Endpoint: GET /users/:id/keys</code></pre> * * @param userId the user ID to get the SSH keys for * @return a list of a specified user's SSH keys * @throws GitLabApiException if any exception occurs */ public List<SshKey> getSshKeys(Integer userId) throws GitLabApiException { if (userId == null) { throw new RuntimeException("userId cannot be null"); } Response response = get(Response.Status.OK, getDefaultPerPageParam(), "users", userId, "keys"); List<SshKey> keys = response.readEntity(new GenericType<List<SshKey>>() {}); if (keys != null) { keys.forEach(key -> key.setUserId(userId)); } return (keys); } /** * Get a single SSH Key. * * <pre><code>GitLab Endpoint: GET /user/keys/:key_id</code></pre> * * @param keyId the ID of the SSH key. * @return an SshKey instance holding the info on the SSH key specified by keyId * @throws GitLabApiException if any exception occurs */ public SshKey getSshKey(Integer keyId) throws GitLabApiException { Response response = get(Response.Status.OK, null, "user", "keys", keyId); return (response.readEntity(SshKey.class)); } /** * Get a single SSH Key as an Optional instance. * * <pre><code>GitLab Endpoint: GET /user/keys/:key_id</code></pre> * * @param keyId the ID of the SSH key * @return an SshKey as an Optional instance holding the info on the SSH key specified by keyId */ public Optional<SshKey> getOptionalSshKey(Integer keyId) { try { return (Optional.ofNullable(getSshKey(keyId))); } catch (GitLabApiException glae) { return (GitLabApi.createOptionalFromException(glae)); } } /** * Creates a new key owned by the currently authenticated user. * * <pre><code>GitLab Endpoint: POST /user/keys</code></pre> * * @param title the new SSH Key's title * @param key the new SSH key * @return an SshKey instance with info on the added SSH key * @throws GitLabApiException if any exception occurs */ public SshKey addSshKey(String title, String key) throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm().withParam("title", title).withParam("key", key); Response response = post(Response.Status.CREATED, formData, "user", "keys"); return (response.readEntity(SshKey.class)); } /** * Create new key owned by specified user. Available only for admin users. * * <pre><code>GitLab Endpoint: POST /users/:id/keys</code></pre> * * @param userId the ID of the user to add the SSH key for * @param title the new SSH Key's title * @param key the new SSH key * @return an SshKey instance with info on the added SSH key * @throws GitLabApiException if any exception occurs */ public SshKey addSshKey(Integer userId, String title, String key) throws GitLabApiException { if (userId == null) { throw new RuntimeException("userId cannot be null"); } GitLabApiForm formData = new GitLabApiForm().withParam("title", title).withParam("key", key); Response response = post(Response.Status.CREATED, formData, "users", userId, "keys"); SshKey sshKey = response.readEntity(SshKey.class); if (sshKey != null) { sshKey.setUserId(userId); } return (sshKey); } /** * Deletes key owned by currently authenticated user. This is an idempotent function and calling it * on a key that is already deleted or not available results in success. * * <pre><code>GitLab Endpoint: DELETE /user/keys/:key_id</code></pre> * * @param keyId the key ID to delete * @throws GitLabApiException if any exception occurs */ public void deleteSshKey(Integer keyId) throws GitLabApiException { if (keyId == null) { throw new RuntimeException("keyId cannot be null"); } Response.Status expectedStatus = (isApiVersion(ApiVersion.V3) ? Response.Status.OK : Response.Status.NO_CONTENT); delete(expectedStatus, null, "user", "keys", keyId); } /** * Deletes key owned by a specified user. Available only for admin users. * * <pre><code>GitLab Endpoint: DELETE /users/:id/keys/:key_id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param keyId the key ID to delete * @throws GitLabApiException if any exception occurs */ public void deleteSshKey(Object userIdOrUsername, Integer keyId) throws GitLabApiException { if (keyId == null) { throw new RuntimeException("keyId cannot be null"); } Response.Status expectedStatus = (isApiVersion(ApiVersion.V3) ? Response.Status.OK : Response.Status.NO_CONTENT); delete(expectedStatus, null, "users", getUserIdOrUsername(userIdOrUsername), "keys", keyId); } /** * Get a list of a specified user's impersonation tokens. Available only for admin users. * * <pre><code>GitLab Endpoint: GET /users/:id/impersonation_tokens</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @return a list of a specified user's impersonation tokens * @throws GitLabApiException if any exception occurs */ public List<ImpersonationToken> getImpersonationTokens(Object userIdOrUsername) throws GitLabApiException { return (getImpersonationTokens(userIdOrUsername, null)); } /** * Get a list of a specified user's impersonation tokens. Available only for admin users. * * <pre><code>GitLab Endpoint: GET /users/:id/impersonation_tokens</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param state the state of impersonation tokens to list (ALL, ACTIVE, INACTIVE) * @return a list of a specified user's impersonation tokens * @throws GitLabApiException if any exception occurs */ public List<ImpersonationToken> getImpersonationTokens(Object userIdOrUsername, ImpersonationState state) throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm() .withParam("state", state) .withParam(PER_PAGE_PARAM, getDefaultPerPage()); Response response = get(Response.Status.OK, formData.asMap(), "users", getUserIdOrUsername(userIdOrUsername), "impersonation_tokens"); return (response.readEntity(new GenericType<List<ImpersonationToken>>() {})); } /** * Get an impersonation token of a user. Available only for admin users. * * <pre><code>GitLab Endpoint: GET /users/:user_id/impersonation_tokens/:impersonation_token_id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param tokenId the impersonation token ID to get * @return the specified impersonation token * @throws GitLabApiException if any exception occurs */ public ImpersonationToken getImpersonationToken(Object userIdOrUsername, Integer tokenId) throws GitLabApiException { if (tokenId == null) { throw new RuntimeException("tokenId cannot be null"); } Response response = get(Response.Status.OK, null, "users", getUserIdOrUsername(userIdOrUsername), "impersonation_tokens", tokenId); return (response.readEntity(ImpersonationToken.class)); } /** * Get an impersonation token of a user as an Optional instance. Available only for admin users. * * <pre><code>GitLab Endpoint: GET /users/:user_id/impersonation_tokens/:impersonation_token_id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param tokenId the impersonation token ID to get * @return the specified impersonation token as an Optional instance */ public Optional<ImpersonationToken> getOptionalImpersonationToken(Object userIdOrUsername, Integer tokenId) { try { return (Optional.ofNullable(getImpersonationToken(userIdOrUsername, tokenId))); } catch (GitLabApiException glae) { return (GitLabApi.createOptionalFromException(glae)); } } /** * Create an impersonation token. Available only for admin users. * * <pre><code>GitLab Endpoint: POST /users/:user_id/impersonation_tokens</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param name the name of the impersonation token, required * @param expiresAt the expiration date of the impersonation token, optional * @param scopes an array of scopes of the impersonation token * @return the created ImpersonationToken instance * @throws GitLabApiException if any exception occurs */ public ImpersonationToken createImpersonationToken(Object userIdOrUsername, String name, Date expiresAt, Scope[] scopes) throws GitLabApiException { if (scopes == null || scopes.length == 0) { throw new RuntimeException("scopes cannot be null or empty"); } GitLabApiForm formData = new GitLabApiForm() .withParam("name", name, true) .withParam("expires_at", expiresAt); for (Scope scope : scopes) { formData.withParam("scopes[]", scope.toString()); } Response response = post(Response.Status.CREATED, formData, "users", getUserIdOrUsername(userIdOrUsername), "impersonation_tokens"); return (response.readEntity(ImpersonationToken.class)); } /** * Revokes an impersonation token. Available only for admin users. * * <pre><code>GitLab Endpoint: DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param tokenId the impersonation token ID to revoke * @throws GitLabApiException if any exception occurs */ public void revokeImpersonationToken(Object userIdOrUsername, Integer tokenId) throws GitLabApiException { if (tokenId == null) { throw new RuntimeException("tokenId cannot be null"); } Response.Status expectedStatus = (isApiVersion(ApiVersion.V3) ? Response.Status.OK : Response.Status.NO_CONTENT); delete(expectedStatus, null, "users", getUserIdOrUsername(userIdOrUsername), "impersonation_tokens", tokenId); } /** * Populate the REST form with data from the User instance. * * @param user the User instance to populate the Form instance with * @param projectsLimit the maximum number of projects the user is allowed (optional) * @param password the password, required when creating a new user * @param create whether the form is being populated to create a new user * @return the populated Form instance */ Form userToForm(User user, Integer projectsLimit, CharSequence password, Boolean resetPassword, boolean create) { if (create) { if ((password == null || password.toString().trim().isEmpty()) && !resetPassword) { throw new IllegalArgumentException("either password or reset_password must be set"); } } projectsLimit = (projectsLimit == null) ? user.getProjectsLimit() : projectsLimit; String skipConfirmationFeildName = create ? "skip_confirmation" : "skip_reconfirmation"; return (new GitLabApiForm() .withParam("email", user.getEmail(), create) .withParam("password", password, false) .withParam("reset_password", resetPassword, false) .withParam("username", user.getUsername(), create) .withParam("name", user.getName(), create) .withParam("skype", user.getSkype(), false) .withParam("linkedin", user.getLinkedin(), false) .withParam("twitter", user.getTwitter(), false) .withParam("website_url", user.getWebsiteUrl(), false) .withParam("organization", user.getOrganization(), false) .withParam("projects_limit", projectsLimit, false) .withParam("extern_uid", user.getExternUid(), false) .withParam("provider", user.getProvider(), false) .withParam("bio", user.getBio(), false) .withParam("location", user.getLocation(), false) .withParam("admin", user.getIsAdmin(), false) .withParam("theme_id", user.getThemeId(), false) .withParam("color_scheme_id", user.getColorSchemeId(), false) .withParam("can_create_group", user.getCanCreateGroup(), false) .withParam(skipConfirmationFeildName, user.getSkipConfirmation(), false) .withParam("external", user.getExternal(), false) .withParam("shared_runners_minutes_limit", user.getSharedRunnersMinutesLimit(), false)); } /** * Creates custom attribute for the given user * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param customAttribute the custom attribute to set * @return the created CustomAttribute * @throws GitLabApiException on failure while setting customAttributes */ public CustomAttribute createCustomAttribute(final Object userIdOrUsername, final CustomAttribute customAttribute) throws GitLabApiException { if (Objects.isNull(customAttribute)) { throw new IllegalArgumentException("CustomAttributes can't be null"); } return createCustomAttribute(userIdOrUsername, customAttribute.getKey(), customAttribute.getValue()); } /** * Creates custom attribute for the given user * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param key for the customAttribute * @param value or the customAttribute * @return the created CustomAttribute * @throws GitLabApiException on failure while setting customAttributes */ public CustomAttribute createCustomAttribute(final Object userIdOrUsername, final String key, final String value) throws GitLabApiException { if (Objects.isNull(key) || key.trim().isEmpty()) { throw new IllegalArgumentException("Key can't be null or empty"); } if (Objects.isNull(value) || value.trim().isEmpty()) { throw new IllegalArgumentException("Value can't be null or empty"); } GitLabApiForm formData = new GitLabApiForm().withParam("value", value); Response response = put(Response.Status.OK, formData.asMap(), "users", getUserIdOrUsername(userIdOrUsername), "custom_attributes", key); return (response.readEntity(CustomAttribute.class)); } /** * Change custom attribute for the given user * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param customAttribute the custome attribute to change * @return the changed CustomAttribute * @throws GitLabApiException on failure while changing customAttributes */ public CustomAttribute changeCustomAttribute(final Object userIdOrUsername, final CustomAttribute customAttribute) throws GitLabApiException { if (Objects.isNull(customAttribute)) { throw new IllegalArgumentException("CustomAttributes can't be null"); } //changing & creating custom attributes is the same call in gitlab api // -> https://docs.gitlab.com/ce/api/custom_attributes.html#set-custom-attribute return createCustomAttribute(userIdOrUsername, customAttribute.getKey(), customAttribute.getValue()); } /** * Changes custom attribute for the given user * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param key for the customAttribute * @param value for the customAttribute * @return changedCustomAttribute * @throws GitLabApiException on failure while changing customAttributes */ public CustomAttribute changeCustomAttribute(final Object userIdOrUsername, final String key, final String value) throws GitLabApiException { return createCustomAttribute(userIdOrUsername, key, value); } /** * Delete a custom attribute for the given user * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param customAttribute to remove * @throws GitLabApiException on failure while deleting customAttributes */ public void deleteCustomAttribute(final Object userIdOrUsername, final CustomAttribute customAttribute) throws GitLabApiException { if (Objects.isNull(customAttribute)) { throw new IllegalArgumentException("customAttributes can't be null"); } deleteCustomAttribute(userIdOrUsername, customAttribute.getKey()); } /** * Delete a custom attribute for the given user * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param key of the customAttribute to remove * @throws GitLabApiException on failure while deleting customAttributes */ public void deleteCustomAttribute(final Object userIdOrUsername, final String key) throws GitLabApiException { if (Objects.isNull(key) || key.trim().isEmpty()) { throw new IllegalArgumentException("Key can't be null or empty"); } delete(Response.Status.OK, null, "users", getUserIdOrUsername(userIdOrUsername), "custom_attributes", key); } /** * Creates a GitLabApiForm instance that will optionally include the * with_custom_attributes query param if enabled. * * @return a GitLabApiForm instance that will optionally include the * with_custom_attributes query param if enabled */ private GitLabApiForm createGitLabApiForm() { GitLabApiForm formData = new GitLabApiForm(); return (customAttributesEnabled ? formData.withParam("with_custom_attributes", true) : formData); } /** * Uploads and sets the user's avatar for the specified user. * * <pre><code>PUT /users/:id</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param avatarFile the File instance of the avatar file to upload * @return the updated User instance * @throws GitLabApiException if any exception occurs */ public User setUserAvatar(final Object userIdOrUsername, File avatarFile) throws GitLabApiException { Response response = putUpload(Response.Status.OK, "avatar", avatarFile, "users", getUserIdOrUsername(userIdOrUsername)); return (response.readEntity(User.class)); } /** * Get a list of emails for the current user. * * <pre><code>GitLab Endpoint: GET /users/emails</code></pre> * * @return a List of Email instances for the current user * @throws GitLabApiException if any exception occurs */ public List<Email> getEmails() throws GitLabApiException { Response response = get(Response.Status.OK, null, "user", "emails"); return (response.readEntity(new GenericType<List<Email>>() {})); } /** * Get a list of a specified user’s emails. Available only for admin users. * * <pre><code>GitLab Endpoint: GET /user/:id/emails</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @return a List of Email instances for the specified user * @throws GitLabApiException if any exception occurs */ public List<Email> getEmails(final Object userIdOrUsername) throws GitLabApiException { Response response = get(Response.Status.OK, null, "users", getUserIdOrUsername(userIdOrUsername), "emails"); return (response.readEntity(new GenericType<List<Email>>() {})); } /** * Add an email to the current user's emails. * * <pre><code>GitLab Endpoint: POST /user/:id/emails</code></pre> * * @param email the email address to add * @return the Email instance for the added email * @throws GitLabApiException if any exception occurs */ public Email addEmail(String email) throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm().withParam("email", email, true); Response response = post(Response.Status.CREATED, formData, "user", "emails"); return (response.readEntity(Email.class)); } /** * Get a single Email instance specified by he email ID * * <pre><code>GitLab Endpoint: GET /user/emails/:emailId</code></pre> * * @param emailId the email ID to get * @return the Email instance for the provided email ID * @throws GitLabApiException if any exception occurs */ public Email getEmail(final Long emailId) throws GitLabApiException { Response response = get(Response.Status.CREATED, null, "user", "emails", emailId); return (response.readEntity(Email.class)); } /** * Add an email to the user's emails. * * <pre><code>GitLab Endpoint: POST /user/:id/emails</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param email the email address to add * @param skipConfirmation skip confirmation and assume e-mail is verified - true or false (default) * @return the Email instance for the added email * @throws GitLabApiException if any exception occurs */ public Email addEmail(final Object userIdOrUsername, String email, Boolean skipConfirmation) throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm() .withParam("email", email, true) .withParam("skip_confirmation ", skipConfirmation); Response response = post(Response.Status.CREATED, formData, "users", getUserIdOrUsername(userIdOrUsername), "emails"); return (response.readEntity(Email.class)); } /** * Deletes an email belonging to the current user. * * <pre><code>GitLab Endpoint: DELETE /user/emails/:emailId</code></pre> * * @param emailId the email ID to delete * @throws GitLabApiException if any exception occurs */ public void deleteEmail(final Long emailId) throws GitLabApiException { delete(Response.Status.NO_CONTENT, null, "user", "emails", emailId); } /** * Deletes a user's email * * <pre><code>GitLab Endpoint: DELETE /user/:id/emails/:emailId</code></pre> * * @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance * @param emailId the email ID to delete * @throws GitLabApiException if any exception occurs */ public void deleteEmail(final Object userIdOrUsername, final Long emailId) throws GitLabApiException { delete(Response.Status.NO_CONTENT, null, "users", getUserIdOrUsername(userIdOrUsername), "emails", emailId); } }