Team policy automation (#5004)

* added teams webhook calls

* split global admin and team admin tests; added policy automation

* changes file

* fixed type errors

* fixed e2e test

* fixed typo

* fixed admin test syntax

* fixed test logic for team maintainer

* lint fixes

* more admin e2e test fixes

* fixed team policy test

* removed duplicate test
This commit is contained in:
Martavis Parker 2022-04-11 14:46:35 -07:00 committed by GitHub
parent 2eeb9142b3
commit 3a326cd0ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 756 additions and 682 deletions

View file

@ -0,0 +1 @@
- Added policy automation for teams

View file

@ -1,4 +1,4 @@
describe("Premium tier - Admin user", () => {
describe("Premium tier - Global Admin user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
@ -14,668 +14,282 @@ describe("Premium tier - Admin user", () => {
cy.stopDockerHost();
});
describe("Global admin", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", "user123#");
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended global admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/organization/i).should("exist");
});
cy.getAttached(".site-nav-container").within(() => {
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/users/i).should("exist");
});
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", "user123#");
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended global admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).click();
});
});
// Global Admin dashboard tested in integration/free/admin.spec.ts
// Team Admin dashboard tested below in integration/premium/admin.spec.ts
describe("Manage hosts page", () => {
beforeEach(() => cy.visit("/hosts/manage"));
it("displays team column in hosts table", () => {
cy.getAttached(".data-table__table th")
.contains("Team")
.should("be.visible");
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/organization/i).should("exist");
});
it("allows global admin to see and click 'Add hosts'", () => {
cy.getAttached(".button-wrap")
.contains("button", /add hosts/i)
.click();
cy.getAttached(".modal__content").contains("button", /done/i).click();
cy.getAttached(".site-nav-container").within(() => {
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).click();
});
it("allows global admin to add new enroll secret", () => {
cy.getAttached(".button-wrap")
.contains("button", /manage enroll secret/i)
.click();
cy.getAttached(".enroll-secret-modal__add-secret")
.contains("button", /add secret/i)
.click();
cy.getAttached(".secret-editor-modal__button-wrap")
.contains("button", /save/i)
.click();
cy.getAttached(".enroll-secret-modal__button-wrap")
.contains("button", /done/i)
.click();
});
});
describe("Host details page", () => {
beforeEach(() => cy.visit("hosts/2"));
it("allows global admin to transfer host to an existing team", () => {
cy.getAttached(".host-details__transfer-button").click();
cy.findByText(/create a team/i).should("exist");
cy.getAttached(".Select-control").click();
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/oranges/i).should("exist");
cy.findByText(/apples/i).click();
});
cy.getAttached(".transfer-host-modal__button-wrap")
.contains("button", /transfer/i)
.click();
cy.findByText(/transferred to apples/i).should("exist");
cy.findByText(/team/i).next().contains("Apples");
});
it("allows global admin to create an operating system policy", () => {
cy.getAttached(".info-flex").within(() => {
cy.findByText(/ubuntu/i).should("exist");
cy.getAttached(".host-summary__os-policy-button").click();
});
cy.getAttached(".modal__content")
.findByRole("button", { name: /create new policy/i })
.should("exist");
});
it("allows global admin to create a custom query", () => {
cy.getAttached(".host-details__query-button").click();
cy.contains("button", /create custom query/i).should("exist");
cy.getAttached(".modal__ex").click();
});
it("allows global admin to delete a host", () => {
cy.getAttached(".host-details__action-button-container")
.contains("button", /delete/i)
.click();
cy.getAttached(".delete-host-modal__modal").within(() => {
cy.findByText(/delete host/i).should("exist");
cy.contains("button", /delete/i).should("exist");
cy.getAttached(".modal__ex").click();
});
});
});
describe("Manage software page", () => {
beforeEach(() => cy.visit("/software/manage"));
it("allows global admin to create webhook software vulnerability automation", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByRole("button", { name: /manage automations/i }).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached("#webhook-radio-btn").next().click();
});
cy.getAttached("#webhook-url").click().type("www.foo.com/bar");
cy.findByRole("button", { name: /^Save$/ }).click();
// Confirm manage automations webhook was added successfully
cy.findByText(/updated vulnerability automations/i).should("exist");
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.getAttached("#webhook-url").should("exist");
});
});
it("hides manage automations button since all teams not selected", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.getAttached(".Select").within(() => {
cy.findByText(/all teams/i).click();
cy.findByText(/apples/i).click();
});
cy.findByText(/manage automations/i).should("not.exist");
});
});
});
describe("Query pages", () => {
beforeEach(() => cy.visit("/queries/manage"));
it("allows global admin to select teams targets for query", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".query-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).click();
});
cy.contains("h3", /teams/i).should("exist");
cy.contains(".selector-name", /apples/i).should("exist");
});
});
// Global Admin schedule tested in integration/free/admin.spec.ts
// Team Admin team schedule tested below in integration/premium/admin.spec.ts
describe("Manage policies page", () => {
beforeEach(() => cy.visit("/policies/manage"));
it("allows global admin to click 'Manage automations' button", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /manage automations/i })
.click();
cy.findByRole("button", { name: /cancel/i }).click();
});
it("allows global admin to add a new policy", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /add a policy/i })
.click();
// Add a default policy
cy.findByText(/gatekeeper enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save policy/i }).click();
});
cy.findByRole("button", { name: /^Save$/ }).click();
cy.findByText(/policy created/i).should("exist");
cy.findByText(/gatekeeper enabled/i).should("exist");
});
it("allows global admin to delete a team policy", () => {
cy.visit("/policies/manage");
cy.getAttached(".Select-control").within(() => {
cy.findByText(/all teams/i).click();
});
cy.getAttached(".Select-menu")
.contains(/apples/i)
.click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".remove-policies-modal").within(() => {
cy.findByRole("button", { name: /delete/i }).should("exist");
cy.findByRole("button", { name: /cancel/i }).click();
});
});
it("allows global admin to edit a team policy", () => {
cy.visit("policies/manage");
cy.findByText(/all teams/i).click();
cy.findByText(/apples/i).click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByText(/filevault enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).should("exist");
});
});
});
describe("Admin settings page", () => {
beforeEach(() => cy.visit("/settings/organization"));
it("allows global admin to access team settings", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/teams/i).click();
});
// Access the Settings - Team details page
cy.getAttached("tbody").within(() => {
cy.findByText(/apples/i).click();
});
cy.findByText(/apples/i).should("exist");
cy.findByText(/manage users with global access here/i).should("exist");
});
it("displays the 'Team' section in the create user modal", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click();
cy.findByText(/assign teams/i).should("exist");
});
it("allows global admin to edit existing user password", () => {
cy.visit("/settings/users");
cy.getAttached("tbody").within(() => {
cy.findByText(/oliver@organization.com/i)
.parent()
.next()
.within(() => cy.getAttached(".Select-placeholder").click());
});
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/edit/i).click();
});
cy.getAttached(".create-user-form").within(() => {
cy.findByLabelText(/email/i).should("exist");
cy.findByLabelText(/password/i).should("exist");
});
});
});
describe("User profile page", () => {
it("renders elements according to role-based access controls", () => {
cy.visit("/profile");
cy.getAttached(".user-settings__additional").within(() => {
cy.findByText(/team/i)
.next()
.contains(/global/i);
cy.findByText("Role").next().contains(/admin/i);
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/users/i).should("exist");
});
});
});
describe("Team admin", () => {
beforeEach(() => {
cy.loginWithCySession("anita@organization.com", "user123#");
// Global Admin dashboard tested in integration/free/admin.spec.ts
// Team Admin dashboard tested below in integration/premium/admin.spec.ts
describe("Manage hosts page", () => {
beforeEach(() => cy.visit("/hosts/manage"));
it("displays team column in hosts table", () => {
cy.getAttached(".data-table__table th")
.contains("Team")
.should("be.visible");
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended team admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).should("not.exist");
cy.findByText(/settings/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/members/i).should("exist");
});
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/agent options/i).should("exist");
});
it("allows global admin to see and click 'Add hosts'", () => {
cy.getAttached(".button-wrap")
.contains("button", /add hosts/i)
.click();
cy.getAttached(".modal__content").contains("button", /done/i).click();
});
it("allows global admin to add new enroll secret", () => {
cy.getAttached(".button-wrap")
.contains("button", /manage enroll secret/i)
.click();
cy.getAttached(".enroll-secret-modal__add-secret")
.contains("button", /add secret/i)
.click();
cy.getAttached(".secret-editor-modal__button-wrap")
.contains("button", /save/i)
.click();
cy.getAttached(".enroll-secret-modal__button-wrap")
.contains("button", /done/i)
.click();
});
});
describe("Host details page", () => {
beforeEach(() => cy.visit("hosts/2"));
it("allows global admin to transfer host to an existing team", () => {
cy.getAttached(".host-details__transfer-button").click();
cy.findByText(/create a team/i).should("exist");
cy.getAttached(".Select-control").click();
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/oranges/i).should("exist");
cy.findByText(/apples/i).click();
});
cy.getAttached(".transfer-host-modal__button-wrap")
.contains("button", /transfer/i)
.click();
cy.findByText(/transferred to apples/i).should("exist");
cy.findByText(/team/i).next().contains("Apples");
});
it("allows global admin to create an operating system policy", () => {
cy.getAttached(".info-flex").within(() => {
cy.findByText(/ubuntu/i).should("exist");
cy.getAttached(".host-summary__os-policy-button").click();
});
cy.getAttached(".modal__content")
.findByRole("button", { name: /create new policy/i })
.should("exist");
});
it("allows global admin to create a custom query", () => {
cy.getAttached(".host-details__query-button").click();
cy.contains("button", /create custom query/i).should("exist");
cy.getAttached(".modal__ex").click();
});
it("allows global admin to delete a host", () => {
cy.getAttached(".host-details__action-button-container")
.contains("button", /delete/i)
.click();
cy.getAttached(".delete-host-modal__modal").within(() => {
cy.findByText(/delete host/i).should("exist");
cy.contains("button", /delete/i).should("exist");
cy.getAttached(".modal__ex").click();
});
});
describe("Dashboard", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays cards for all platforms", () => {
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
cy.getAttached(".home-software").should("exist");
cy.get(".activity-feed").should("not.exist");
});
});
describe("Manage software page", () => {
beforeEach(() => cy.visit("/software/manage"));
it("allows global admin to create webhook software vulnerability automation", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByRole("button", { name: /manage automations/i }).click();
});
it("displays cards for windows only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/windows/i).click();
});
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached("#webhook-radio-btn").next().click();
});
it("displays cards for linux only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/linux/i).click();
});
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
});
cy.getAttached("#webhook-url").click().type("www.foo.com/bar");
cy.findByRole("button", { name: /^Save$/ }).click();
// Confirm manage automations webhook was added successfully
cy.findByText(/updated vulnerability automations/i).should("exist");
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
it("displays cards for macOS only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/macos/i).click();
});
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
cy.getAttached(".home-munki").should("exist");
cy.getAttached(".home-mdm").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
});
});
it("views all hosts for all platforms", () => {
cy.findByText(/view all hosts/i).click();
cy.get(".manage-hosts__label-block").should("not.exist");
});
it("views all hosts for windows only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/windows/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.getAttached(".manage-hosts__label-block").within(() => {
cy.getAttached(".title").within(() => {
cy.findByText(/windows/i).should("exist");
});
});
});
it("views all hosts for linux only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/linux/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.getAttached(".manage-hosts__label-block").within(() => {
cy.getAttached(".title").within(() => {
cy.findByText(/linux/i).should("exist");
});
});
});
it("views all hosts for macOS only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/macos/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.getAttached(".manage-hosts__label-block").within(() => {
cy.getAttached(".title").within(() => {
cy.findByText(/macos/i).should("exist");
});
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.getAttached("#webhook-url").should("exist");
});
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.visit("/hosts/manage");
});
it("displays team column in hosts table", () => {
cy.getAttached(".data-table__table th")
.contains("Team")
.should("be.visible");
});
it("allows team admin to see and click 'Add hosts'", () => {
cy.getAttached(".button-wrap")
.contains("button", /add hosts/i)
.click();
cy.getAttached(".modal__content").contains("button", /done/i).click();
});
it("allows team admin to add new enroll secret", () => {
cy.getAttached(".button-wrap")
.contains("button", /manage enroll secret/i)
.click();
cy.getAttached(".enroll-secret-modal__add-secret")
.contains("button", /add secret/i)
.click();
cy.getAttached(".secret-editor-modal__button-wrap")
.contains("button", /save/i)
.click();
cy.getAttached(".enroll-secret-modal__button-wrap")
.contains("button", /done/i)
.click();
});
});
describe("Host details page", () => {
beforeEach(() => cy.visit("hosts/1"));
it("allows team admin to create an operating system policy", () => {
cy.getAttached(".info-flex").within(() => {
cy.findByText(/ubuntu/i).should("exist");
cy.getAttached(".host-summary__os-policy-button").click();
});
cy.getAttached(".modal__content")
.findByRole("button", { name: /create new policy/i })
.should("exist");
});
it("allows team admin to query host but not transfer host", () => {
cy.getAttached(".host-details__query-button").should("exist");
cy.findByText(/transfer/i).should("not.exist");
});
it("allows team admin to delete a host", () => {
cy.getAttached(".host-details__action-button-container")
.contains("button", /delete/i)
.click();
cy.getAttached(".delete-host-modal__modal").within(() => {
cy.findByText(/delete host/i).should("exist");
cy.contains("button", /delete/i).should("exist");
cy.getAttached(".modal__ex").click();
});
});
});
describe("Manage software page", () => {
beforeEach(() => cy.visit("/software/manage"));
it("hides manage automations button since all teams not selected", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByText(/apples/i).should("exist");
it("hides manage automations button since all teams not selected", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.getAttached(".Select").within(() => {
cy.findByText(/all teams/i).click();
cy.findByText(/apples/i).click();
});
cy.findByText(/manage automations/i).should("not.exist");
});
});
describe("Query pages", () => {
beforeEach(() => cy.visit("/queries/manage"));
it("allows team admin to select teams targets for query", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".query-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).click();
});
cy.contains("h3", /teams/i).should("exist");
cy.contains(".selector-name", /apples/i).should("exist");
});
it("disables team admin from deleting or editing a query not authored by them", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").should("be.disabled");
});
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".query-form__save").should("be.disabled");
});
});
describe("Manage schedules page", () => {
beforeEach(() => {
cy.visit("/schedule/manage");
});
it("hides advanced button when team admin", () => {
cy.getAttached(".manage-schedule-page__header-wrap").within(() => {
cy.findByText(/apples/i).should("exist");
});
cy.findByText(/advanced/i).should("not.exist");
});
it("creates a new team scheduled query", () => {
cy.getAttached(".no-schedule__schedule-button").click();
cy.getAttached(".schedule-editor-modal__form").within(() => {
cy.findByText(/select query/i).click();
cy.findByText(/detect presence/i).click();
cy.getAttached(".schedule-editor-modal__btn-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).click();
});
});
cy.findByText(/successfully added/i).should("be.visible");
});
it("edit a team's scheduled query successfully", () => {
cy.getAttached("tbody>tr")
.should("have.length", 1)
});
describe("Query pages", () => {
beforeEach(() => cy.visit("/queries/manage"));
it("allows global admin to select teams targets for query", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
cy.getAttached(".schedule-editor-modal__form").within(() => {
cy.findByText(/every day/i).click();
cy.findByText(/every 6 hours/i).click();
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".schedule-editor-modal__btn-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).click();
});
});
cy.findByText(/successfully updated/i).should("be.visible");
});
it("remove a team's scheduled query successfully", () => {
cy.getAttached("tbody>tr")
.should("have.length", 1)
.within(() => {
cy.findByText(/6 hours/i).should("exist");
cy.findByText(/action/i).click();
cy.findByText(/remove/i).click();
});
cy.getAttached(".remove-scheduled-query-modal__btn-wrap").within(() => {
cy.findByRole("button", { name: /remove/i }).click();
});
cy.findByText(/successfully removed/i).should("be.visible");
cy.getAttached(".query-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).click();
});
cy.contains("h3", /teams/i).should("exist");
cy.contains(".selector-name", /apples/i).should("exist");
});
describe("Manage policies page", () => {
beforeEach(() => cy.visit("/policies/manage"));
it("hides manage automations button when all teams not selected", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/apples/i).should("exist");
});
cy.findByText(/manage automations/i).should("not.exist");
});
it("allows team admin to add a new policy", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /add a policy/i })
.click();
// Add a default policy
cy.findByText(/gatekeeper enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save policy/i }).click();
});
cy.findByRole("button", { name: /^Save$/ }).click();
cy.findByText(/policy created/i).should("exist");
});
it("allows team admin to edit a team policy", () => {
cy.visit("policies/manage");
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByText(/filevault enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).should("exist");
});
});
it("allows team admin to delete a team policy", () => {
cy.visit("/policies/manage");
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".remove-policies-modal").within(() => {
cy.findByRole("button", { name: /delete/i }).should("exist");
cy.findByRole("button", { name: /cancel/i }).click();
});
});
// Global Admin schedule tested in integration/free/admin.spec.ts
// Team Admin team schedule tested below in integration/premium/admin.spec.ts
describe("Manage policies page", () => {
beforeEach(() => cy.visit("/policies/manage"));
it("allows global admin to add a new policy", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /add a policy/i })
.click();
// Add a default policy
cy.findByText(/gatekeeper enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save policy/i }).click();
});
cy.findByRole("button", { name: /^Save$/ }).click();
cy.findByText(/policy created/i).should("exist");
cy.findByText(/gatekeeper enabled/i).should("exist");
});
describe("Team admin settings page", () => {
beforeEach(() => cy.visit("/settings/teams/1/members"));
it("allows team admin to access team settings", () => {
// Access the Settings - Team details page
cy.findByText(/apples/i).should("exist");
});
it("displays the team admin controls", () => {
cy.findByRole("button", { name: /add member/i }).click();
cy.findByRole("button", { name: /cancel/i }).click();
cy.findByRole("button", { name: /add hosts/i }).click();
cy.findByRole("button", { name: /done/i }).click();
cy.findByRole("button", { name: /manage enroll secrets/i }).click();
cy.findByRole("button", { name: /done/i }).click();
});
it("allows team admin to edit a team member", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.eq(1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
});
cy.getAttached(".select-role-form__role-dropdown").within(() => {
cy.findByText(/observer/i).click();
cy.findByText(/maintainer/i).click();
});
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.eq(1)
.within(() => {
cy.findByText(/maintainer/i).should("exist");
});
});
});
it("does not allow team admin to edit existing user password", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.eq(1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
});
cy.getAttached(".create-user-form").within(() => {
cy.findByLabelText(/email/i).should("exist");
cy.findByLabelText(/password/i).should("not.exist");
});
});
it("allows team admin to edit team name", () => {
cy.findByRole("button", { name: /edit team/i }).click();
cy.findByLabelText(/team name/i)
it("allows global admin to automate a global policy", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /manage automations/i })
.click();
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
cy.getAttached("#webhook-url")
.clear()
.type("Mystic");
cy.findByRole("button", { name: /save/i }).click();
cy.findByText(/updated team name/i).should("exist");
.type("https://example.com/global_admin");
cy.findByText(/save/i).click();
});
cy.findByText(/successfully updated policy automations/i).should("exist");
});
it("allows global admin to delete a team policy", () => {
cy.visit("/policies/manage");
cy.getAttached(".Select-control").within(() => {
cy.findByText(/all teams/i).click();
});
cy.getAttached(".Select-menu")
.contains(/apples/i)
.click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".remove-policies-modal").within(() => {
cy.findByRole("button", { name: /delete/i }).should("exist");
cy.findByRole("button", { name: /cancel/i }).click();
});
});
describe("User profile page", () => {
it("should render elements according to role-based access controls", () => {
cy.visit("/profile");
cy.getAttached(".user-settings__additional").within(() => {
cy.findByText(/team/i)
.next()
.contains(/mystic/i); // Updated team name
cy.findByText("Role").next().contains(/admin/i);
});
it("allows global admin to edit a team policy", () => {
cy.visit("policies/manage");
cy.findByText(/all teams/i).click();
cy.findByText(/apples/i).click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByText(/filevault enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).should("exist");
});
});
});
describe("Admin settings page", () => {
beforeEach(() => cy.visit("/settings/organization"));
it("allows global admin to access team settings", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/teams/i).click();
});
// Access the Settings - Team details page
cy.getAttached("tbody").within(() => {
cy.findByText(/apples/i).click();
});
cy.findByText(/apples/i).should("exist");
cy.findByText(/manage users with global access here/i).should("exist");
});
it("displays the 'Team' section in the create user modal", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click();
cy.findByText(/assign teams/i).should("exist");
});
it("allows global admin to edit existing user password", () => {
cy.visit("/settings/users");
cy.getAttached("tbody").within(() => {
cy.findByText("Oliver") // case-sensitive
.parent()
.next()
.next()
.next()
.next()
.next()
.within(() => cy.getAttached(".Select-placeholder").click());
});
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/edit/i).click();
});
cy.getAttached(".create-user-form").within(() => {
cy.findByLabelText(/email/i).should("exist");
cy.findByLabelText(/password/i).should("exist");
});
});
});
describe("User profile page", () => {
it("renders elements according to role-based access controls", () => {
cy.visit("/profile");
cy.getAttached(".user-settings__additional").within(() => {
cy.findByText(/team/i)
.next()
.contains(/global/i);
cy.findByText("Role").next().contains(/admin/i);
});
});
});

View file

@ -0,0 +1,410 @@
describe("Premium tier - Team Admin user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.seedPolicies("apples");
cy.addDockerHost("apples"); // host not transferred
cy.addDockerHost("oranges"); // host transferred between teams by global admin
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
beforeEach(() => {
cy.loginWithCySession("anita@organization.com", "user123#");
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended team admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).should("not.exist");
cy.findByText(/settings/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/members/i).should("exist");
});
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/agent options/i).should("exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays cards for all platforms", () => {
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
cy.getAttached(".home-software").should("exist");
cy.get(".activity-feed").should("not.exist");
});
});
it("displays cards for windows only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/windows/i).click();
});
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
});
});
it("displays cards for linux only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/linux/i).click();
});
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
});
});
it("displays cards for macOS only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/macos/i).click();
});
cy.getAttached(".homepage__wrapper").within(() => {
cy.findByText(/apples/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".hosts-status").should("exist");
cy.getAttached(".home-munki").should("exist");
cy.getAttached(".home-mdm").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
});
});
it("views all hosts for all platforms", () => {
cy.findByText(/view all hosts/i).click();
cy.get(".manage-hosts__label-block").should("not.exist");
});
it("views all hosts for windows only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/windows/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.getAttached(".manage-hosts__label-block").within(() => {
cy.getAttached(".title").within(() => {
cy.findByText(/windows/i).should("exist");
});
});
});
it("views all hosts for linux only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/linux/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.getAttached(".manage-hosts__label-block").within(() => {
cy.getAttached(".title").within(() => {
cy.findByText(/linux/i).should("exist");
});
});
});
it("views all hosts for macOS only", () => {
cy.getAttached(".homepage__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/macos/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.getAttached(".manage-hosts__label-block").within(() => {
cy.getAttached(".title").within(() => {
cy.findByText(/macos/i).should("exist");
});
});
});
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.visit("/hosts/manage");
});
it("displays team column in hosts table", () => {
cy.getAttached(".data-table__table th")
.contains("Team")
.should("be.visible");
});
it("allows team admin to see and click 'Add hosts'", () => {
cy.getAttached(".button-wrap")
.contains("button", /add hosts/i)
.click();
cy.getAttached(".modal__content").contains("button", /done/i).click();
});
it("allows team admin to add new enroll secret", () => {
cy.getAttached(".button-wrap")
.contains("button", /manage enroll secret/i)
.click();
cy.getAttached(".enroll-secret-modal__add-secret")
.contains("button", /add secret/i)
.click();
cy.getAttached(".secret-editor-modal__button-wrap")
.contains("button", /save/i)
.click();
cy.getAttached(".enroll-secret-modal__button-wrap")
.contains("button", /done/i)
.click();
});
});
describe("Host details page", () => {
beforeEach(() => cy.visit("hosts/1"));
it("allows team admin to create an operating system policy", () => {
cy.getAttached(".info-flex").within(() => {
cy.findByText(/ubuntu/i).should("exist");
cy.getAttached(".host-summary__os-policy-button").click();
});
cy.getAttached(".modal__content")
.findByRole("button", { name: /create new policy/i })
.should("exist");
});
it("allows team admin to query host but not transfer host", () => {
cy.getAttached(".host-details__query-button").should("exist");
cy.findByText(/transfer/i).should("not.exist");
});
it("allows team admin to delete a host", () => {
cy.getAttached(".host-details__action-button-container")
.contains("button", /delete/i)
.click();
cy.getAttached(".delete-host-modal__modal").within(() => {
cy.findByText(/delete host/i).should("exist");
cy.contains("button", /delete/i).should("exist");
cy.getAttached(".modal__ex").click();
});
});
});
describe("Manage software page", () => {
beforeEach(() => cy.visit("/software/manage"));
it("hides manage automations button since all teams not selected", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByText(/apples/i).should("exist");
});
cy.findByText(/manage automations/i).should("not.exist");
});
});
describe("Query pages", () => {
beforeEach(() => cy.visit("/queries/manage"));
it("allows team admin to select teams targets for query", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".query-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).click();
});
cy.contains("h3", /teams/i).should("exist");
cy.contains(".selector-name", /apples/i).should("exist");
});
it("disables team admin from deleting or editing a query not authored by them", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").should("be.disabled");
});
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".query-form__save").should("be.disabled");
});
});
describe("Manage schedules page", () => {
beforeEach(() => {
cy.visit("/schedule/manage");
});
it("hides advanced button when team admin", () => {
cy.getAttached(".manage-schedule-page__header-wrap").within(() => {
cy.findByText(/apples/i).should("exist");
});
cy.findByText(/advanced/i).should("not.exist");
});
it("creates a new team scheduled query", () => {
cy.getAttached(".no-schedule__schedule-button").click();
cy.getAttached(".schedule-editor-modal__form").within(() => {
cy.findByText(/select query/i).click();
cy.findByText(/detect presence/i).click();
cy.getAttached(".schedule-editor-modal__btn-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).click();
});
});
cy.findByText(/successfully added/i).should("be.visible");
});
it("edit a team's scheduled query successfully", () => {
cy.getAttached("tbody>tr")
.should("have.length", 1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
cy.getAttached(".schedule-editor-modal__form").within(() => {
cy.findByText(/every day/i).click();
cy.findByText(/every 6 hours/i).click();
cy.getAttached(".schedule-editor-modal__btn-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).click();
});
});
cy.findByText(/successfully updated/i).should("be.visible");
});
it("remove a team's scheduled query successfully", () => {
cy.getAttached("tbody>tr")
.should("have.length", 1)
.within(() => {
cy.findByText(/6 hours/i).should("exist");
cy.findByText(/action/i).click();
cy.findByText(/remove/i).click();
});
cy.getAttached(".remove-scheduled-query-modal__btn-wrap").within(() => {
cy.findByRole("button", { name: /remove/i }).click();
});
cy.findByText(/successfully removed/i).should("be.visible");
});
});
describe("Manage policies page", () => {
beforeEach(() => cy.visit("/policies/manage"));
it("hides manage automations button when all teams not selected", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/apples/i).should("exist");
});
cy.findByText(/manage automations/i).should("not.exist");
});
it("allows team admin to add a new policy", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /add a policy/i })
.click();
// Add a default policy
cy.findByText(/gatekeeper enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save policy/i }).click();
});
cy.findByRole("button", { name: /^Save$/ }).click();
cy.findByText(/policy created/i).should("exist");
});
it("allows team admin to edit a team policy", () => {
cy.visit("policies/manage");
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByText(/filevault enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).should("exist");
});
});
it("allows team admin to automate a team policy", () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /manage automations/i })
.click();
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
cy.getAttached("#webhook-url")
.clear()
.type("https://example.com/team_admin");
cy.findByText(/save/i).click();
});
cy.findByText(/successfully updated policy automations/i).should("exist");
});
it("allows team admin to delete a team policy", () => {
cy.visit("/policies/manage");
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".remove-policies-modal").within(() => {
cy.findByRole("button", { name: /delete/i }).should("exist");
cy.findByRole("button", { name: /cancel/i }).click();
});
});
});
describe("Team admin settings page", () => {
beforeEach(() => cy.visit("/settings/teams/1/members"));
it("allows team admin to access team settings", () => {
// Access the Settings - Team details page
cy.findByText(/apples/i).should("exist");
});
it("displays the team admin controls", () => {
cy.findByRole("button", { name: /add member/i }).click();
cy.findByRole("button", { name: /cancel/i }).click();
cy.findByRole("button", { name: /add hosts/i }).click();
cy.findByRole("button", { name: /done/i }).click();
cy.findByRole("button", { name: /manage enroll secrets/i }).click();
cy.findByRole("button", { name: /done/i }).click();
});
it("allows team admin to edit a team member", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.eq(1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
});
cy.getAttached(".select-role-form__role-dropdown").within(() => {
cy.findByText(/observer/i).click();
cy.findByText(/maintainer/i).click();
});
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.eq(1)
.within(() => {
cy.findByText(/maintainer/i).should("exist");
});
});
});
it("allows team admin to edit team name", () => {
cy.findByRole("button", { name: /edit team/i }).click();
cy.findByLabelText(/team name/i)
.clear()
.type("Mystic");
cy.findByRole("button", { name: /save/i }).click();
cy.findByText(/updated team name/i).should("exist");
});
});
describe("User profile page", () => {
it("should render elements according to role-based access controls", () => {
cy.visit("/profile");
cy.getAttached(".user-settings__additional").within(() => {
cy.findByText(/team/i)
.next()
.contains(/mystic/i); // Updated team name
cy.findByText("Role").next().contains(/admin/i);
});
});
});
});

View file

@ -276,8 +276,8 @@ describe("Premium tier - Team observer/maintainer user", () => {
cy.findByText(/apples/i).click();
cy.findByText(/oranges/i).click();
// On maintaining team, not see the "Manage automations" button
cy.findByText(/manage automations/i).should("not.exist");
// On maintaining team, should see the "Manage automations" button
cy.findByText(/manage automations/i).should("exist");
// On maintaining team, should see "add a policy" and "save" a policy
cy.findByText(/add a policy/i).click();

View file

@ -31,13 +31,22 @@ export interface ITeam extends ITeamSummary {
display_text?: string;
count?: number;
created_at?: string;
agent_options?: any;
agent_options?: {
[key: string]: any;
};
webhook_settings?: {
[key: string]: any;
};
user_count?: number;
host_count?: number;
secrets?: IEnrollSecret[];
role?: string; // role value is included when the team is in the context of a user
}
export interface ILoadTeamResponse {
team: ITeam;
}
/**
* The shape of a new member to add to a team
*/

View file

@ -312,7 +312,7 @@ const TeamDetailsWrapper = ({
}
try {
await teamsAPI.update(currentTeam.id, updatedAttrs);
await teamsAPI.update(updatedAttrs, currentTeam.id);
await teamsAPI.loadAll({ perPage: 500 });
renderFlash(

View file

@ -143,7 +143,7 @@ const TeamManagementPage = (): JSX.Element => {
toggleEditTeamModal();
} else if (teamEditing) {
teamsAPI
.update(teamEditing.id, formData)
.update(formData, teamEditing.id)
.then(() => {
renderFlash(
"success",

View file

@ -1,7 +1,7 @@
import React, { useCallback, useContext, useEffect, useState } from "react";
import { useQuery } from "react-query";
import { InjectedRouter } from "react-router/lib/Router";
import { noop } from "lodash";
import { get, has, noop } from "lodash";
import { AppContext } from "context/app";
import { PolicyContext } from "context/policy";
@ -10,11 +10,13 @@ import { NotificationContext } from "context/notification";
import { IPolicyStats, ILoadAllPoliciesResponse } from "interfaces/policy";
import { IWebhookFailingPolicies } from "interfaces/webhook";
import { IConfig } from "interfaces/config";
import { ITeam, ILoadTeamResponse } from "interfaces/team";
import PATHS from "router/paths";
import configAPI from "services/entities/config";
import globalPoliciesAPI from "services/entities/global_policies";
import teamPoliciesAPI from "services/entities/team_policies";
import teamsAPI from "services/entities/teams";
import usersAPI, { IGetMeResponse } from "services/entities/users";
import Button from "components/buttons/Button";
@ -137,19 +139,37 @@ const ManagePolicyPage = ({
const canAddOrRemovePolicy =
isGlobalAdmin || isGlobalMaintainer || isTeamMaintainer || isTeamAdmin;
const { isLoading: isLoadingConfig, refetch: refetchConfig } = useQuery<
IConfig,
Error
>(["config"], () => configAPI.loadAll(), {
enabled: canAddOrRemovePolicy,
onSuccess: (data) => {
setFailingPoliciesWebhook(data.webhook_settings.failing_policies_webhook);
setCurrentAutomatedPolicies(
data.webhook_settings.failing_policies_webhook.policy_ids
);
setConfig(data);
const { isLoading: isLoadingWebhooks, refetch: refetchWebhooks } = useQuery<
IConfig | ILoadTeamResponse,
Error,
IConfig | ITeam
>(
["webhooks", teamId],
() => {
return teamId ? teamsAPI.load(teamId) : configAPI.loadAll();
},
});
{
enabled: canAddOrRemovePolicy,
select: (data) => {
if (has(data, "team")) {
return get(data, "team");
}
return data;
},
onSuccess: (data) => {
setFailingPoliciesWebhook(
data.webhook_settings?.failing_policies_webhook
);
setCurrentAutomatedPolicies(
data.webhook_settings?.failing_policies_webhook.policy_ids
);
if (has(data, "org_info")) {
setConfig(data as IConfig);
}
},
}
);
const refetchPolicies = (id?: number) => {
refetchGlobalPolicies();
@ -192,17 +212,15 @@ const ManagePolicyPage = ({
const toggleShowInheritedPolicies = () =>
setShowInheritedPolicies(!showInheritedPolicies);
const onManageAutomationsClick = () => {
toggleManageAutomationsModal();
};
const onCreateWebhookSubmit = async ({
destination_url,
policy_ids,
enable_failing_policies_webhook,
}: IWebhookFailingPolicies) => {
try {
const request = configAPI.update({
const api = teamId ? teamsAPI : configAPI;
const secondParam = teamId || undefined;
const data = {
webhook_settings: {
failing_policies_webhook: {
destination_url,
@ -210,7 +228,9 @@ const ManagePolicyPage = ({
enable_failing_policies_webhook,
},
},
});
};
const request = api.update(data, secondParam);
await request.then(() => {
renderFlash("success", "Successfully updated policy automations.");
});
@ -221,7 +241,7 @@ const ManagePolicyPage = ({
);
} finally {
toggleManageAutomationsModal();
refetchConfig();
refetchWebhooks();
}
};
@ -285,6 +305,9 @@ const ManagePolicyPage = ({
!globalPoliciesError &&
!!globalPolicies?.length;
const availablePoliciesForAutomation =
(teamId ? teamPolicies : globalPolicies) || [];
// If team_id from URL query params is not valid, we instead use a default team
// either the current team (if any) or all teams (for global users) or
// the first available team (for non-global users)
@ -342,11 +365,10 @@ const ManagePolicyPage = ({
</div>
<div className={`${baseClass} button-wrap`}>
{canAddOrRemovePolicy &&
teamId === 0 &&
!isLoadingConfig &&
!isLoadingWebhooks &&
!isLoadingGlobalPolicies && (
<Button
onClick={() => onManageAutomationsClick()}
onClick={toggleManageAutomationsModal}
className={`${baseClass}__manage-automations button`}
variant="inverse"
>
@ -383,12 +405,12 @@ const ManagePolicyPage = ({
{!!teamId && teamPoliciesError && <TableDataError />}
{!!teamId &&
!teamPoliciesError &&
(isLoadingTeamPolicies && isLoadingConfig ? (
(isLoadingTeamPolicies && isLoadingWebhooks ? (
<Spinner />
) : (
<PoliciesListWrapper
policiesList={teamPolicies || []}
isLoading={isLoadingTeamPolicies && isLoadingConfig}
isLoading={isLoadingTeamPolicies && isLoadingWebhooks}
onRemovePoliciesClick={onRemovePoliciesClick}
canAddOrRemovePolicy={canAddOrRemovePolicy}
currentTeam={currentTeam}
@ -403,7 +425,7 @@ const ManagePolicyPage = ({
) : (
<PoliciesListWrapper
policiesList={globalPolicies || []}
isLoading={isLoadingGlobalPolicies && isLoadingConfig}
isLoading={isLoadingGlobalPolicies && isLoadingWebhooks}
onRemovePoliciesClick={onRemovePoliciesClick}
canAddOrRemovePolicy={canAddOrRemovePolicy}
currentTeam={currentTeam}
@ -438,7 +460,7 @@ const ManagePolicyPage = ({
<Spinner />
) : (
<PoliciesListWrapper
isLoading={isLoadingGlobalPolicies && isLoadingConfig}
isLoading={isLoadingGlobalPolicies && isLoadingWebhooks}
policiesList={globalPolicies || []}
onRemovePoliciesClick={noop}
resultsTitle="policies"
@ -456,7 +478,7 @@ const ManagePolicyPage = ({
onCreateWebhookSubmit={onCreateWebhookSubmit}
togglePreviewPayloadModal={togglePreviewPayloadModal}
showPreviewPayloadModal={showPreviewPayloadModal}
availablePolicies={globalPolicies || []}
availablePolicies={availablePoliciesForAutomation}
currentAutomatedPolicies={currentAutomatedPolicies || []}
currentDestinationUrl={
(failingPoliciesWebhook &&

View file

@ -232,6 +232,15 @@ const generateTableHeaders = (options: {
);
},
},
{
title: "Automations",
Header: "Automations",
disableSortBy: true,
accessor: "webhook",
Cell: (cellProps: ICellProps): JSX.Element => (
<StatusCell value={cellProps.cell.value} />
),
},
];
if (!canAddOrRemovePolicy) {
@ -260,18 +269,6 @@ const generateTableHeaders = (options: {
disableHidden: true,
});
if (!selectedTeamId) {
tableHeaders.push({
title: "Automations",
Header: "Automations",
disableSortBy: true,
accessor: "webhook",
Cell: (cellProps: ICellProps): JSX.Element => (
<StatusCell value={cellProps.cell.value} />
),
});
}
return tableHeaders;
}
}

View file

@ -11,10 +11,18 @@ interface ITeamSearchOptions {
globalFilter?: string;
}
interface IEditTeamFormData {
interface ITeamName {
name: string;
}
interface ITeamWebhooks {
webhook_settings: {
[key: string]: any;
};
}
type ITeamEditData = ITeamName | ITeamWebhooks;
export default {
create: (formData: ICreateTeamFormData) => {
const { TEAMS } = endpoints;
@ -27,6 +35,12 @@ export default {
return sendRequest("DELETE", path);
},
load: (teamId: number) => {
const { TEAMS } = endpoints;
const path = `${TEAMS}/${teamId}`;
return sendRequest("GET", path);
},
loadAll: ({
page = 0,
perPage = 100,
@ -46,7 +60,14 @@ export default {
return sendRequest("GET", path);
},
update: (teamId: number, updateParams: IEditTeamFormData) => {
update: (updateParams: ITeamEditData, teamId?: number) => {
// we are grouping this update with the config api update function
// on the ManagePoliciesPage to streamline updating the
// webhook settings globally or for a team - see ManagePoliciesPage line 208
if (typeof teamId === "undefined") {
return Promise.reject();
}
const { TEAMS } = endpoints;
const path = `${TEAMS}/${teamId}`;