mirror of
https://github.com/bitwarden/browser
synced 2026-02-20 03:13:55 +00:00
[PM-16694] ac integration page background fill missing (#18508)
* Fixing some tech debt before implementing actual fix of implementation * Adding new components to handle the different routes for the integrations page to make use of bit-tab-nav-bar to follow background-fill UI spec * Implement organization integrations page with routing and state management - Added routing for organization integrations including device management, event management, single sign-on, and user provisioning. - Created OrganizationIntegrationsState to manage integrations and organization data. - Introduced OrganizationIntegrationsResolver for preloading organization and integration data. - Updated components to utilize the new state management and resolver. - Refactored integration routes to follow updated naming conventions. * Refactor organization integrations components to use signals and observables; enhance async handling in templates and add debug logging * Enhance organization integrations module with routing updates and state management improvements - Added OrganizationIntegrationsState for better state management. - Updated routing to redirect to single sign-on by default. - Integrated OrganizationIntegrationsResolver for preloading data. - Refactored components to utilize new state management and improved async handling. * Refactor SingleSignOnComponent to remove OnInit lifecycle and debug logging - Simplified SingleSignOnComponent by removing the OnInit implementation. - Eliminated debug logging for integrations in ngOnInit. - Cleaned up imports for better readability. * Refactor WebHeaderComponent to simplify background handling - Removed the useAltBackground input signal from WebHeaderComponent. - Updated the HTML template to conditionally apply styles based solely on the child element count of the tabs container. * Refactor organization integrations components for improved readability and performance - Updated HTML templates to remove optional chaining for organization properties. - Removed unnecessary debug logging and comments in the OrganizationIntegrationsResolver. - Simplified DeviceManagementComponent by eliminating the OnInit lifecycle hook. * Refactor organization integrations components to use direct state properties - Updated components to access organization and integrations directly from state instead of using observables. - Simplified HTML templates by removing async pipes and using direct function calls for better readability. - Ensured consistent naming conventions for organization and integrations variables across components. * Enhance WebHeaderComponent by adding bitTypography attribute to the title element for improved styling consistency * Refactor organization state to use 'undefined' instead of 'null' for organization signal and remove OnInit lifecycle hook from UserProvisioningComponent for cleaner code. * Refactor EventManagementComponent to remove OnInit lifecycle hook for cleaner code and improved readability. * Update organization state to set organization value to 'undefined' when null is provided, enhancing state management consistency. * Update WebHeaderComponent to allow optional title and icon inputs, enhancing flexibility in header configuration. * Update WebHeaderComponent to allow account property to be nullable, improving type safety and handling of user data.
This commit is contained in:
@@ -79,7 +79,7 @@
|
||||
<bit-nav-item
|
||||
icon="bwi-msp"
|
||||
[text]="'integrations' | i18n"
|
||||
route="integrations"
|
||||
route="integrations/single-sign-on"
|
||||
*ngIf="integrationPageEnabled$ | async"
|
||||
></bit-nav-item>
|
||||
<bit-nav-group
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
bitTypography="h1"
|
||||
noMargin
|
||||
class="tw-m-0 tw-mr-2 tw-leading-10 tw-flex tw-gap-1"
|
||||
[title]="title || (routeData.titleId | i18n)"
|
||||
[title]="title() || (routeData.titleId | i18n)"
|
||||
>
|
||||
<div class="tw-truncate">
|
||||
<i *ngIf="icon" class="bwi {{ icon }}" aria-hidden="true"></i>
|
||||
{{ title || (routeData.titleId | i18n) }}
|
||||
<i *ngIf="icon" class="bwi {{ icon() }}" aria-hidden="true"></i>
|
||||
{{ title() || (routeData.titleId | i18n) }}
|
||||
</div>
|
||||
<div><ng-content select="[slot=title-suffix]"></ng-content></div>
|
||||
</h1>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { Component, input, InputSignal } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { map, Observable } from "rxjs";
|
||||
|
||||
@@ -25,19 +23,15 @@ export class WebHeaderComponent {
|
||||
/**
|
||||
* Custom title that overrides the route data `titleId`
|
||||
*/
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
||||
@Input() title: string;
|
||||
readonly title: InputSignal<string | undefined> = input();
|
||||
|
||||
/**
|
||||
* Icon to show before the title
|
||||
*/
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
||||
@Input() icon: string;
|
||||
readonly icon: InputSignal<string | undefined> = input();
|
||||
|
||||
protected routeData$: Observable<{ titleId: string }>;
|
||||
protected account$: Observable<User & { id: UserId }>;
|
||||
protected account$: Observable<(User & { id: UserId }) | null>;
|
||||
protected canLock$: Observable<boolean>;
|
||||
protected selfHosted: boolean;
|
||||
protected hostname = location.hostname;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
@let integrationsList = integrations();
|
||||
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "deviceManagement" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">{{ "deviceManagementDesc" | i18n }}</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.DEVICE"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IntegrationType } from "@bitwarden/common/enums/integration-type.enum";
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
|
||||
import { IntegrationGridComponent } from "../integration-grid/integration-grid.component";
|
||||
import { FilterIntegrationsPipe } from "../integrations.pipe";
|
||||
import { OrganizationIntegrationsState } from "../organization-integrations.state";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "device-management",
|
||||
templateUrl: "device-management.component.html",
|
||||
imports: [SharedModule, IntegrationGridComponent, FilterIntegrationsPipe],
|
||||
})
|
||||
export class DeviceManagementComponent {
|
||||
integrations = this.state.integrations;
|
||||
|
||||
constructor(private state: OrganizationIntegrationsState) {}
|
||||
|
||||
get IntegrationType(): typeof IntegrationType {
|
||||
return IntegrationType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@let integrationsList = integrations();
|
||||
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "eventManagement" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">{{ "eventManagementDesc" | i18n }}</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.EVENT"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IntegrationType } from "@bitwarden/common/enums/integration-type.enum";
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
|
||||
import { IntegrationGridComponent } from "../integration-grid/integration-grid.component";
|
||||
import { FilterIntegrationsPipe } from "../integrations.pipe";
|
||||
import { OrganizationIntegrationsState } from "../organization-integrations.state";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "event-management",
|
||||
templateUrl: "event-management.component.html",
|
||||
imports: [SharedModule, IntegrationGridComponent, FilterIntegrationsPipe],
|
||||
})
|
||||
export class EventManagementComponent {
|
||||
integrations = this.state.integrations;
|
||||
constructor(private state: OrganizationIntegrationsState) {}
|
||||
|
||||
get IntegrationType(): typeof IntegrationType {
|
||||
return IntegrationType;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +1,18 @@
|
||||
<app-header> </app-header>
|
||||
@let org = organization();
|
||||
|
||||
@let organization = organization$ | async;
|
||||
<app-header>
|
||||
@if (org) {
|
||||
<bit-tab-nav-bar slot="tabs">
|
||||
<bit-tab-link route="single-sign-on">{{ "singleSignOn" | i18n }}</bit-tab-link>
|
||||
@if (org.useScim || org.useDirectory) {
|
||||
<bit-tab-link route="user-provisioning">{{ "userProvisioning" | i18n }}</bit-tab-link>
|
||||
}
|
||||
@if (org.useEvents) {
|
||||
<bit-tab-link route="event-management">{{ "eventManagement" | i18n }}</bit-tab-link>
|
||||
}
|
||||
<bit-tab-link route="device-management">{{ "deviceManagement" | i18n }}</bit-tab-link>
|
||||
</bit-tab-nav-bar>
|
||||
}
|
||||
</app-header>
|
||||
|
||||
@if (organization) {
|
||||
<bit-tab-group [(selectedIndex)]="tabIndex">
|
||||
@if (organization?.useSso) {
|
||||
<bit-tab [label]="'singleSignOn' | i18n">
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">{{ "singleSignOn" | i18n }}</h2>
|
||||
<p bitTypography="body1">
|
||||
{{ "ssoDescStart" | i18n }}
|
||||
<a bitLink routerLink="../settings/sso" class="tw-lowercase">{{
|
||||
"singleSignOn" | i18n
|
||||
}}</a>
|
||||
{{ "ssoDescEnd" | i18n }}
|
||||
</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.SSO"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
</bit-tab>
|
||||
}
|
||||
|
||||
@if (organization?.useScim || organization?.useDirectory) {
|
||||
<bit-tab [label]="'userProvisioning' | i18n">
|
||||
@if (organization?.useScim) {
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "scimIntegration" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">
|
||||
{{ "scimIntegrationDescStart" | i18n }}
|
||||
<a bitLink routerLink="../settings/scim">{{ "scimIntegration" | i18n }}</a>
|
||||
{{ "scimIntegrationDescEnd" | i18n }}
|
||||
</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.SCIM"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
}
|
||||
@if (organization?.useDirectory) {
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "bwdc" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">{{ "bwdcDesc" | i18n }}</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.BWDC"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
}
|
||||
</bit-tab>
|
||||
}
|
||||
|
||||
@if (organization?.useEvents) {
|
||||
<bit-tab [label]="'eventManagement' | i18n">
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "eventManagement" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">{{ "eventManagementDesc" | i18n }}</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.EVENT"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
</bit-tab>
|
||||
}
|
||||
|
||||
<bit-tab [label]="'deviceManagement' | i18n">
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "deviceManagement" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">{{ "deviceManagementDesc" | i18n }}</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.DEVICE"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
</bit-tab>
|
||||
</bit-tab-group>
|
||||
}
|
||||
<router-outlet></router-outlet>
|
||||
|
||||
@@ -1,336 +1,22 @@
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { firstValueFrom, Observable, Subject, switchMap, takeUntil, takeWhile } from "rxjs";
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { Integration } from "@bitwarden/bit-common/dirt/organization-integrations/models/integration";
|
||||
import { OrganizationIntegrationServiceName } from "@bitwarden/bit-common/dirt/organization-integrations/models/organization-integration-service-type";
|
||||
import { OrganizationIntegrationType } from "@bitwarden/bit-common/dirt/organization-integrations/models/organization-integration-type";
|
||||
import { OrganizationIntegrationService } from "@bitwarden/bit-common/dirt/organization-integrations/services/organization-integration-service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { IntegrationType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { getById } from "@bitwarden/common/platform/misc";
|
||||
import { IntegrationType } from "@bitwarden/common/enums/integration-type.enum";
|
||||
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module";
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
|
||||
import { IntegrationGridComponent } from "./integration-grid/integration-grid.component";
|
||||
import { FilterIntegrationsPipe } from "./integrations.pipe";
|
||||
import { OrganizationIntegrationsState } from "./organization-integrations.state";
|
||||
|
||||
// attempted, but because bit-tab-group is not OnPush, caused more issues than it solved
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "ac-integrations",
|
||||
templateUrl: "./integrations.component.html",
|
||||
imports: [SharedModule, IntegrationGridComponent, HeaderModule, FilterIntegrationsPipe],
|
||||
imports: [SharedModule, HeaderModule],
|
||||
})
|
||||
export class AdminConsoleIntegrationsComponent implements OnInit, OnDestroy {
|
||||
tabIndex: number = 0;
|
||||
organization$: Observable<Organization> = new Observable<Organization>();
|
||||
isEventManagementForDataDogAndCrowdStrikeEnabled: boolean = false;
|
||||
isEventManagementForHuntressEnabled: boolean = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
export class AdminConsoleIntegrationsComponent {
|
||||
organization = this.state.organization;
|
||||
|
||||
// initialize the integrations list with default integrations
|
||||
integrationsList: Integration[] = [
|
||||
{
|
||||
name: "AD FS",
|
||||
linkURL: "https://bitwarden.com/help/saml-adfs/",
|
||||
image: "../../../../../../../images/integrations/azure-active-directory.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Auth0",
|
||||
linkURL: "https://bitwarden.com/help/saml-auth0/",
|
||||
image: "../../../../../../../images/integrations/logo-auth0-badge-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "AWS",
|
||||
linkURL: "https://bitwarden.com/help/saml-aws/",
|
||||
image: "../../../../../../../images/integrations/aws-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/aws-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Entra ID",
|
||||
linkURL: "https://bitwarden.com/help/saml-azure/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-entra-id-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Duo",
|
||||
linkURL: "https://bitwarden.com/help/saml-duo/",
|
||||
image: "../../../../../../../images/integrations/logo-duo-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Google",
|
||||
linkURL: "https://bitwarden.com/help/saml-google/",
|
||||
image: "../../../../../../../images/integrations/logo-google-badge-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "JumpCloud",
|
||||
linkURL: "https://bitwarden.com/help/saml-jumpcloud/",
|
||||
image: "../../../../../../../images/integrations/logo-jumpcloud-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/jumpcloud-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "KeyCloak",
|
||||
linkURL: "https://bitwarden.com/help/saml-keycloak/",
|
||||
image: "../../../../../../../images/integrations/logo-keycloak-icon.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Okta",
|
||||
linkURL: "https://bitwarden.com/help/saml-okta/",
|
||||
image: "../../../../../../../images/integrations/logo-okta-symbol-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/okta-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "OneLogin",
|
||||
linkURL: "https://bitwarden.com/help/saml-onelogin/",
|
||||
image: "../../../../../../../images/integrations/logo-onelogin-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/onelogin-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "PingFederate",
|
||||
linkURL: "https://bitwarden.com/help/saml-pingfederate/",
|
||||
image: "../../../../../../../images/integrations/logo-ping-identity-badge-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Entra ID",
|
||||
linkURL: "https://bitwarden.com/help/microsoft-entra-id-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-entra-id-color.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "Okta",
|
||||
linkURL: "https://bitwarden.com/help/okta-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-okta-symbol-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/okta-darkmode.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "OneLogin",
|
||||
linkURL: "https://bitwarden.com/help/onelogin-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-onelogin-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/onelogin-darkmode.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "JumpCloud",
|
||||
linkURL: "https://bitwarden.com/help/jumpcloud-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-jumpcloud-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/jumpcloud-darkmode.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "Ping Identity",
|
||||
linkURL: "https://bitwarden.com/help/ping-identity-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-ping-identity-badge-color.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "Active Directory",
|
||||
linkURL: "https://bitwarden.com/help/ldap-directory/",
|
||||
image: "../../../../../../../images/integrations/azure-active-directory.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Entra ID",
|
||||
linkURL: "https://bitwarden.com/help/microsoft-entra-id/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-entra-id-color.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Google Workspace",
|
||||
linkURL: "https://bitwarden.com/help/workspace-directory/",
|
||||
image: "../../../../../../../images/integrations/logo-google-badge-color.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Okta",
|
||||
linkURL: "https://bitwarden.com/help/okta-directory/",
|
||||
image: "../../../../../../../images/integrations/logo-okta-symbol-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/okta-darkmode.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "OneLogin",
|
||||
linkURL: "https://bitwarden.com/help/onelogin-directory/",
|
||||
image: "../../../../../../../images/integrations/logo-onelogin-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/onelogin-darkmode.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Splunk",
|
||||
linkURL: "https://bitwarden.com/help/splunk-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-splunk-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/splunk-darkmode.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Sentinel",
|
||||
linkURL: "https://bitwarden.com/help/microsoft-sentinel-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-sentinel-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Rapid7",
|
||||
linkURL: "https://bitwarden.com/help/rapid7-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-rapid7-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/rapid7-darkmode.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Elastic",
|
||||
linkURL: "https://bitwarden.com/help/elastic-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-elastic-badge-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Panther",
|
||||
linkURL: "https://bitwarden.com/help/panther-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-panther-round-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Sumo Logic",
|
||||
linkURL: "https://bitwarden.com/help/sumo-logic-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-sumo-logic-siem.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/logo-sumo-logic-siem-darkmode.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
newBadgeExpiration: "2025-12-31",
|
||||
},
|
||||
{
|
||||
name: "Microsoft Intune",
|
||||
linkURL: "https://bitwarden.com/help/deploy-browser-extensions-with-intune/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-intune-color.svg",
|
||||
type: IntegrationType.DEVICE,
|
||||
},
|
||||
];
|
||||
|
||||
async ngOnInit() {
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
if (!userId) {
|
||||
throw new Error("User ID not found");
|
||||
}
|
||||
|
||||
this.organization$ = this.route.params.pipe(
|
||||
switchMap((params) =>
|
||||
this.organizationService.organizations$(userId).pipe(
|
||||
getById(params.organizationId),
|
||||
// Filter out undefined values
|
||||
takeWhile((org: Organization | undefined) => !!org),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Sets the organization ID which also loads the integrations$
|
||||
this.organization$
|
||||
.pipe(
|
||||
switchMap((org) => this.organizationIntegrationService.setOrganizationId(org.id)),
|
||||
takeUntil(this.destroy$),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private configService: ConfigService,
|
||||
private organizationIntegrationService: OrganizationIntegrationService,
|
||||
) {
|
||||
this.configService
|
||||
.getFeatureFlag$(FeatureFlag.EventManagementForDataDogAndCrowdStrike)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((isEnabled) => {
|
||||
this.isEventManagementForDataDogAndCrowdStrikeEnabled = isEnabled;
|
||||
});
|
||||
|
||||
this.configService
|
||||
.getFeatureFlag$(FeatureFlag.EventManagementForHuntress)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((isEnabled) => {
|
||||
this.isEventManagementForHuntressEnabled = isEnabled;
|
||||
});
|
||||
|
||||
// Add the new event based items to the list
|
||||
if (this.isEventManagementForDataDogAndCrowdStrikeEnabled) {
|
||||
const crowdstrikeIntegration: Integration = {
|
||||
name: OrganizationIntegrationServiceName.CrowdStrike,
|
||||
linkURL: "https://bitwarden.com/help/crowdstrike-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-crowdstrike-black.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
description: "crowdstrikeEventIntegrationDesc",
|
||||
canSetupConnection: true,
|
||||
integrationType: OrganizationIntegrationType.Hec,
|
||||
};
|
||||
|
||||
this.integrationsList.push(crowdstrikeIntegration);
|
||||
|
||||
const datadogIntegration: Integration = {
|
||||
name: OrganizationIntegrationServiceName.Datadog,
|
||||
linkURL: "https://bitwarden.com/help/datadog-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-datadog-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
description: "datadogEventIntegrationDesc",
|
||||
canSetupConnection: true,
|
||||
integrationType: OrganizationIntegrationType.Datadog,
|
||||
};
|
||||
|
||||
this.integrationsList.push(datadogIntegration);
|
||||
}
|
||||
|
||||
// Add Huntress SIEM integration (separate feature flag)
|
||||
if (this.isEventManagementForHuntressEnabled) {
|
||||
const huntressIntegration: Integration = {
|
||||
name: OrganizationIntegrationServiceName.Huntress,
|
||||
linkURL: "https://bitwarden.com/help/huntress-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-huntress-siem.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
description: "huntressEventIntegrationDesc",
|
||||
canSetupConnection: true,
|
||||
integrationType: OrganizationIntegrationType.Hec,
|
||||
};
|
||||
|
||||
this.integrationsList.push(huntressIntegration);
|
||||
}
|
||||
|
||||
// For all existing event based configurations loop through and assign the
|
||||
// organizationIntegration for the correct services.
|
||||
this.organizationIntegrationService.integrations$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((integrations) => {
|
||||
// reset all event based integrations to null first - in case one was deleted
|
||||
this.integrationsList.forEach((i) => {
|
||||
i.organizationIntegration = null;
|
||||
});
|
||||
|
||||
integrations.forEach((integration) => {
|
||||
const item = this.integrationsList.find((i) => i.name === integration.serviceName);
|
||||
if (item) {
|
||||
item.organizationIntegration = integration;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
constructor(private state: OrganizationIntegrationsState) {}
|
||||
|
||||
// use in the view
|
||||
get IntegrationType(): typeof IntegrationType {
|
||||
|
||||
@@ -7,7 +7,10 @@ import { IntegrationType } from "@bitwarden/common/enums";
|
||||
name: "filterIntegrations",
|
||||
})
|
||||
export class FilterIntegrationsPipe implements PipeTransform {
|
||||
transform(integrations: Integration[], type: IntegrationType): Integration[] {
|
||||
transform(integrations: Integration[] | null | undefined, type: IntegrationType): Integration[] {
|
||||
if (!integrations) {
|
||||
return [];
|
||||
}
|
||||
return integrations.filter((integration) => integration.type === type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,31 @@ import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { organizationPermissionsGuard } from "@bitwarden/web-vault/app/admin-console/organizations/guards/org-permissions.guard";
|
||||
|
||||
import { DeviceManagementComponent } from "./device-management/device-management.component";
|
||||
import { EventManagementComponent } from "./event-management/event-management.component";
|
||||
import { AdminConsoleIntegrationsComponent } from "./integrations.component";
|
||||
import { OrganizationIntegrationsResolver } from "./organization-integrations.resolver";
|
||||
import { OrganizationIntegrationsState } from "./organization-integrations.state";
|
||||
import { SingleSignOnComponent } from "./single-sign-on/single-sign-on.component";
|
||||
import { UserProvisioningComponent } from "./user-provisioning/user-provisioning.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: "",
|
||||
canActivate: [organizationPermissionsGuard((org) => org.canAccessIntegrations)],
|
||||
component: AdminConsoleIntegrationsComponent,
|
||||
data: {
|
||||
titleId: "integrations",
|
||||
},
|
||||
component: AdminConsoleIntegrationsComponent,
|
||||
providers: [OrganizationIntegrationsState, OrganizationIntegrationsResolver],
|
||||
resolve: { integrations: OrganizationIntegrationsResolver },
|
||||
children: [
|
||||
{ path: "", redirectTo: "single-sign-on", pathMatch: "full" },
|
||||
{ path: "single-sign-on", component: SingleSignOnComponent },
|
||||
{ path: "user-provisioning", component: UserProvisioningComponent },
|
||||
{ path: "event-management", component: EventManagementComponent },
|
||||
{ path: "device-management", component: DeviceManagementComponent },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { DeviceManagementComponent } from "@bitwarden/angular/auth/device-management/device-management.component";
|
||||
import { OrganizationIntegrationApiService } from "@bitwarden/bit-common/dirt/organization-integrations/services/organization-integration-api.service";
|
||||
import { OrganizationIntegrationConfigurationApiService } from "@bitwarden/bit-common/dirt/organization-integrations/services/organization-integration-configuration-api.service";
|
||||
import { OrganizationIntegrationService } from "@bitwarden/bit-common/dirt/organization-integrations/services/organization-integration-service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { safeProvider } from "@bitwarden/ui-common";
|
||||
|
||||
import { EventManagementComponent } from "./event-management/event-management.component";
|
||||
import { AdminConsoleIntegrationsComponent } from "./integrations.component";
|
||||
import { OrganizationIntegrationsRoutingModule } from "./organization-integrations-routing.module";
|
||||
import { OrganizationIntegrationsResolver } from "./organization-integrations.resolver";
|
||||
import { SingleSignOnComponent } from "./single-sign-on/single-sign-on.component";
|
||||
import { UserProvisioningComponent } from "./user-provisioning/user-provisioning.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [AdminConsoleIntegrationsComponent, OrganizationIntegrationsRoutingModule],
|
||||
imports: [
|
||||
AdminConsoleIntegrationsComponent,
|
||||
OrganizationIntegrationsRoutingModule,
|
||||
SingleSignOnComponent,
|
||||
UserProvisioningComponent,
|
||||
DeviceManagementComponent,
|
||||
EventManagementComponent,
|
||||
],
|
||||
providers: [
|
||||
OrganizationIntegrationsResolver,
|
||||
safeProvider({
|
||||
provide: OrganizationIntegrationService,
|
||||
useClass: OrganizationIntegrationService,
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, Resolve } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { take, takeWhile } from "rxjs/operators";
|
||||
|
||||
import { Integration } from "@bitwarden/bit-common/dirt/organization-integrations/models/integration";
|
||||
import { OrganizationIntegrationServiceName } from "@bitwarden/bit-common/dirt/organization-integrations/models/organization-integration-service-type";
|
||||
import { OrganizationIntegrationType } from "@bitwarden/bit-common/dirt/organization-integrations/models/organization-integration-type";
|
||||
import { OrganizationIntegrationService } from "@bitwarden/bit-common/dirt/organization-integrations/services/organization-integration-service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { IntegrationType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { getById } from "@bitwarden/common/platform/misc";
|
||||
|
||||
import { OrganizationIntegrationsState } from "./organization-integrations.state";
|
||||
|
||||
@Injectable()
|
||||
export class OrganizationIntegrationsResolver implements Resolve<boolean> {
|
||||
constructor(
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private configService: ConfigService,
|
||||
private organizationIntegrationService: OrganizationIntegrationService,
|
||||
private state: OrganizationIntegrationsState,
|
||||
) {}
|
||||
|
||||
async resolve(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("User ID not found");
|
||||
}
|
||||
|
||||
const orgId = route.paramMap.get("organizationId")!;
|
||||
const org = await firstValueFrom(
|
||||
this.organizationService.organizations$(userId).pipe(getById(orgId), takeWhile(Boolean)),
|
||||
);
|
||||
|
||||
this.state.setOrganization(org);
|
||||
|
||||
await firstValueFrom(this.organizationIntegrationService.setOrganizationId(org.id));
|
||||
|
||||
const integrations: Integration[] = [
|
||||
{
|
||||
name: "AD FS",
|
||||
linkURL: "https://bitwarden.com/help/saml-adfs/",
|
||||
image: "../../../../../../../images/integrations/azure-active-directory.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Auth0",
|
||||
linkURL: "https://bitwarden.com/help/saml-auth0/",
|
||||
image: "../../../../../../../images/integrations/logo-auth0-badge-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "AWS",
|
||||
linkURL: "https://bitwarden.com/help/saml-aws/",
|
||||
image: "../../../../../../../images/integrations/aws-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/aws-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Entra ID",
|
||||
linkURL: "https://bitwarden.com/help/saml-azure/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-entra-id-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Duo",
|
||||
linkURL: "https://bitwarden.com/help/saml-duo/",
|
||||
image: "../../../../../../../images/integrations/logo-duo-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Google",
|
||||
linkURL: "https://bitwarden.com/help/saml-google/",
|
||||
image: "../../../../../../../images/integrations/logo-google-badge-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "JumpCloud",
|
||||
linkURL: "https://bitwarden.com/help/saml-jumpcloud/",
|
||||
image: "../../../../../../../images/integrations/logo-jumpcloud-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/jumpcloud-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "KeyCloak",
|
||||
linkURL: "https://bitwarden.com/help/saml-keycloak/",
|
||||
image: "../../../../../../../images/integrations/logo-keycloak-icon.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Okta",
|
||||
linkURL: "https://bitwarden.com/help/saml-okta/",
|
||||
image: "../../../../../../../images/integrations/logo-okta-symbol-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/okta-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "OneLogin",
|
||||
linkURL: "https://bitwarden.com/help/saml-onelogin/",
|
||||
image: "../../../../../../../images/integrations/logo-onelogin-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/onelogin-darkmode.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "PingFederate",
|
||||
linkURL: "https://bitwarden.com/help/saml-pingfederate/",
|
||||
image: "../../../../../../../images/integrations/logo-ping-identity-badge-color.svg",
|
||||
type: IntegrationType.SSO,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Entra ID",
|
||||
linkURL: "https://bitwarden.com/help/microsoft-entra-id-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-entra-id-color.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "Okta",
|
||||
linkURL: "https://bitwarden.com/help/okta-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-okta-symbol-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/okta-darkmode.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "OneLogin",
|
||||
linkURL: "https://bitwarden.com/help/onelogin-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-onelogin-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/onelogin-darkmode.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "JumpCloud",
|
||||
linkURL: "https://bitwarden.com/help/jumpcloud-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-jumpcloud-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/jumpcloud-darkmode.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "Ping Identity",
|
||||
linkURL: "https://bitwarden.com/help/ping-identity-scim-integration/",
|
||||
image: "../../../../../../../images/integrations/logo-ping-identity-badge-color.svg",
|
||||
type: IntegrationType.SCIM,
|
||||
},
|
||||
{
|
||||
name: "Active Directory",
|
||||
linkURL: "https://bitwarden.com/help/ldap-directory/",
|
||||
image: "../../../../../../../images/integrations/azure-active-directory.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Entra ID",
|
||||
linkURL: "https://bitwarden.com/help/microsoft-entra-id/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-entra-id-color.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Google Workspace",
|
||||
linkURL: "https://bitwarden.com/help/workspace-directory/",
|
||||
image: "../../../../../../../images/integrations/logo-google-badge-color.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Okta",
|
||||
linkURL: "https://bitwarden.com/help/okta-directory/",
|
||||
image: "../../../../../../../images/integrations/logo-okta-symbol-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/okta-darkmode.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "OneLogin",
|
||||
linkURL: "https://bitwarden.com/help/onelogin-directory/",
|
||||
image: "../../../../../../../images/integrations/logo-onelogin-badge-color.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/onelogin-darkmode.svg",
|
||||
type: IntegrationType.BWDC,
|
||||
},
|
||||
{
|
||||
name: "Splunk",
|
||||
linkURL: "https://bitwarden.com/help/splunk-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-splunk-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/splunk-darkmode.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Microsoft Sentinel",
|
||||
linkURL: "https://bitwarden.com/help/microsoft-sentinel-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-sentinel-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Rapid7",
|
||||
linkURL: "https://bitwarden.com/help/rapid7-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-rapid7-black.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/rapid7-darkmode.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Elastic",
|
||||
linkURL: "https://bitwarden.com/help/elastic-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-elastic-badge-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Panther",
|
||||
linkURL: "https://bitwarden.com/help/panther-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-panther-round-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
},
|
||||
{
|
||||
name: "Sumo Logic",
|
||||
linkURL: "https://bitwarden.com/help/sumo-logic-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-sumo-logic-siem.svg",
|
||||
imageDarkMode: "../../../../../../../images/integrations/logo-sumo-logic-siem-darkmode.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
newBadgeExpiration: "2025-12-31",
|
||||
},
|
||||
{
|
||||
name: "Microsoft Intune",
|
||||
linkURL: "https://bitwarden.com/help/deploy-browser-extensions-with-intune/",
|
||||
image: "../../../../../../../images/integrations/logo-microsoft-intune-color.svg",
|
||||
type: IntegrationType.DEVICE,
|
||||
},
|
||||
];
|
||||
|
||||
const featureEnabled = await firstValueFrom(
|
||||
this.configService.getFeatureFlag$(FeatureFlag.EventManagementForDataDogAndCrowdStrike),
|
||||
);
|
||||
|
||||
if (featureEnabled) {
|
||||
integrations.push(
|
||||
{
|
||||
name: OrganizationIntegrationServiceName.CrowdStrike,
|
||||
linkURL: "https://bitwarden.com/help/crowdstrike-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-crowdstrike-black.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
canSetupConnection: true,
|
||||
integrationType: OrganizationIntegrationType.Hec,
|
||||
},
|
||||
{
|
||||
name: OrganizationIntegrationServiceName.Datadog,
|
||||
linkURL: "https://bitwarden.com/help/datadog-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-datadog-color.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
canSetupConnection: true,
|
||||
integrationType: OrganizationIntegrationType.Datadog,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Add Huntress SIEM integration (separate feature flag)
|
||||
const huntressFeatureEnabled = await firstValueFrom(
|
||||
this.configService.getFeatureFlag$(FeatureFlag.EventManagementForHuntress),
|
||||
);
|
||||
|
||||
if (huntressFeatureEnabled) {
|
||||
integrations.push({
|
||||
name: OrganizationIntegrationServiceName.Huntress,
|
||||
linkURL: "https://bitwarden.com/help/huntress-siem/",
|
||||
image: "../../../../../../../images/integrations/logo-huntress-siem.svg",
|
||||
type: IntegrationType.EVENT,
|
||||
description: "huntressEventIntegrationDesc",
|
||||
canSetupConnection: true,
|
||||
integrationType: OrganizationIntegrationType.Hec,
|
||||
});
|
||||
}
|
||||
|
||||
const orgIntegrations = await firstValueFrom(
|
||||
this.organizationIntegrationService.integrations$.pipe(take(1)),
|
||||
);
|
||||
|
||||
const merged = integrations.map((i) => ({
|
||||
...i,
|
||||
organizationIntegration: orgIntegrations.find((o) => o.serviceName === i.name) ?? null,
|
||||
}));
|
||||
|
||||
this.state.setIntegrations(merged);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Injectable, signal } from "@angular/core";
|
||||
|
||||
import { Integration } from "@bitwarden/bit-common/dirt/organization-integrations/models/integration";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
|
||||
@Injectable()
|
||||
export class OrganizationIntegrationsState {
|
||||
private readonly _integrations = signal<Integration[]>([]);
|
||||
private readonly _organization = signal<Organization | undefined>(undefined);
|
||||
|
||||
// Signals
|
||||
integrations = this._integrations.asReadonly();
|
||||
organization = this._organization.asReadonly();
|
||||
|
||||
setOrganization(val: Organization | null) {
|
||||
this._organization.set(val ?? undefined);
|
||||
}
|
||||
|
||||
setIntegrations(val: Integration[]) {
|
||||
this._integrations.set(val);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
@let integrationsList = integrations();
|
||||
<section class="tw-mb-9">
|
||||
<h2 bitTypography="h2">{{ "singleSignOn" | i18n }}</h2>
|
||||
<p bitTypography="body1">
|
||||
{{ "ssoDescStart" | i18n }}
|
||||
<a bitLink routerLink="../settings/sso" class="tw-lowercase">{{ "singleSignOn" | i18n }}</a>
|
||||
{{ "ssoDescEnd" | i18n }}
|
||||
</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.SSO"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IntegrationType } from "@bitwarden/common/enums/integration-type.enum";
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
|
||||
import { IntegrationGridComponent } from "../integration-grid/integration-grid.component";
|
||||
import { FilterIntegrationsPipe } from "../integrations.pipe";
|
||||
import { OrganizationIntegrationsState } from "../organization-integrations.state";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "single-sign-on",
|
||||
templateUrl: "single-sign-on.component.html",
|
||||
imports: [SharedModule, IntegrationGridComponent, FilterIntegrationsPipe],
|
||||
})
|
||||
export class SingleSignOnComponent {
|
||||
integrations = this.state.integrations;
|
||||
IntegrationType = IntegrationType;
|
||||
|
||||
constructor(private state: OrganizationIntegrationsState) {}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@let org = organization();
|
||||
@let integrationsList = integrations();
|
||||
|
||||
<section class="tw-mb-9" *ngIf="org?.useScim">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "scimIntegration" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">
|
||||
{{ "scimIntegrationDescStart" | i18n }}
|
||||
<a bitLink routerLink="../settings/scim">{{ "scimIntegration" | i18n }}</a>
|
||||
{{ "scimIntegrationDescEnd" | i18n }}
|
||||
</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.SCIM"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
<section class="tw-mb-9" *ngIf="org?.useDirectory">
|
||||
<h2 bitTypography="h2">
|
||||
{{ "bwdc" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1">{{ "bwdcDesc" | i18n }}</p>
|
||||
<app-integration-grid
|
||||
[integrations]="integrationsList | filterIntegrations: IntegrationType.BWDC"
|
||||
></app-integration-grid>
|
||||
</section>
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IntegrationType } from "@bitwarden/common/enums/integration-type.enum";
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
|
||||
import { IntegrationGridComponent } from "../integration-grid/integration-grid.component";
|
||||
import { FilterIntegrationsPipe } from "../integrations.pipe";
|
||||
import { OrganizationIntegrationsState } from "../organization-integrations.state";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "user-provisioning",
|
||||
templateUrl: "user-provisioning.component.html",
|
||||
imports: [SharedModule, IntegrationGridComponent, FilterIntegrationsPipe],
|
||||
})
|
||||
export class UserProvisioningComponent {
|
||||
organization = this.state.organization;
|
||||
integrations = this.state.integrations;
|
||||
|
||||
constructor(private state: OrganizationIntegrationsState) {}
|
||||
|
||||
get IntegrationType(): typeof IntegrationType {
|
||||
return IntegrationType;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user