diff --git a/src/main/java/org/gitlab4j/api/ApplicationSettingsApi.java b/src/main/java/org/gitlab4j/api/ApplicationSettingsApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d53437b027dfcda1e1117c710aed61b42dcaf29
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/ApplicationSettingsApi.java
@@ -0,0 +1,156 @@
+package org.gitlab4j.api;
+
+import java.text.ParseException;
+import java.util.Iterator;
+
+import javax.ws.rs.core.Response;
+
+import org.gitlab4j.api.models.Setting;
+import org.gitlab4j.api.models.ApplicationSettings;
+import org.gitlab4j.api.utils.ISO8601;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * This class implements the client side API for the GitLab Application Settings API.
+ * See Application Settings API at GitLab for more information.
+ */
+public class ApplicationSettingsApi extends AbstractApi {
+
+ public ApplicationSettingsApi(GitLabApi gitLabApi) {
+ super(gitLabApi);
+ }
+
+ /**
+ * Get the current application settings of the GitLab instance.
+ *
+ *
GitLab Endpoint: GET /api/v4/application/settings
+ *
+ * @return an ApplicationSettings instance containing the current application settings of the GitLab instance.
+ * @throws GitLabApiException if any exception occurs
+ */
+ public ApplicationSettings getApplicationSettings() throws GitLabApiException {
+
+ Response response = get(Response.Status.OK, null, "application", "settings");
+ JsonNode root = response.readEntity(JsonNode.class);
+ return (parseApplicationSettings(root));
+ }
+
+ /**
+ * Update the application settings of the GitLab instance with the settings in the
+ * provided ApplicationSettings instance.
+ *
+ * GitLab Endpoint: PUT /api/v4/application/settings
+ *
+ * @param appSettings the ApplicationSettings instance holding the settings and values to update
+ * @return the updated application settings in an ApplicationSettings instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public ApplicationSettings updateApplicationSettings(ApplicationSettings appSettings) throws GitLabApiException {
+
+ if (appSettings == null || appSettings.getSettings().isEmpty()) {
+ throw new GitLabApiException("ApplicationSettings cannot be null or empty.");
+ }
+
+ final GitLabApiForm form = new GitLabApiForm();
+ appSettings.getSettings().forEach((s, v) -> form.withParam(s, v));
+ Response response = put(Response.Status.OK, form.asMap(), "application", "settings");
+ JsonNode root = response.readEntity(JsonNode.class);
+ return (parseApplicationSettings(root));
+ }
+
+ /**
+ * Update a single application setting of the GitLab instance with the provided settings and value.
+ *
+ * GitLab Endpoint: PUT /api/v4/application/settings
+ *
+ * @param setting the ApplicationSetting to update
+ * @param value the new value for the application setting
+ * @return the updated application settings in an ApplicationSettings instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public ApplicationSettings updateApplicationSetting(Setting setting, Object value) throws GitLabApiException {
+
+ if (setting == null) {
+ throw new GitLabApiException("setting cannot be null.");
+ }
+
+ return (updateApplicationSetting(setting.toString(), value));
+ }
+
+ /**
+ * Update a single application setting of the GitLab instance with the provided settings and value.
+ *
+ * GitLab Endpoint: PUT /api/v4/application/settings
+ *
+ * @param setting the ApplicationSetting to update
+ * @param value the new value for the application setting
+ * @return the updated application settings in an ApplicationSettings instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public ApplicationSettings updateApplicationSetting(String setting, Object value) throws GitLabApiException {
+
+ if (setting == null || setting.trim().isEmpty()) {
+ throw new GitLabApiException("setting cannot be null or empty.");
+ }
+
+ GitLabApiForm form = new GitLabApiForm().withParam(setting, value);
+ Response response = put(Response.Status.OK, form.asMap(), "application", "settings");
+ JsonNode root = response.readEntity(JsonNode.class);
+ return (parseApplicationSettings(root));
+ }
+
+ /**
+ * Pareses the returned JSON and returns an ApplicationSettings instance.
+ *
+ * @param root the root JsonNode
+ * @return the populated ApplicationSettings instance
+ * @throws GitLabApiException if any error occurs
+ */
+ private final ApplicationSettings parseApplicationSettings(JsonNode root) throws GitLabApiException {
+
+ ApplicationSettings appSettings = new ApplicationSettings();
+
+ Iterator fieldNames = root.fieldNames();
+ while (fieldNames.hasNext()) {
+
+ String fieldName = fieldNames.next();
+ switch (fieldName) {
+ case "id":
+ appSettings.setId(root.path(fieldName).asInt());
+ break;
+
+ case "created_at":
+ try {
+ appSettings.setCreatedAt(ISO8601.toDate(root.path(fieldName).asText()));
+ } catch (ParseException pe) {
+ throw new GitLabApiException(pe);
+ }
+ break;
+
+ case "updated_at":
+ try {
+ appSettings.setUpdatedAt(ISO8601.toDate(root.path(fieldName).asText()));
+ } catch (ParseException pe) {
+ throw new GitLabApiException(pe);
+ }
+ break;
+
+ default:
+
+ Setting setting = Setting.forValue(fieldName);
+ if (setting != null) {
+ appSettings.addSetting(setting, root.path(fieldName));
+ } else {
+ GitLabApi.getLogger().warning(String.format("Unknown setting: %s, type: %s",
+ fieldName, root.path(fieldName).getClass().getSimpleName()));
+ appSettings.addSetting(fieldName, root.path(fieldName));
+ }
+
+ break;
+ }
+ }
+
+ return (appSettings);
+ }
+}
diff --git a/src/main/java/org/gitlab4j/api/models/ApplicationSettings.java b/src/main/java/org/gitlab4j/api/models/ApplicationSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd33bb26cb66c92fc3feae972d58f7b3380a9b06
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/models/ApplicationSettings.java
@@ -0,0 +1,147 @@
+package org.gitlab4j.api.models;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.gitlab4j.api.GitLabApiException;
+import org.gitlab4j.api.utils.JacksonJson;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.BooleanNode;
+import com.fasterxml.jackson.databind.node.DoubleNode;
+import com.fasterxml.jackson.databind.node.FloatNode;
+import com.fasterxml.jackson.databind.node.IntNode;
+import com.fasterxml.jackson.databind.node.NullNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+
+public class ApplicationSettings {
+
+ private Integer id;
+ private Date createdAt;
+ private Date updatedAt;
+ private Map settings = new HashMap<>();
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Date getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(Date createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public Date getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public void setUpdatedAt(Date updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ public Map getSettings() {
+ return settings;
+ }
+
+ public void setSettings(Map settings) {
+ this.settings = settings;
+ }
+
+ @JsonIgnore
+ public Object getSetting(Setting setting) {
+
+ if (setting == null) {
+ return (null);
+ }
+
+ String name = setting.toString();
+ return (settings.get(name));
+ }
+
+ @JsonIgnore
+ public Object getSetting(String setting) {
+
+ if (setting == null) {
+ return (null);
+ }
+
+ return (settings.get(setting));
+ }
+
+ public Object addSetting(String setting, Object value) throws GitLabApiException {
+
+ Setting appSetting = Setting.forValue(setting);
+ if (appSetting != null) {
+ return (addSetting(appSetting, value));
+ }
+
+ settings.put(setting, value);
+ return (value);
+ }
+
+ public Object addSetting(Setting setting, Object value) throws GitLabApiException {
+
+ if (value instanceof JsonNode) {
+ value = jsonNodeToValue((JsonNode)value);
+ }
+
+ setting.validate(value);
+ settings.put(setting.toString(), value);
+ return (value);
+ }
+
+ public Object removeSetting(Setting setting) {
+ return settings.remove(setting.toString());
+ }
+
+ public Object removeSetting(String setting) {
+ return settings.remove(setting);
+ }
+
+ public void clearSettings() {
+ settings.clear();
+ }
+
+ private Object jsonNodeToValue(JsonNode node) {
+
+ Object value = node;
+ if (node instanceof NullNode) {
+ value = null;
+ } else if (node instanceof TextNode) {
+ value = node.asText();
+ } else if (node instanceof BooleanNode) {
+ value = node.asBoolean();
+ } else if (node instanceof IntNode) {
+ value = node.asInt();
+ } else if (node instanceof FloatNode) {
+ value = (float)((FloatNode)node).asDouble();
+ } else if (node instanceof DoubleNode) {
+ value = (float)((DoubleNode)node).asDouble();
+ } else if (node instanceof ArrayNode) {
+
+ int numItems = node.size();
+ String[] values = new String[numItems];
+ for (int i = 0; i < numItems; i++) {
+ values[i] = node.path(i).asText();
+ }
+
+ value = values;
+ }
+
+ return (value);
+ }
+
+ @Override
+ public String toString() {
+ return (JacksonJson.toJsonString(this));
+ }
+}
diff --git a/src/main/java/org/gitlab4j/api/models/Setting.java b/src/main/java/org/gitlab4j/api/models/Setting.java
new file mode 100644
index 0000000000000000000000000000000000000000..409bd8f47ccaa81985a9eed262cc537cd1c5edda
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/models/Setting.java
@@ -0,0 +1,795 @@
+package org.gitlab4j.api.models;
+
+import org.gitlab4j.api.GitLabApiException;
+import org.gitlab4j.api.utils.JacksonJsonEnumHelper;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * This enum provides constants and value validation for the available GitLab application settings.
+ * See
+ * List of settings that can be accessed via API calls for more information.
+ */
+public enum Setting {
+
+ /**
+ * Abuse reports will be sent to this address if it is set. Abuse reports are
+ * always available in the admin area.
+ */
+ ADMIN_NOTIFICATION_EMAIL(String.class),
+
+ /** Where to redirect users after logout. */
+ AFTER_SIGN_OUT_PATH(String.class),
+
+ /** Text shown to the user after signing up */
+ AFTER_SIGN_UP_TEXT(String.class),
+
+ /** required by: akismet_enabled API key for akismet spam protection. */
+ AKISMET_API_KEY(String.class),
+
+ /**
+ * (If enabled, requires: akismet_api_key) Enable or disable akismet spam
+ * protection.
+ */
+ AKISMET_ENABLED(Boolean.class),
+
+ /** (Premium) Set to true to allow group owners to manage LDAP */
+ ALLOW_GROUP_OWNERS_TO_MANAGE_LDAP(Boolean.class),
+
+ /** Allow requests to the local network from hooks and services. */
+ ALLOW_LOCAL_REQUESTS_FROM_HOOKS_AND_SERVICES(Boolean.class),
+
+ /**
+ * By default, we write to the authorized_keys file to support Git over SSH
+ * without additional configuration. GitLab can be optimized to authenticate SSH
+ * keys via the database file. Only disable this if you have configured your
+ * OpenSSH server to use the AuthorizedKeysCommand.
+ */
+ AUTHORIZED_KEYS_ENABLED(Boolean.class),
+
+ /**
+ * Specify a domain to use by default for every project’s Auto Review Apps and
+ * Auto Deploy stages.
+ */
+ AUTO_DEVOPS_DOMAIN(String.class),
+
+ /**
+ * Enable Auto DevOps for projects by default. It will automatically build,
+ * test, and deploy applications based on a predefined CI/CD configuration.
+ */
+ AUTO_DEVOPS_ENABLED(Boolean.class),
+
+ /**
+ * (Premium) Enabling this will make only licensed EE features available to
+ * projects if the project namespace’s plan includes the feature or if the
+ * project is public.
+ */
+ CHECK_NAMESPACE_PLAN(Boolean.class),
+
+ /**
+ * required by: clientside_sentry_enabled Clientside Sentry Data Source Name.
+ */
+ CLIENTSIDE_SENTRY_DSN(String.class),
+
+ /**
+ * (If enabled, requires: clientside_sentry_dsn) Enable Sentry error reporting
+ * for the client side.
+ */
+ CLIENTSIDE_SENTRY_ENABLED(Boolean.class),
+
+ /** Container Registry token duration in minutes. */
+ CONTAINER_REGISTRY_TOKEN_EXPIRE_DELAY(Integer.class),
+
+ /** Set the default expiration time for each job’s artifacts. */
+ DEFAULT_ARTIFACTS_EXPIRE_IN(String.class),
+
+ /**
+ * Determine if developers can push to master. Can take: 0 (not protected, both
+ * developers and maintainers can push new commits, force push, or delete the
+ * branch), 1 (partially protected, developers and maintainers can push new
+ * commits, but cannot force push or delete the branch) or 2 (fully protected,
+ * developers cannot push new commits, but maintainers can; no-one can force
+ * push or delete the branch) as a parameter. Default is 2.
+ */
+ DEFAULT_BRANCH_PROTECTION(Integer.class),
+
+ /**
+ * What visibility level new groups receive. Can take private, internal and
+ * public as a parameter. Default is private.
+ */
+ DEFAULT_GROUP_VISIBILITY(String.class),
+
+ /**
+ * What visibility level new projects receive. Can take private, internal and
+ * public as a parameter. Default is private.
+ */
+ DEFAULT_PROJECT_VISIBILITY(String.class),
+
+ /** Project limit per user. Default is 100000. */
+ DEFAULT_PROJECTS_LIMIT(Integer.class),
+
+ /**
+ * What visibility level new snippets receive. Can take private, internal and
+ * public as a parameter. Default is private.
+ */
+ DEFAULT_SNIPPET_VISIBILITY(String.class),
+
+ /** Disabled OAuth sign-in sources. */
+ DISABLED_OAUTH_SIGN_IN_SOURCES(String[].class),
+
+ /**
+ * required by: domain_blacklist_enabled Users with e-mail addresses that match
+ * these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate
+ * lines for multiple entries. Ex: domain.com, *.domain.com.
+ */
+ DOMAIN_BLACKLIST(String[].class),
+
+ /**
+ * (If enabled, requires: domain_blacklist) Allows blocking sign-ups from emails
+ * from specific domains.
+ */
+ DOMAIN_BLACKLIST_ENABLED(Boolean.class),
+
+ /**
+ * Force people to use only corporate emails for sign-up. Default is null,
+ * meaning there is no restriction.
+ */
+ DOMAIN_WHITELIST(String[].class),
+
+ /**
+ * The minimum allowed bit length of an uploaded DSA key. Default is 0 (no
+ * restriction). -1 disables DSA keys.
+ */
+ DSA_KEY_RESTRICTION(Integer.class),
+
+ /**
+ * The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is
+ * 0 (no restriction). -1 disables ECDSA keys.
+ */
+ ECDSA_KEY_RESTRICTION(Integer.class),
+
+ /**
+ * The minimum allowed curve size (in bits) of an uploaded ED25519 key. Default
+ * is 0 (no restriction). -1 disables ED25519 keys.
+ */
+ ED25519_KEY_RESTRICTION(Integer.class),
+
+ /** (Premium) Enable the use of AWS hosted Elasticsearch */
+ ELASTICSEARCH_AWS(Boolean.class),
+
+ /** (Premium) AWS IAM access key */
+ ELASTICSEARCH_AWS_ACCESS_KEY(String.class),
+
+ /** (Premium) The AWS region the elasticsearch domain is configured */
+ ELASTICSEARCH_AWS_REGION(String.class),
+
+ /** (Premium) AWS IAM secret access key */
+ ELASTICSEARCH_AWS_SECRET_ACCESS_KEY(String.class),
+
+ /**
+ * (Premium) Use the experimental elasticsearch indexer. More info:
+ * https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer
+ */
+ ELASTICSEARCH_EXPERIMENTAL_INDEXER(Boolean.class),
+
+ /** (Premium) Enable Elasticsearch indexing */
+ ELASTICSEARCH_INDEXING(Boolean.class),
+
+ /** (Premium) Enable Elasticsearch search */
+ ELASTICSEARCH_SEARCH(Boolean.class),
+
+ /**
+ * (Premium) The url to use for connecting to Elasticsearch. Use a
+ * comma-separated list to support cluster (e.g., “http://localhost:9200,
+ * http://localhost:9201"). If your Elasticsearch instance is password
+ * protected, pass the username:password in the URL,
+ */
+ ELASTICSEARCH_URL(String.class),
+
+ /**
+ * (Premium) Additional text added to the bottom of every email for
+ * legal/auditing/compliance reasons
+ */
+ EMAIL_ADDITIONAL_TEXT(String.class),
+
+ /**
+ * Some email servers do not support overriding the email sender name. Enable
+ * this option to include the name of the author of the issue, merge request or
+ * comment in the email body instead.
+ */
+ EMAIL_AUTHOR_IN_BODY(Boolean.class),
+
+ /**
+ * Enabled protocols for Git access. Allowed values are: ssh, http, and nil to
+ * allow both protocols.
+ */
+ ENABLED_GIT_ACCESS_PROTOCOL(String.class),
+
+ /** (If enabled, requires: terms) Enforce application ToS to all users. */
+ ENFORCE_TERMS(Boolean.class),
+
+ /**
+ * (Premium) (If enabled, requires: external_auth_client_key) The certificate to
+ * use to authenticate with the external authorization service
+ */
+ EXTERNAL_AUTH_CLIENT_CERT(String.class),
+
+ /**
+ * required by: external_auth_client_cert (Premium) Private key for the
+ * certificate when authentication is required for the external authorization
+ * service, this is encrypted when stored
+ */
+ EXTERNAL_AUTH_CLIENT_KEY(String.class),
+
+ /**
+ * (Premium) Passphrase to use for the private key when authenticating with the
+ * external service this is encrypted when stored
+ */
+ EXTERNAL_AUTH_CLIENT_KEY_PASS(String.class),
+
+ /**
+ * required by: external_authorization_service_enabled (Premium) The default
+ * classification label to use when requesting authorization and no
+ * classification label has been specified on the project
+ */
+ EXTERNAL_AUTHORIZATION_SERVICE_DEFAULT_LABEL(String.class),
+
+ /**
+ * (Premium) (If enabled, requires:
+ * external_authorization_service_default_label,
+ * external_authorization_service_timeout and external_authorization_service_url
+ * ) Enable using an external authorization service for accessing projects
+ */
+ EXTERNAL_AUTHORIZATION_SERVICE_ENABLED(Boolean.class),
+
+ /**
+ * required by: external_authorization_service_enabled (Premium) The timeout
+ * after which an authorization request is aborted, in seconds. When a request
+ * times out, access is denied to the user. (min: 0.001, max: 10, step: 0.001)
+ */
+ EXTERNAL_AUTHORIZATION_SERVICE_TIMEOUT(Float.class),
+
+ /**
+ * required by: external_authorization_service_enabled (Premium) URL to which
+ * authorization requests will be directed
+ */
+ EXTERNAL_AUTHORIZATION_SERVICE_URL(String.class),
+
+ /** (Premium) The ID of a project to load custom file templates from */
+ FILE_TEMPLATE_PROJECT_ID(Integer.class),
+
+ /**
+ * Start day of the week for calendar views and date pickers. Valid values are 0
+ * (default) for Sunday, 1 for Monday, and 6 for Saturday.
+ */
+ FIRST_DAY_OF_WEEK(Integer.class),
+
+ /**
+ * (Premium) Comma-separated list of IPs and CIDRs of allowed secondary nodes.
+ * For example, 1.1.1.1, 2.2.2.0/24.
+ */
+ GEO_NODE_ALLOWED_IPS(String.class),
+
+ /**
+ * (Premium) The amount of seconds after which a request to get a secondary node
+ * status will time out.
+ */
+ GEO_STATUS_TIMEOUT(Integer.class),
+
+ /**
+ * Default Gitaly timeout, in seconds. This timeout is not enforced for git
+ * fetch/push operations or Sidekiq jobs. Set to 0 to disable timeouts.
+ */
+ GITALY_TIMEOUT_DEFAULT(Integer.class),
+
+ /**
+ * Gitaly fast operation timeout, in seconds. Some Gitaly operations are
+ * expected to be fast. If they exceed this threshold, there may be a problem
+ * with a storage shard and ‘failing fast’ can help maintain the stability of
+ * the GitLab instance. Set to 0 to disable timeouts.
+ */
+ GITALY_TIMEOUT_FAST(Integer.class),
+
+ /**
+ * Medium Gitaly timeout, in seconds. This should be a value between the Fast
+ * and the Default timeout. Set to 0 to disable timeouts.
+ */
+ GITALY_TIMEOUT_MEDIUM(Integer.class),
+
+ /** Enable Gravatar. */
+ GRAVATAR_ENABLED(Boolean.class),
+
+ /**
+ * Create new projects using hashed storage paths: Enable immutable, hash-based
+ * paths and repository names to store repositories on disk. This prevents
+ * repositories from having to be moved or renamed when the Project URL changes
+ * and may improve disk I/O performance. (EXPERIMENTAL)
+ */
+ HASHED_STORAGE_ENABLED(Boolean.class),
+
+ /** Hide marketing-related entries from help. */
+ HELP_PAGE_HIDE_COMMERCIAL_CONTENT(Boolean.class),
+
+ /** Alternate support URL for help page. */
+ HELP_PAGE_SUPPORT_URL(String.class),
+
+ /** Custom text displayed on the help page. */
+ HELP_PAGE_TEXT(String.class),
+
+ /** (Premium) GitLab server administrator information */
+ HELP_TEXT(String.class),
+
+ /** Do not display offers from third parties within GitLab. */
+ HIDE_THIRD_PARTY_OFFERS(Boolean.class),
+
+ /** Redirect to this URL when not logged in. */
+ HOME_PAGE_URL(String.class),
+
+ /** required by: housekeeping_enabled Enable Git pack file bitmap creation. */
+ HOUSEKEEPING_BITMAPS_ENABLED(Boolean.class),
+
+ /**
+ * (If enabled, requires: housekeeping_bitmaps_enabled,
+ * housekeeping_full_repack_period, housekeeping_gc_period, and
+ * housekeeping_incremental_repack_period) Enable or disable git housekeeping.
+ */
+ HOUSEKEEPING_ENABLED(Boolean.class),
+
+ /**
+ * required by: housekeeping_enabled Number of Git pushes after which an
+ * incremental git repack is run.
+ */
+ HOUSEKEEPING_FULL_REPACK_PERIOD(Integer.class),
+
+ /**
+ * required by: housekeeping_enabled Number of Git pushes after which git gc is
+ * run.
+ */
+ HOUSEKEEPING_GC_PERIOD(Integer.class),
+
+ /**
+ * required by: housekeeping_enabled Number of Git pushes after which an
+ * incremental git repack is run.
+ */
+ HOUSEKEEPING_INCREMENTAL_REPACK_PERIOD(Integer.class),
+
+ /** Enable HTML emails. */
+ HTML_EMAILS_ENABLED(Boolean.class),
+
+ /**
+ * Sources to allow project import from, possible values: github, bitbucket,
+ * gitlab, google_code, fogbugz, git, and gitlab_project.
+ */
+ IMPORT_SOURCES(String[].class),
+
+ /** When set to true Instance statistics will only be available to admins. */
+ INSTANCE_STATISTICS_VISIBILITY_PRIVATE(Boolean.class),
+
+ /** Increase this value when any cached markdown should be invalidated. */
+ LOCAL_MARKDOWN_VERSION(Integer.class),
+
+ /** Maximum artifacts size in MB */
+ MAX_ARTIFACTS_SIZE(Integer.class),
+
+ /** Limit attachment size in MB */
+ MAX_ATTACHMENT_SIZE(Integer.class),
+
+ /** Maximum size of pages repositories in MB */
+ MAX_PAGES_SIZE(Integer.class),
+
+ /**
+ * (If enabled, requires: metrics_host, metrics_method_call_threshold,
+ * metrics_packet_size, metrics_pool_size, metrics_port, metrics_sample_interval
+ * and metrics_timeout) Enable influxDB metrics.
+ */
+ METRICS_ENABLED(Boolean.class),
+
+ /** required by: metrics_enabled InfluxDB host. */
+ METRICS_HOST(String.class),
+
+ /**
+ * required by: metrics_enabled A method call is only tracked when it takes
+ * longer than the given amount of milliseconds.
+ */
+ METRICS_METHOD_CALL_THRESHOLD(Integer.class),
+
+ /**
+ * required by: metrics_enabled The amount of datapoints to send in a single UDP
+ * packet.
+ */
+ METRICS_PACKET_SIZE(Integer.class),
+
+ /**
+ * required by: metrics_enabled The amount of InfluxDB connections to keep open.
+ */
+ METRICS_POOL_SIZE(Integer.class),
+
+ /**
+ * required by: metrics_enabled The UDP port to use for connecting to InfluxDB.
+ */
+ METRICS_PORT(Integer.class),
+
+ /** required by: metrics_enabled The sampling interval in seconds. */
+ METRICS_SAMPLE_INTERVAL(Integer.class),
+
+ /**
+ * required by: metrics_enabled The amount of seconds after which InfluxDB will
+ * time out.
+ */
+ METRICS_TIMEOUT(Integer.class),
+
+ /**
+ * Allow mirrors to be set up for projects. If disabled, only admins will be
+ * able to set up mirrors in projects.
+ */
+ MIRROR_AVAILABLE(Boolean.class),
+
+ /**
+ * (Premium) Minimum capacity to be available before scheduling more mirrors
+ * preemptively
+ */
+ MIRROR_CAPACITY_THRESHOLD(Integer.class),
+
+ /**
+ * (Premium) Maximum number of mirrors that can be synchronizing at the same
+ * time.
+ */
+ MIRROR_MAX_CAPACITY(Integer.class),
+
+ /**
+ * (Premium) Maximum time (in minutes) between updates that a mirror can have
+ * when scheduled to synchronize.
+ */
+ MIRROR_MAX_DELAY(Integer.class),
+
+ /**
+ * Require users to prove ownership of custom domains. Domain verification is an
+ * essential security measure for public GitLab sites. Users are required to
+ * demonstrate they control a domain before it is enabled.
+ */
+ PAGES_DOMAIN_VERIFICATION_ENABLED(Boolean.class),
+
+ /**
+ * Enable authentication for Git over HTTP(S) via a GitLab account password.
+ * Default is true.
+ */
+ PASSWORD_AUTHENTICATION_ENABLED_FOR_GIT(Boolean.class),
+
+ /**
+ * Enable authentication for the web interface via a GitLab account password.
+ * Default is true.
+ */
+ PASSWORD_AUTHENTICATION_ENABLED_FOR_WEB(Boolean.class),
+
+ /**
+ * (Deprecated: Use performance_bar_allowed_group_path instead) Path of the
+ * group that is allowed to toggle the performance bar.
+ */
+ PERFORMANCE_BAR_ALLOWED_GROUP_ID(String.class),
+
+ /** Path of the group that is allowed to toggle the performance bar. */
+ PERFORMANCE_BAR_ALLOWED_GROUP_PATH(String.class),
+
+ /**
+ * (Deprecated: Pass performance_bar_allowed_group_path: nil instead) Allow
+ * enabling the performance bar.
+ */
+ PERFORMANCE_BAR_ENABLED(Boolean.class),
+
+ /**
+ * (If enabled, requires: plantuml_url) Enable PlantUML integration. Default is
+ * false.
+ */
+ PLANTUML_ENABLED(Boolean.class), // Decimal
+
+ /** required by: plantuml_enabled The PlantUML instance URL for integration. */
+ PLANTUML_URL(String.class),
+
+ /**
+ * Interval multiplier used by endpoints that perform polling. Set to 0 to disable polling.
+ * The documentation liusts this as a decimal, but it is a String in the JSON.
+ */
+ POLLING_INTERVAL_MULTIPLIER(String.class),
+
+ /** Enable project export. */
+ PROJECT_EXPORT_ENABLED(Boolean.class),
+
+ /** Enable prometheus metrics. */
+ PROMETHEUS_METRICS_ENABLED(Boolean.class),
+
+ /**
+ * (Premium) When enabled, GitLab will run a background job that will produce
+ * pseudonymized CSVs of the GitLab database that will be uploaded to your
+ * configured object storage directory.
+ */
+ PSEUDONYMIZER_ENABLED(Boolean.class),
+
+ /**
+ * (If enabled, requires: recaptcha_private_key and recaptcha_site_key) Enable
+ * recaptcha.
+ */
+ RECAPTCHA_ENABLED(Boolean.class),
+
+ /** required by: recaptcha_enabled Private key for recaptcha. */
+ RECAPTCHA_PRIVATE_KEY(String.class),
+
+ /** required by: recaptcha_enabled Site key for recaptcha. */
+ RECAPTCHA_SITE_KEY(String.class),
+
+ /**
+ * GitLab will periodically run git fsck in all project and wiki repositories to
+ * look for silent disk corruption issues.
+ */
+ REPOSITORY_CHECKS_ENABLED(Boolean.class),
+
+ /** (Premium) Size limit per repository (MB) */
+ REPOSITORY_SIZE_LIMIT(Integer.class),
+
+ /**
+ * A list of names of enabled storage paths, taken from gitlab.yml. New projects
+ * will be created in one of these stores, chosen at random.
+ */
+ REPOSITORY_STORAGES(String[].class),
+
+ /**
+ * (If enabled, requires: two_factor_grace_period) Require all users to set up
+ * Two-factor authentication.
+ */
+ REQUIRE_TWO_FACTOR_AUTHENTICATION(Boolean.class),
+
+ /**
+ * Selected levels cannot be used by non-admin users for groups, projects or
+ * snippets. Can take private, internal and public as a parameter. Default is
+ * null which means there is no restriction.
+ */
+ RESTRICTED_VISIBILITY_LEVELS(String[].class),
+
+ /**
+ * The minimum allowed bit length of an uploaded RSA key. Default is 0 (no
+ * restriction). -1 disables RSA keys.
+ */
+ RSA_KEY_RESTRICTION(Integer.class),
+
+ /** Send confirmation email on sign-up. */
+ SEND_USER_CONFIRMATION_EMAIL(Boolean.class),
+
+ /** required by: sentry_enabled Sentry Data Source Name. */
+ SENTRY_DSN(String.class),
+
+ /**
+ * (If enabled, requires: sentry_dsn) Sentry is an error reporting and logging
+ * tool which is currently not shipped with GitLab, available at
+ * https://sentry.io.
+ */
+ SENTRY_ENABLED(Boolean.class),
+
+ /** Session duration in minutes. GitLab restart is required to apply changes */
+ SESSION_EXPIRE_DELAY(Integer.class),
+
+ /**
+ * (If enabled, requires: shared_runners_text and shared_runners_minutes)
+ * Enable shared runners for new projects.
+ */
+ SHARED_RUNNERS_ENABLED(Boolean.class),
+
+ /**
+ * required by: shared_runners_enabled (Premium) Set the maximum number of
+ * pipeline minutes that a group can use on shared Runners per month.
+ */
+ SHARED_RUNNERS_MINUTES(Integer.class),
+
+ /** required by: shared_runners_enabled Shared runners text. */
+ SHARED_RUNNERS_TEXT(String.class),
+
+ /** Text on the login page. */
+ SIGN_IN_TEXT(String.class),
+
+ /**
+ * (Deprecated: Use password_authentication_enabled_for_web instead) Flag
+ * indicating if password authentication is enabled for the web interface.
+ * Documentation lists this as a String, but it s a Boolean
+ */
+ SIGNIN_ENABLED(Boolean.class),
+
+ /** Enable registration. Default is true. */
+ SIGNUP_ENABLED(Boolean.class),
+
+ /**
+ * (Premium) (If enabled, requires: slack_app_id, slack_app_secret and
+ * slack_app_secret) Enable Slack app.
+ */
+ SLACK_APP_ENABLED(Boolean.class),
+
+ /**
+ * string required by: slack_app_enabled (Premium) The app id of the Slack-app.
+ */
+ SLACK_APP_ID(String.class),
+
+ /** required by: slack_app_enabled (Premium) The app secret of the Slack-app. */
+ SLACK_APP_SECRET(String.class),
+
+ /**
+ * required by: slack_app_enabled (Premium) The verification token of the
+ * Slack-app.
+ */
+ SLACK_APP_VERIFICATION_TOKEN(String.class),
+
+ /**
+ * Maximum time for web terminal websocket connection (in seconds). Set to 0 for
+ * unlimited time.
+ */
+ TERMINAL_MAX_SESSION_TIME(Integer.class),
+
+ /**
+ * required by: enforce_terms (Required by: enforce_terms) Markdown content for
+ * the ToS.
+ */
+ TERMS(String.class),
+
+ /**
+ * (If enabled, requires: throttle_authenticated_api_period_in_seconds and
+ * throttle_authenticated_api_requests_per_period) Enable authenticated API
+ * request rate limit. Helps reduce request volume (e.g. from crawlers or
+ * abusive bots).
+ */
+ THROTTLE_AUTHENTICATED_API_ENABLED(Boolean.class),
+
+ /**
+ * required by: throttle_authenticated_api_enabled Rate limit period in seconds.
+ */
+ THROTTLE_AUTHENTICATED_API_PERIOD_IN_SECONDS(Integer.class),
+
+ /**
+ * required by: throttle_authenticated_api_enabled Max requests per period per
+ * user.
+ */
+ THROTTLE_AUTHENTICATED_API_REQUESTS_PER_PERIOD(Integer.class),
+
+ /**
+ * (If enabled, requires: throttle_authenticated_web_period_in_seconds and
+ * throttle_authenticated_web_requests_per_period) Enable authenticated web
+ * request rate limit. Helps reduce request volume (e.g. from crawlers or
+ * abusive bots).
+ */
+ THROTTLE_AUTHENTICATED_WEB_ENABLED(Boolean.class),
+
+ /**
+ * required by: throttle_authenticated_web_enabled Rate limit period in seconds.
+ */
+ THROTTLE_AUTHENTICATED_WEB_PERIOD_IN_SECONDS(Integer.class),
+
+ /**
+ * required by: throttle_authenticated_web_enabled Max requests per period per
+ * user.
+ */
+ THROTTLE_AUTHENTICATED_WEB_REQUESTS_PER_PERIOD(Integer.class),
+
+ /**
+ * (If enabled, requires: throttle_unauthenticated_period_in_seconds and
+ * throttle_unauthenticated_requests_per_period) Enable unauthenticated request
+ * rate limit. Helps reduce request volume (e.g. from crawlers or abusive bots).
+ */
+ THROTTLE_UNAUTHENTICATED_ENABLED(Boolean.class),
+
+ /**
+ * required by: throttle_unauthenticated_enabled Rate limit period in seconds.
+ */
+ THROTTLE_UNAUTHENTICATED_PERIOD_IN_SECONDS(Integer.class),
+
+ /**
+ * required by: throttle_unauthenticated_enabled Max requests per period per IP.
+ */
+ THROTTLE_UNAUTHENTICATED_REQUESTS_PER_PERIOD(Integer.class),
+
+ /**
+ * required by: require_two_factor_authentication Amount of time (in hours) that
+ * users are allowed to skip forced configuration of two-factor authentication.
+ */
+ TWO_FACTOR_GRACE_PERIOD(Integer.class),
+
+ /**
+ * (If enabled, requires: unique_ips_limit_per_user and
+ * unique_ips_limit_time_window) Limit sign in from multiple ips.
+ */
+ UNIQUE_IPS_LIMIT_ENABLED(Boolean.class),
+
+ /**
+ * integer required by: unique_ips_limit_enabled Maximum number of ips per user.
+ */
+ UNIQUE_IPS_LIMIT_PER_USER(Integer.class),
+
+ /**
+ * required by: unique_ips_limit_enabled How many seconds an IP will be counted
+ * towards the limit.
+ */
+ UNIQUE_IPS_LIMIT_TIME_WINDOW(Integer.class),
+
+ /** Every week GitLab will report license usage back to GitLab, Inc. */
+ USAGE_PING_ENABLED(Boolean.class),
+
+ /** Newly registered users will be external by default. */
+ USER_DEFAULT_EXTERNAL(Boolean.class),
+
+ /**
+ * Allow users to register any application to use GitLab as an OAuth provider.
+ */
+ USER_OAUTH_APPLICATIONS(Boolean.class),
+
+ /**
+ * When set to false disable the “You won’t be able to pull or push project code
+ * via SSH” warning shown to users with no uploaded SSH key.
+ */
+ USER_SHOW_ADD_SSH_KEY_MESSAGE(Boolean.class),
+
+ /** Let GitLab inform you when an update is available. */
+ VERSION_CHECK_ENABLED(Boolean.class),
+
+ /* The following settings are undocumented, but are returned from the server */
+ ARCHIVE_BUILDS_IN_HUMAN_READABLE(Boolean.class),
+ DEFAULT_PROJECT_CREATION(Integer.class),
+ DOMAIN_BLACKLIST_RAW(String.class),
+ DOMAIN_WHITELIST_RAW(String.class),
+ RECEIVE_MAX_INPUT_SIZE(Integer.class),
+ USER_DEFAULT_INTERNAL_REGEX(String.class),
+ WEB_IDE_CLIENTSIDE_PREVIEW_ENABLED(Boolean.class),
+ DIFF_MAX_PATCH_BYTES(Integer.class),
+ COMMIT_EMAIL_HOSTNAME(String.class),
+ PROTECTED_CI_VARIABLES(Boolean.class),
+ PASSWORD_AUTHENTICATION_ENABLED(Boolean.class);
+
+ private static JacksonJsonEnumHelper enumHelper = new JacksonJsonEnumHelper<>(Setting.class);
+
+ private Class> type;
+ private Setting(Class> type) {
+ this.type = type;
+ }
+
+ public final Class> getType() {
+ return (type);
+ }
+
+ @JsonCreator
+ public static Setting forValue(String value) {
+ return enumHelper.forValue(value);
+ }
+
+ @JsonValue
+ public String toValue() {
+ return (enumHelper.toString(this));
+ }
+
+ @Override
+ public String toString() {
+ return (enumHelper.toString(this));
+ }
+
+ /**
+ * Returns true if the provided value is of the correct type specified by this ApplicationSetting enum,
+ * otherwise returns false.
+ *
+ * @param value the value to validate
+ * @return true if the value is of the correct type or null
+ */
+ public boolean isValid(Object value) {
+ return (value == null || value.getClass() == type);
+ }
+
+ /**
+ * Validates the provided value against the data type of this ApplicationSetting enum.
+ * Will throw a GitLabApiException if the value is not of the correct type.
+ *
+ * @param value the value to validate
+ * @throws GitLabApiException if the provided value is not a valid type for the ApplicationSetting
+ */
+ public final void validate(Object value) throws GitLabApiException {
+
+ if (isValid(value)) {
+ return;
+ }
+
+ String errorMsg = String.format("'%s' value is of incorrect type, is %s, should be %s",
+ toValue(), value.getClass().getSimpleName(), getType().getSimpleName());
+ throw new GitLabApiException(errorMsg);
+ }
+}
diff --git a/src/test/java/org/gitlab4j/api/TestApplicationSettingsApi.java b/src/test/java/org/gitlab4j/api/TestApplicationSettingsApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c42e208a5f3dc8c94387091650ea8046810427d
--- /dev/null
+++ b/src/test/java/org/gitlab4j/api/TestApplicationSettingsApi.java
@@ -0,0 +1,135 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Greg Messner
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.gitlab4j.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import static org.gitlab4j.api.models.Setting.LOCAL_MARKDOWN_VERSION;
+import org.gitlab4j.api.models.ApplicationSettings;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * In order for these tests to run you must set the following properties in test-gitlab4j.properties
+ *
+ * TEST_HOST_URL
+ * TEST_PRIVATE_TOKEN
+ *
+ * If any of the above are NULL, all tests in this class will be skipped.
+ */
+@Category(IntegrationTest.class)
+public class TestApplicationSettingsApi extends AbstractIntegrationTest {
+
+ private static GitLabApi gitLabApi;
+ private static Object savedLocalMarkdownVersion;
+ private static boolean fetchedApplicationSettings;
+
+ public TestApplicationSettingsApi() {
+ super();
+ }
+
+ @BeforeClass
+ public static void setup() {
+ // Must setup the connection to the GitLab test server
+ gitLabApi = baseTestSetup();
+
+ if (gitLabApi != null) {
+ try {
+ ApplicationSettings appSettings = gitLabApi.getApplicationSettingsApi().getApplicationSettings();
+ savedLocalMarkdownVersion = appSettings.getSetting(LOCAL_MARKDOWN_VERSION);
+ fetchedApplicationSettings = true;
+ } catch (Exception ignore) {}
+ }
+ }
+
+ @AfterClass
+ public static void teardown() {
+
+ if (fetchedApplicationSettings) {
+ try {
+ gitLabApi.getApplicationSettingsApi().updateApplicationSetting(
+ LOCAL_MARKDOWN_VERSION, savedLocalMarkdownVersion);
+ } catch (Exception ignore) {}
+ }
+ }
+
+ @Before
+ public void beforeMethod() {
+ assumeTrue(fetchedApplicationSettings);
+ }
+
+ @Test
+ public void testGetApplicationSettings() throws GitLabApiException {
+ ApplicationSettings appSettings = gitLabApi.getApplicationSettingsApi().getApplicationSettings();
+ assertNotNull(appSettings);
+ }
+
+ @Test
+ public void testUpdateApplicationSetting() throws GitLabApiException {
+
+ int newValue = (savedLocalMarkdownVersion != null ? ((Integer)savedLocalMarkdownVersion).intValue() + 1234 : 1234);
+ ApplicationSettings appSettings = gitLabApi.getApplicationSettingsApi().updateApplicationSetting(LOCAL_MARKDOWN_VERSION, newValue);
+ assertNotNull(appSettings);
+
+ Object updatedLocalMarkdownVersion = appSettings.getSetting(LOCAL_MARKDOWN_VERSION);
+ assertEquals(newValue, updatedLocalMarkdownVersion);
+
+ appSettings = gitLabApi.getApplicationSettingsApi().updateApplicationSetting(LOCAL_MARKDOWN_VERSION, savedLocalMarkdownVersion);
+ updatedLocalMarkdownVersion = appSettings.getSetting(LOCAL_MARKDOWN_VERSION);
+ assertEquals(savedLocalMarkdownVersion, updatedLocalMarkdownVersion);
+ }
+
+ @Test
+ public void testUpdateApplicationSettings() throws GitLabApiException {
+
+ // Arrange
+ int newValue = (savedLocalMarkdownVersion != null ? ((Integer)savedLocalMarkdownVersion).intValue() + 123 : 123);
+ ApplicationSettings appSettings = new ApplicationSettings();
+ appSettings.addSetting(LOCAL_MARKDOWN_VERSION, newValue);
+
+ // Act
+ ApplicationSettings updatedAppSettings = gitLabApi.getApplicationSettingsApi().updateApplicationSettings(appSettings);
+
+ // Assert
+ assertNotNull(updatedAppSettings);
+ Object updatedLocalMarkdownVersion = updatedAppSettings.getSetting(LOCAL_MARKDOWN_VERSION);
+ assertEquals(newValue, updatedLocalMarkdownVersion);
+
+ // Arrange
+ appSettings = new ApplicationSettings();
+ appSettings.addSetting(LOCAL_MARKDOWN_VERSION, savedLocalMarkdownVersion);
+
+ // Act
+ updatedAppSettings = gitLabApi.getApplicationSettingsApi().updateApplicationSettings(appSettings);
+
+ // Assert
+ updatedLocalMarkdownVersion = updatedAppSettings.getSetting(LOCAL_MARKDOWN_VERSION);
+ assertEquals(savedLocalMarkdownVersion, updatedLocalMarkdownVersion);
+ }
+}
diff --git a/src/test/java/org/gitlab4j/api/TestApplications.java b/src/test/java/org/gitlab4j/api/TestApplicationsApi.java
similarity index 100%
rename from src/test/java/org/gitlab4j/api/TestApplications.java
rename to src/test/java/org/gitlab4j/api/TestApplicationsApi.java