[AC-1046] activate autofill on page load policy (#4860)
* [EC-1046] add activate autofill policy to web * [EC-1046] add local setting if policy needs to be set * [AC-1046] activate autofill on page load if flag exists * [AC-1046] move activation to current tab page * [AC-1046] add warning to autofill policy * [AC-1046] add useActivateAutofillPolicy to organization reponse * [AC-1046] autofill to auto-fill
This commit is contained in:
parent
e8faf12ac1
commit
7892834f97
|
@ -2120,6 +2120,9 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"autofillPageLoadPolicyActivated": {
|
||||
"message": "Your organization policies have turned on auto-fill on page load."
|
||||
},
|
||||
"howToAutofill": {
|
||||
"message": "How to auto-fill"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { BehaviorSubject } from "rxjs";
|
||||
import { BehaviorSubject, filter, map, Observable, switchMap, tap } from "rxjs";
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization/organization.service.abstraction";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||
import { Policy } from "@bitwarden/common/models/domain/policy";
|
||||
import { PolicyService } from "@bitwarden/common/services/policy/policy.service";
|
||||
|
||||
|
@ -13,4 +16,29 @@ export class BrowserPolicyService extends PolicyService {
|
|||
initializeAs: "array",
|
||||
})
|
||||
protected _policies: BehaviorSubject<Policy[]>;
|
||||
|
||||
constructor(stateService: StateService, organizationService: OrganizationService) {
|
||||
super(stateService, organizationService);
|
||||
this._policies.pipe(this.handleActivateAutofillPolicy.bind(this)).subscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the ActivateAutofill policy is enabled, save a flag indicating if we need to
|
||||
* enable Autofill on page load.
|
||||
*/
|
||||
private handleActivateAutofillPolicy(policies$: Observable<Policy[]>) {
|
||||
return policies$.pipe(
|
||||
map((policies) => policies.find((p) => p.type == PolicyType.ActivateAutofill && p.enabled)),
|
||||
filter((p) => p != null),
|
||||
switchMap(async (_) => [
|
||||
await this.stateService.getActivateAutoFillOnPageLoadFromPolicy(),
|
||||
await this.stateService.getEnableAutoFillOnPageLoad(),
|
||||
]),
|
||||
tap(([activated, autofillEnabled]) => {
|
||||
if (activated === undefined) {
|
||||
this.stateService.setActivateAutoFillOnPageLoadFromPolicy(!autofillEnabled);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,17 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
|||
this.search$
|
||||
.pipe(debounceTime(500), takeUntil(this.destroy$))
|
||||
.subscribe(() => this.searchVault());
|
||||
|
||||
// activate autofill on page load if policy is set
|
||||
if (await this.stateService.getActivateAutoFillOnPageLoadFromPolicy()) {
|
||||
await this.stateService.setEnableAutoFillOnPageLoad(true);
|
||||
await this.stateService.setActivateAutoFillOnPageLoadFromPolicy(false);
|
||||
this.platformUtilsService.showToast(
|
||||
"info",
|
||||
null,
|
||||
this.i18nService.t("autofillPageLoadPolicyActivated")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
|
|
@ -6,6 +6,7 @@ import { first } from "rxjs/operators";
|
|||
|
||||
import { VaultFilter } from "@bitwarden/angular/vault/vault-filter/models/vault-filter.model";
|
||||
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
|
@ -72,6 +73,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
|
|||
private allCiphers: CipherView[] = null;
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private cipherService: CipherService,
|
||||
private router: Router,
|
||||
private ngZone: NgZone,
|
||||
|
|
|
@ -4853,6 +4853,18 @@
|
|||
"personalVaultExportPolicyInEffect": {
|
||||
"message": "One or more organization policies prevents you from exporting your individual vault."
|
||||
},
|
||||
"activateAutofill": {
|
||||
"message": "Activate auto-fill"
|
||||
},
|
||||
"activateAutofillDesc": {
|
||||
"message": "Activate the auto-fill with page load settings on the browser extension for all existing and new members."
|
||||
},
|
||||
"experimentalFeature": {
|
||||
"message": "Compromised or untrusted websites can exploit auto-fill on page load."
|
||||
},
|
||||
"learnMoreAboutAutofill": {
|
||||
"message": "Learn more about auto-fill"
|
||||
},
|
||||
"selectType": {
|
||||
"message": "Select SSO type"
|
||||
},
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
|||
|
||||
import { AppComponent as BaseAppComponent } from "@bitwarden/web-vault/app/app.component";
|
||||
|
||||
import { ActivateAutofillPolicy } from "./policies/activate-autofill.component";
|
||||
import { DisablePersonalVaultExportPolicy } from "./policies/disable-personal-vault-export.component";
|
||||
import { MaximumVaultTimeoutPolicy } from "./policies/maximum-vault-timeout.component";
|
||||
|
||||
|
@ -16,6 +17,7 @@ export class AppComponent extends BaseAppComponent {
|
|||
this.policyListService.addPolicies([
|
||||
new MaximumVaultTimeoutPolicy(),
|
||||
new DisablePersonalVaultExportPolicy(),
|
||||
new ActivateAutofillPolicy(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import { WildcardRoutingModule } from "@bitwarden/web-vault/app/wildcard-routing
|
|||
import { AppRoutingModule } from "./app-routing.module";
|
||||
import { AppComponent } from "./app.component";
|
||||
import { OrganizationsModule } from "./organizations/organizations.module";
|
||||
import { ActivateAutofillPolicyComponent } from "./policies/activate-autofill.component";
|
||||
import { DisablePersonalVaultExportPolicyComponent } from "./policies/disable-personal-vault-export.component";
|
||||
import { MaximumVaultTimeoutPolicyComponent } from "./policies/maximum-vault-timeout.component";
|
||||
|
||||
|
@ -39,6 +40,7 @@ import { MaximumVaultTimeoutPolicyComponent } from "./policies/maximum-vault-tim
|
|||
AppComponent,
|
||||
DisablePersonalVaultExportPolicyComponent,
|
||||
MaximumVaultTimeoutPolicyComponent,
|
||||
ActivateAutofillPolicyComponent,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<app-callout type="warning">
|
||||
{{ "experimentalFeature" | i18n }}
|
||||
<a href="https://bitwarden.com/help/auto-fill-browser/" target="_blank" rel="noopener">{{
|
||||
"learnMoreAboutAutofill" | i18n
|
||||
}}</a>
|
||||
</app-callout>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
[formControl]="enabled"
|
||||
name="Enabled"
|
||||
/>
|
||||
<label class="form-check-label" for="enabled">{{ "turnOn" | i18n }}</label>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,25 @@
|
|||
import { Component } from "@angular/core";
|
||||
|
||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||
import {
|
||||
BasePolicy,
|
||||
BasePolicyComponent,
|
||||
} from "@bitwarden/web-vault/app/organizations/policies/base-policy.component";
|
||||
|
||||
export class ActivateAutofillPolicy extends BasePolicy {
|
||||
name = "activateAutofill";
|
||||
description = "activateAutofillDesc";
|
||||
type = PolicyType.ActivateAutofill;
|
||||
component = ActivateAutofillPolicyComponent;
|
||||
|
||||
display(organization: Organization) {
|
||||
return organization.useActivateAutofillPolicy;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "policy-activate-autofill",
|
||||
templateUrl: "activate-autofill.component.html",
|
||||
})
|
||||
export class ActivateAutofillPolicyComponent extends BasePolicyComponent {}
|
|
@ -358,7 +358,13 @@ export abstract class StateService<T extends Account = Account> {
|
|||
|
||||
getAvatarColor: (options?: StorageOptions) => Promise<string | null | undefined>;
|
||||
setAvatarColor: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
|
||||
getActivateAutoFillOnPageLoadFromPolicy: (
|
||||
options?: StorageOptions
|
||||
) => Promise<boolean | undefined>;
|
||||
setActivateAutoFillOnPageLoadFromPolicy: (
|
||||
value: boolean,
|
||||
options?: StorageOptions
|
||||
) => Promise<void>;
|
||||
getSMOnboardingTasks: (
|
||||
options?: StorageOptions
|
||||
) => Promise<Record<string, Record<string, boolean>>>;
|
||||
|
|
|
@ -10,4 +10,5 @@ export enum PolicyType {
|
|||
ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow
|
||||
MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout
|
||||
DisablePersonalVaultExport = 10, // Disable personal vault export
|
||||
ActivateAutofill = 11, // Activates autofill with page load on the browser extension
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ export class OrganizationData {
|
|||
useCustomPermissions: boolean;
|
||||
useResetPassword: boolean;
|
||||
useSecretsManager: boolean;
|
||||
useActivateAutofillPolicy: boolean;
|
||||
selfHost: boolean;
|
||||
usersGetPremium: boolean;
|
||||
seats: number;
|
||||
|
@ -66,6 +67,7 @@ export class OrganizationData {
|
|||
this.useCustomPermissions = response.useCustomPermissions;
|
||||
this.useResetPassword = response.useResetPassword;
|
||||
this.useSecretsManager = response.useSecretsManager;
|
||||
this.useActivateAutofillPolicy = response.useActivateAutofillPolicy;
|
||||
this.selfHost = response.selfHost;
|
||||
this.usersGetPremium = response.usersGetPremium;
|
||||
this.seats = response.seats;
|
||||
|
|
|
@ -238,6 +238,7 @@ export class AccountSettings {
|
|||
serverConfig?: ServerConfigData;
|
||||
approveLoginRequests?: boolean;
|
||||
avatarColor?: string;
|
||||
activateAutoFillOnPageLoadFromPolicy?: boolean;
|
||||
smOnboardingTasks?: Record<string, Record<string, boolean>>;
|
||||
|
||||
static fromJSON(obj: Jsonify<AccountSettings>): AccountSettings {
|
||||
|
|
|
@ -25,6 +25,7 @@ export class Organization {
|
|||
useCustomPermissions: boolean;
|
||||
useResetPassword: boolean;
|
||||
useSecretsManager: boolean;
|
||||
useActivateAutofillPolicy: boolean;
|
||||
selfHost: boolean;
|
||||
usersGetPremium: boolean;
|
||||
seats: number;
|
||||
|
@ -72,6 +73,7 @@ export class Organization {
|
|||
this.useCustomPermissions = obj.useCustomPermissions;
|
||||
this.useResetPassword = obj.useResetPassword;
|
||||
this.useSecretsManager = obj.useSecretsManager;
|
||||
this.useActivateAutofillPolicy = obj.useActivateAutofillPolicy;
|
||||
this.selfHost = obj.selfHost;
|
||||
this.usersGetPremium = obj.usersGetPremium;
|
||||
this.seats = obj.seats;
|
||||
|
|
|
@ -21,6 +21,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
|||
useCustomPermissions: boolean;
|
||||
useResetPassword: boolean;
|
||||
useSecretsManager: boolean;
|
||||
useActivateAutofillPolicy: boolean;
|
||||
selfHost: boolean;
|
||||
usersGetPremium: boolean;
|
||||
seats: number;
|
||||
|
@ -65,6 +66,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
|||
this.useCustomPermissions = this.getResponseProperty("UseCustomPermissions") ?? false;
|
||||
this.useResetPassword = this.getResponseProperty("UseResetPassword");
|
||||
this.useSecretsManager = this.getResponseProperty("UseSecretsManager");
|
||||
this.useActivateAutofillPolicy = this.getResponseProperty("UseActivateAutofillPolicy");
|
||||
this.selfHost = this.getResponseProperty("SelfHost");
|
||||
this.usersGetPremium = this.getResponseProperty("UsersGetPremium");
|
||||
this.seats = this.getResponseProperty("Seats");
|
||||
|
|
|
@ -21,7 +21,7 @@ export class PolicyService implements InternalPolicyServiceAbstraction {
|
|||
policies$ = this._policies.asObservable();
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
protected stateService: StateService,
|
||||
private organizationService: OrganizationService
|
||||
) {
|
||||
this.stateService.activeAccountUnlocked$
|
||||
|
|
|
@ -2365,6 +2365,26 @@ export class StateService<
|
|||
);
|
||||
}
|
||||
|
||||
async getActivateAutoFillOnPageLoadFromPolicy(options?: StorageOptions): Promise<boolean> {
|
||||
return (
|
||||
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()))
|
||||
)?.settings?.activateAutoFillOnPageLoadFromPolicy;
|
||||
}
|
||||
|
||||
async setActivateAutoFillOnPageLoadFromPolicy(
|
||||
value: boolean,
|
||||
options?: StorageOptions
|
||||
): Promise<void> {
|
||||
const account = await this.getAccount(
|
||||
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())
|
||||
);
|
||||
account.settings.activateAutoFillOnPageLoadFromPolicy = value;
|
||||
return await this.saveAccount(
|
||||
account,
|
||||
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())
|
||||
);
|
||||
}
|
||||
|
||||
async getSMOnboardingTasks(
|
||||
options?: StorageOptions
|
||||
): Promise<Record<string, Record<string, boolean>>> {
|
||||
|
|
Loading…
Reference in New Issue