diff --git a/ui/src/Components/AlertAck/index.js b/ui/src/Components/AlertAck/index.js
index 11e6d64a6..0db2fb741 100644
--- a/ui/src/Components/AlertAck/index.js
+++ b/ui/src/Components/AlertAck/index.js
@@ -172,6 +172,20 @@ const AlertAck = observer(
return;
}
+ let author =
+ alertStore.settings.values.silenceForm.author !== ""
+ ? alertStore.settings.values.silenceForm.author
+ : silenceFormStore.data.author !== ""
+ ? toJS(silenceFormStore.data.author)
+ : toJS(alertStore.settings.values.alertAcknowledgement.author);
+
+ if (alertStore.info.authentication.enabled) {
+ silenceFormStore.data.author = toJS(
+ alertStore.info.authentication.username
+ );
+ author = alertStore.info.authentication.username;
+ }
+
const alertmanagers = Object.entries(group.alertmanagerCount)
.filter(([amName, alertCount]) => alertCount > 0)
.map(([amName, _]) => amName);
@@ -187,11 +201,7 @@ const AlertAck = observer(
toJS(group),
toJS(clusterMembers),
toJS(alertStore.settings.values.alertAcknowledgement.durationSeconds),
- alertStore.settings.values.silenceForm.author !== ""
- ? alertStore.settings.values.silenceForm.author
- : silenceFormStore.data.author !== ""
- ? toJS(silenceFormStore.data.author)
- : toJS(alertStore.settings.values.alertAcknowledgement.author),
+ author,
toJS(alertStore.settings.values.alertAcknowledgement.commentPrefix)
);
this.submitState.pushSilence(clusterName, pendingSilence);
diff --git a/ui/src/Components/AlertAck/index.test.js b/ui/src/Components/AlertAck/index.test.js
index 4a6020cfd..14f04daa7 100644
--- a/ui/src/Components/AlertAck/index.test.js
+++ b/ui/src/Components/AlertAck/index.test.js
@@ -189,6 +189,27 @@ describe("", () => {
});
});
+ it("uses author from authentication info when auth is enabled", () => {
+ alertStore.info.authentication.enabled = true;
+ alertStore.info.authentication.username = "auth@example.com";
+ alertStore.settings.values.silenceForm.author = "john@example.com";
+ alertStore.settings.values.alertAcknowledgement.durationSeconds = 222;
+ alertStore.settings.values.alertAcknowledgement.author = "me";
+ alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:";
+ MountAndClick();
+ expect(JSON.parse(fetch.mock.calls[0][1].body)).toEqual({
+ comment:
+ "FOO: This alert was acknowledged using karma on Tue Feb 01 2000 00:00:00 GMT+0000",
+ createdBy: "auth@example.com",
+ endsAt: "2000-02-01T00:03:42.000Z",
+ matchers: [
+ { isRegex: false, name: "alertname", value: "Fake Alert" },
+ { isRegex: true, name: "foo", value: "(bar|baz)" }
+ ],
+ startsAt: "2000-02-01T00:00:00.000Z"
+ });
+ });
+
it("uses author from alertStore if present", () => {
alertStore.settings.values.silenceForm.author = "john@example.com";
alertStore.settings.values.alertAcknowledgement.durationSeconds = 222;
diff --git a/ui/src/Components/SilenceModal/AuthorInput.js b/ui/src/Components/SilenceModal/AuthorInput.js
new file mode 100644
index 000000000..c7a147e9e
--- /dev/null
+++ b/ui/src/Components/SilenceModal/AuthorInput.js
@@ -0,0 +1,59 @@
+import React from "react";
+import PropTypes from "prop-types";
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faUser } from "@fortawesome/free-solid-svg-icons/faUser";
+
+import { AlertStore } from "Stores/AlertStore";
+
+const IconInput = ({
+ type,
+ autoComplete,
+ icon,
+ placeholder,
+ value,
+ onChange,
+ ...extra
+}) => (
+
+);
+IconInput.propTypes = {
+ type: PropTypes.string.isRequired,
+ autoComplete: PropTypes.string.isRequired,
+ icon: FontAwesomeIcon.propTypes.icon.isRequired,
+ placeholder: PropTypes.string.isRequired,
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func
+};
+
+const AuthenticatedAuthorInput = ({ alertStore }) => (
+
+);
+AuthenticatedAuthorInput.propTypes = {
+ alertStore: PropTypes.instanceOf(AlertStore).isRequired
+};
+
+export { IconInput, AuthenticatedAuthorInput };
diff --git a/ui/src/Components/SilenceModal/SilenceForm.js b/ui/src/Components/SilenceModal/SilenceForm.js
index 511f9a8be..e6a72dfe3 100644
--- a/ui/src/Components/SilenceModal/SilenceForm.js
+++ b/ui/src/Components/SilenceModal/SilenceForm.js
@@ -21,40 +21,7 @@ import { AlertManagerInput } from "./AlertManagerInput";
import { SilenceMatch } from "./SilenceMatch";
import { DateTimeSelect } from "./DateTimeSelect";
import { PayloadPreview } from "./PayloadPreview";
-
-const IconInput = ({
- type,
- autoComplete,
- icon,
- placeholder,
- value,
- onChange
-}) => (
-
-);
-IconInput.propTypes = {
- type: PropTypes.string.isRequired,
- autoComplete: PropTypes.string.isRequired,
- icon: FontAwesomeIcon.propTypes.icon.isRequired,
- placeholder: PropTypes.string.isRequired,
- value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired
-};
+import { IconInput, AuthenticatedAuthorInput } from "./AuthorInput";
const SilenceForm = observer(
class SilenceForm extends Component {
@@ -111,6 +78,10 @@ const SilenceForm = observer(
silenceFormStore.data.author =
settingsStore.silenceFormConfig.config.author;
}
+
+ if (alertStore.info.authentication.enabled) {
+ silenceFormStore.data.author = alertStore.info.authentication.username;
+ }
});
addMore = action(event => {
@@ -177,14 +148,19 @@ const SilenceForm = observer(
-
+ {alertStore.info.authentication.enabled ? (
+
+ ) : (
+
+ )}
+
preview", () => {
});
describe(" inputs", () => {
+ it("author is read-only when info.authentication.enabled is true", () => {
+ alertStore.info.authentication.enabled = true;
+ alertStore.info.authentication.username = "auth@example.com";
+ const tree = MountedSilenceForm();
+ const input = tree.find("input[placeholder='Author']");
+ expect(input.props().readOnly).toBe(true);
+ expect(input.props().value).toBe("auth@example.com");
+ expect(silenceFormStore.data.author).toBe("auth@example.com");
+ });
+
it("default author value comes from Settings store", () => {
settingsStore.silenceFormConfig.config.author = "foo@example.com";
const tree = MountedSilenceForm();
diff --git a/ui/src/Stores/AlertStore.js b/ui/src/Stores/AlertStore.js
index 610b6e141..9bbffedad 100644
--- a/ui/src/Stores/AlertStore.js
+++ b/ui/src/Stores/AlertStore.js
@@ -215,6 +215,10 @@ class AlertStore {
info = observable(
{
+ authentication: {
+ enabled: false,
+ username: ""
+ },
totalAlerts: 0,
version: "unknown",
upgradeNeeded: false,
@@ -418,7 +422,7 @@ class AlertStore {
this.info.upgradeNeeded = true;
}
// update extra root level keys that are stored under 'info'
- for (const key of ["totalAlerts", "version"]) {
+ for (const key of ["totalAlerts", "version", "authentication"]) {
if (this.info[key] !== result[key]) {
this.info[key] = result[key];
}