mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
feat(ui): enforce username from credentials if auth is enabled
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -189,6 +189,27 @@ describe("<AlertAck />", () => {
|
||||
});
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
}) => (
|
||||
<div className="input-group mb-3">
|
||||
<div className="input-group-prepend">
|
||||
<span className="input-group-text">
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
type={type}
|
||||
className="form-control"
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
required
|
||||
autoComplete={autoComplete}
|
||||
onChange={onChange}
|
||||
{...extra}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
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 }) => (
|
||||
<IconInput
|
||||
type="text"
|
||||
autoComplete="email"
|
||||
placeholder="Author"
|
||||
icon={faUser}
|
||||
value={alertStore.info.authentication.username}
|
||||
readOnly={true}
|
||||
/>
|
||||
);
|
||||
AuthenticatedAuthorInput.propTypes = {
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired
|
||||
};
|
||||
|
||||
export { IconInput, AuthenticatedAuthorInput };
|
||||
@@ -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
|
||||
}) => (
|
||||
<div className="input-group mb-3">
|
||||
<div className="input-group-prepend">
|
||||
<span className="input-group-text">
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
type={type}
|
||||
className="form-control"
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
required
|
||||
autoComplete={autoComplete}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
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(
|
||||
</button>
|
||||
</TooltipWrapper>
|
||||
<DateTimeSelect silenceFormStore={silenceFormStore} />
|
||||
<IconInput
|
||||
type="text"
|
||||
autoComplete="email"
|
||||
placeholder="Author"
|
||||
icon={faUser}
|
||||
value={silenceFormStore.data.author}
|
||||
onChange={this.onAuthorChange}
|
||||
/>
|
||||
{alertStore.info.authentication.enabled ? (
|
||||
<AuthenticatedAuthorInput alertStore={alertStore} />
|
||||
) : (
|
||||
<IconInput
|
||||
type="text"
|
||||
autoComplete="email"
|
||||
placeholder="Author"
|
||||
icon={faUser}
|
||||
value={silenceFormStore.data.author}
|
||||
onChange={this.onAuthorChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
<IconInput
|
||||
type="text"
|
||||
autoComplete="on"
|
||||
|
||||
@@ -127,6 +127,16 @@ describe("<SilenceForm /> preview", () => {
|
||||
});
|
||||
|
||||
describe("<SilenceForm /> 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();
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user