in gui/frontend/src/modules/mrs/dialogs/MrsConfigurationDialog.tsx [114:441]
private dialogValues(request: IDialogRequest): IDialogValues {
if (request.values) {
const values = request.values as IMrsConfigurationDialogData;
const status = request.parameters?.status as IMrsStatusData;
const versions = request.parameters?.versionsAvailable as string[] ?? [values.version];
const showUpdateSelection = !request.parameters?.init && !request.parameters?.isCloudInstance
&& status.serviceUpgradeable;
// Ensure that the version is actually in the list of available versions.
if (!versions.includes(values.version)) {
versions.push(values.version);
}
const mainSection: IDialogSection = {
caption: request.title,
values: {
enabled: {
type: "choice",
caption: "MySQL REST Service Status",
choices: ["Enabled", "Disabled"],
value: values.enabled ? "Enabled" : "Disabled",
horizontalSpan: 3,
description: "If set to disabled, all MySQL REST Service endpoints will be disabled.",
},
version: {
type: "choice",
caption: request.parameters?.init ? "Version" : "Current Version",
choices: versions,
value: values.version,
horizontalSpan: 2,
options: request.parameters?.init ? [] : [
CommonDialogValueOption.Disabled,
],
description: "The version of the MySQL REST Service metadata schema.",
},
},
};
// Do not show the upgrade checkbox during initial configuration and
// do not show it for cloud instances
if (showUpdateSelection) {
const updateToVersions = versions.slice();
const currentVersionIndex = updateToVersions.indexOf(values.version);
if (currentVersionIndex > -1) {
updateToVersions.length = currentVersionIndex;
}
updateToVersions.push("No Update");
mainSection.values.updateToVersion = {
type: "choice",
caption: "Update to Version",
choices: updateToVersions,
value: updateToVersions[0],
horizontalSpan: 3,
description: "The version to update to MySQL REST Service metadata schema to.",
};
} else if (request.parameters?.init) {
mainSection.values.info = {
type: "description",
caption: "The MySQL REST Service will be configured using the selected version.",
horizontalSpan: 3,
};
} else if (request.parameters?.isCloudInstance) {
mainSection.values.info = {
type: "description",
caption: "Version upgrades for this instance are managed by the cloud vendor.",
horizontalSpan: 3,
};
} else if (status.serviceUpgradeIgnored) {
mainSection.values.info = {
type: "description",
caption: "The current MySQL REST Service update is being skipped.",
horizontalSpan: 3,
};
} else {
mainSection.values.info = {
type: "description",
caption: "The MySQL REST Service metadata schema is up to date.",
horizontalSpan: 3,
};
}
const authSection: IDialogSection = {
contexts: ["init"],
caption: "Authentication",
groupName: "group1",
values: {
mrsAdminCreation: {
type: "boolean",
caption: "Create default REST authentication app",
value: true,
description: "Select this option to create a REST authentication app using the built-in MRS "
+ "vendor. REST authentication apps are required to allow end users to login into the "
+ "MySQL REST Service and access REST endpoints that require authentication.",
horizontalSpan: 8,
},
mrsAdminUser: {
type: "text",
caption: "REST User Name",
value: "",
horizontalSpan: 4,
description: "The user name of the REST user account. This account will be enabled to login "
+ "into the MySQL REST Service and access all REST endpoints of the linked REST services.",
options: [
CommonDialogValueOption.AutoFocus,
],
},
mrsAdminUserPassword: {
type: "text",
caption: "REST User Password",
obfuscated: true,
value: "",
horizontalSpan: 4,
description: "The password of the REST user account.",
},
},
};
const authThrottlingSection: IDialogSection = {
contexts: ["config"],
caption: "Authentication Throttling",
groupName: "group1",
values: {
throttlingPerAccountSep: {
type: "separator",
caption: "Per-Account Throttling",
horizontalSpan: 3,
},
throttlingPerHostSep: {
type: "separator",
caption: "Per-Host Throttling",
horizontalSpan: 3,
},
throttlingSep: {
type: "separator",
caption: "Throttling General",
horizontalSpan: 2,
},
perAccountMinimumTimeBetweenRequestsInMs: {
type: "number",
caption: "Minimum Time Between Requests",
value: values.options.authentication?.throttling?.perAccount?.minimumTimeBetweenRequestsInMs,
placeholder: 1500,
horizontalSpan: 3,
description: "Sets the minimum time between connection attempts. The value is given in "
+ "milliseconds.",
},
perHostMinimumTimeBetweenRequestsInMs: {
type: "number",
caption: "Minimum Time Between Requests",
value: values.options.authentication?.throttling?.perHost?.minimumTimeBetweenRequestsInMs,
placeholder: 1500,
horizontalSpan: 3,
description: "Sets the minimum time between connection attempts for a give host. The value is "
+ "given in ms.",
},
blockWhenAttemptsExceededInSeconds: {
type: "number",
caption: "Block Timeout",
value: values.options.authentication?.throttling?.blockWhenAttemptsExceededInSeconds,
placeholder: 120,
horizontalSpan: 2,
verticalSpan: 2,
description: "Sets the amount of time the account or client host will be blocked from "
+ "authentication. The value is given in seconds.",
},
perAccountMaximumAttemptsPerMinute: {
type: "number",
caption: "Maximum Attempts Per Minute",
value: values.options.authentication?.throttling?.perAccount?.maximumAttemptsPerMinute,
placeholder: 5,
horizontalSpan: 3,
description: "Sets the maximum amount of attempts per minute per client. "
+ "Further attempts will be blocked.",
},
perHostMaximumAttemptsPerMinute: {
type: "number",
caption: "Maximum Attempts Per Minute",
value: values.options.authentication?.throttling?.perHost?.maximumAttemptsPerMinute,
placeholder: 5,
horizontalSpan: 3,
description: "Sets the maximum amount of attempts per minute for a given host.",
},
},
};
delete values.options.authentication;
const cacheSection: IDialogSection = {
contexts: ["config"],
caption: "Caches",
groupName: "group1",
values: {
responseCacheMaxCacheSize: {
type: "text",
caption: "Endpoint Response Cache",
value: values.options.responseCache?.maxCacheSize
? values.options.responseCache?.maxCacheSize
: "",
horizontalSpan: 4,
description: "Global options for the REST endpoint response cache, which keeps an in-memory "
+ "cache of responses to GET requests on tables, views, procedures and functions. To "
+ "enable caching of an endpoint, you must also set the cacheTimeToLive option for each "
+ "object to be cached.",
placeholder: "1M",
},
fileCacheMaxCacheSize: {
type: "text",
caption: "Static File Cache",
value: values.options.fileCache?.maxCacheSize
? values.options.fileCache?.maxCacheSize
: "",
horizontalSpan: 4,
description: "Global options for the static file data cache, which keeps an in-memory cache "
+ "of responses to GET requests on content set files. Maximum size of the cache. Default "
+ "is 1M.",
placeholder: "1M",
},
gtidCacheEnable: {
type: "boolean",
caption: "GTID Cache",
value: values.options.gtid?.cache?.enable ?? false,
horizontalSpan: 2,
description: "Enables the Global Transaction Id (GTID) cache. GTIDs are used to "
+ "ensure a given commit can be read on secondary instances.",
},
gtidCacheRefreshRate: {
type: "number",
caption: "Refresh Rate",
value: values.options.gtid?.cache?.refreshRate,
horizontalSpan: 3,
description: "Defines how often the GTID cache will be refreshed on MySQL Router instances. "
+ "The value has to be set in seconds, e.g. 5.",
},
gtidCacheRefreshWhenIncreasesBy: {
type: "number",
caption: "Refresh When Increased",
value: values.options.gtid?.cache?.refreshWhenIncreasesBy,
horizontalSpan: 3,
description: "In addition to the time based refresh, the GTID cache can also be refreshed "
+ "based on the number of transactions that happened since the last refresh. Set in number "
+ "of transactions, e.g. 500.",
},
},
};
delete values.options.responseCache;
delete values.options.fileCache;
delete values.options.gtid;
const contentRedirectSection: IDialogSection = {
contexts: ["config"],
caption: "Redirects & Static Content",
groupName: "group1",
values: {
directoryIndexDirective: {
type: "set",
caption: "Endpoint Response Cache",
value: values.options.directoryIndexDirective,
tagSet: values.options.directoryIndexDirective ?? ["index.html"],
horizontalSpan: 8,
description: "Holds an ordered list of files that should be returned when a directory path "
+ "has been requested. The first matching file that is available will be returned.",
},
defaultStaticContent: {
type: "matrix",
caption: "Endpoint Response Cache",
value: values.options.defaultStaticContent,
horizontalSpan: 4,
description: "Allows the definition of static content for the root path / that will be "
+ "returned for file paths matching the given JSON keys. A JSON key index.html will be "
+ "served as /index.html by the MySQL Router.",
},
defaultRedirects: {
type: "matrix",
caption: "Default Redirects",
value: values.options.defaultRedirects,
horizontalSpan: 4,
description: "Is used to define internal redirects performed by the MySQL Router. This "
+ "can be used to expose content of a REST service on the root path /. A JSON key "
+ "index.html holding the value /myService/myContentSet/index.html will exposed the "
+ "corresponding file from the given path as /index.html.",
},
},
};
delete values.options.directoryIndexDirective;
delete values.options.defaultStaticContent;
delete values.options.defaultRedirects;
let optionsStr = JSON.stringify(values.options);
if (optionsStr === "{}") {
optionsStr = "";
}
const optionsSection: IDialogSection = {
contexts: ["config"],
caption: "Options",
groupName: "group1",
values: {
options: {
type: "text",
caption: "Options:",
value: optionsStr,
horizontalSpan: 8,
multiLine: true,
multiLineCount: 12,
description: "Additional options in JSON format",
},
},
};
return {
id: "mainSection",
sections: new Map<string, IDialogSection>([
["mainSection", mainSection],
["authSection", authSection],
["authThrottlingSection", authThrottlingSection],
["cacheSection", cacheSection],
["contentRedirectSection", contentRedirectSection],
["optionsSection", optionsSection],
]),
};
} else {
return { id: "", sections: new Map<string, IDialogSection>([]) };
}
}