mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-28 12:45:45 +01:00
[EC-243] Grant premium status when member accepts org invite (#2870)
* Rename setCanAccessPremium to setHasPremiumPersonally * Add hasPremiumFromOrganization * Refactor stateService methods * Add getHasPremiumPersonally, deprecate tokenService.getPremium
This commit is contained in:
parent
29f95cdb7d
commit
b92685dcd9
@ -45,8 +45,8 @@ export class PremiumComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
this.canAccessPremium = await this.stateService.getCanAccessPremium();
|
||||
const premium = await this.tokenService.getPremium();
|
||||
if (premium) {
|
||||
const premiumPersonally = await this.stateService.getHasPremiumPersonally();
|
||||
if (premiumPersonally) {
|
||||
this.router.navigate(["/settings/subscription/user-subscription"]);
|
||||
return;
|
||||
}
|
||||
|
@ -51,9 +51,9 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.premium = await this.tokenService.getPremium();
|
||||
this.premium = await this.stateService.getHasPremiumPersonally();
|
||||
this.hasFamilySponsorshipAvailable = await this.organizationService.canManageSponsorships();
|
||||
const hasPremiumFromOrg = await this.stateService.getCanAccessPremium();
|
||||
const hasPremiumFromOrg = await this.stateService.getHasPremiumFromOrganization();
|
||||
let billing = null;
|
||||
if (!this.selfHosted) {
|
||||
billing = await this.apiService.getUserBillingHistory();
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { TokenService } from "jslib-common/abstractions/token.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-subscription",
|
||||
@ -12,12 +12,12 @@ export class SubscriptionComponent {
|
||||
selfHosted: boolean;
|
||||
|
||||
constructor(
|
||||
private tokenService: TokenService,
|
||||
private stateService: StateService,
|
||||
private platformUtilsService: PlatformUtilsService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.hasPremium = await this.tokenService.getPremium();
|
||||
this.hasPremium = await this.stateService.getHasPremiumPersonally();
|
||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { TokenService } from "jslib-common/abstractions/token.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { SubscriptionResponse } from "jslib-common/models/response/subscriptionResponse";
|
||||
|
||||
@Component({
|
||||
@ -25,7 +25,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
reinstatePromise: Promise<any>;
|
||||
|
||||
constructor(
|
||||
private tokenService: TokenService,
|
||||
private stateService: StateService,
|
||||
private apiService: ApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
@ -45,7 +45,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.tokenService.getPremium()) {
|
||||
if (this.stateService.getHasPremiumPersonally()) {
|
||||
this.loading = true;
|
||||
this.sub = await this.apiService.getUserSubscription();
|
||||
} else {
|
||||
|
@ -58,7 +58,10 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getBiometricUnlock: (options?: StorageOptions) => Promise<boolean>;
|
||||
setBiometricUnlock: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getCanAccessPremium: (options?: StorageOptions) => Promise<boolean>;
|
||||
setCanAccessPremium: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getHasPremiumPersonally: (options?: StorageOptions) => Promise<boolean>;
|
||||
setHasPremiumPersonally: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
setHasPremiumFromOrganization: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getHasPremiumFromOrganization: (options?: StorageOptions) => Promise<boolean>;
|
||||
getClearClipboard: (options?: StorageOptions) => Promise<number>;
|
||||
setClearClipboard: (value: number, options?: StorageOptions) => Promise<void>;
|
||||
getCollapsedGroupings: (options?: StorageOptions) => Promise<string[]>;
|
||||
|
@ -26,7 +26,6 @@ export abstract class TokenService {
|
||||
getEmail: () => Promise<string>;
|
||||
getEmailVerified: () => Promise<boolean>;
|
||||
getName: () => Promise<string>;
|
||||
getPremium: () => Promise<boolean>;
|
||||
getIssuer: () => Promise<string>;
|
||||
getIsExternal: () => Promise<boolean>;
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ export class AccountProfile {
|
||||
everBeenUnlocked?: boolean;
|
||||
forcePasswordReset?: boolean;
|
||||
hasPremiumPersonally?: boolean;
|
||||
hasPremiumFromOrganization?: boolean;
|
||||
lastSync?: string;
|
||||
userId?: string;
|
||||
usesKeyConnector?: boolean;
|
||||
|
@ -9,7 +9,8 @@ export class ProfileResponse extends BaseResponse {
|
||||
email: string;
|
||||
emailVerified: boolean;
|
||||
masterPasswordHint: string;
|
||||
premium: boolean;
|
||||
premiumPersonally: boolean;
|
||||
premiumFromOrganization: boolean;
|
||||
culture: string;
|
||||
twoFactorEnabled: boolean;
|
||||
key: string;
|
||||
@ -28,7 +29,8 @@ export class ProfileResponse extends BaseResponse {
|
||||
this.email = this.getResponseProperty("Email");
|
||||
this.emailVerified = this.getResponseProperty("EmailVerified");
|
||||
this.masterPasswordHint = this.getResponseProperty("MasterPasswordHint");
|
||||
this.premium = this.getResponseProperty("Premium");
|
||||
this.premiumPersonally = this.getResponseProperty("Premium");
|
||||
this.premiumFromOrganization = this.getResponseProperty("PremiumFromOrganization");
|
||||
this.culture = this.getResponseProperty("Culture");
|
||||
this.twoFactorEnabled = this.getResponseProperty("TwoFactorEnabled");
|
||||
this.key = this.getResponseProperty("Key");
|
||||
|
@ -337,13 +337,41 @@ export class StateService<
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
(await this.getHasPremiumPersonally(options)) ||
|
||||
(await this.getHasPremiumFromOrganization(options))
|
||||
);
|
||||
}
|
||||
|
||||
async getHasPremiumPersonally(options?: StorageOptions): Promise<boolean> {
|
||||
const account = await this.getAccount(
|
||||
this.reconcileOptions(options, await this.defaultOnDiskOptions())
|
||||
);
|
||||
if (account.profile.hasPremiumPersonally) {
|
||||
return account?.profile?.hasPremiumPersonally;
|
||||
}
|
||||
|
||||
async setHasPremiumPersonally(value: boolean, options?: StorageOptions): Promise<void> {
|
||||
const account = await this.getAccount(
|
||||
this.reconcileOptions(options, await this.defaultOnDiskOptions())
|
||||
);
|
||||
account.profile.hasPremiumPersonally = value;
|
||||
await this.saveAccount(
|
||||
account,
|
||||
this.reconcileOptions(options, await this.defaultOnDiskOptions())
|
||||
);
|
||||
}
|
||||
|
||||
async getHasPremiumFromOrganization(options?: StorageOptions): Promise<boolean> {
|
||||
const account = await this.getAccount(
|
||||
this.reconcileOptions(options, await this.defaultOnDiskOptions())
|
||||
);
|
||||
|
||||
if (account.profile?.hasPremiumFromOrganization) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: older server versions won't send the hasPremiumFromOrganization flag, so we're keeping the old logic
|
||||
// for backwards compatibility. It can be removed after everyone has upgraded.
|
||||
const organizations = await this.getOrganizations(options);
|
||||
if (organizations == null) {
|
||||
return false;
|
||||
@ -359,11 +387,11 @@ export class StateService<
|
||||
return false;
|
||||
}
|
||||
|
||||
async setCanAccessPremium(value: boolean, options?: StorageOptions): Promise<void> {
|
||||
async setHasPremiumFromOrganization(value: boolean, options?: StorageOptions): Promise<void> {
|
||||
const account = await this.getAccount(
|
||||
this.reconcileOptions(options, await this.defaultOnDiskOptions())
|
||||
);
|
||||
account.profile.hasPremiumPersonally = value;
|
||||
account.profile.hasPremiumFromOrganization = value;
|
||||
await this.saveAccount(
|
||||
account,
|
||||
this.reconcileOptions(options, await this.defaultOnDiskOptions())
|
||||
|
@ -304,7 +304,8 @@ export class SyncService implements SyncServiceAbstraction {
|
||||
await this.cryptoService.setOrgKeys(response.organizations, response.providerOrganizations);
|
||||
await this.stateService.setSecurityStamp(response.securityStamp);
|
||||
await this.stateService.setEmailVerified(response.emailVerified);
|
||||
await this.stateService.setCanAccessPremium(response.premium);
|
||||
await this.stateService.setHasPremiumPersonally(response.premiumPersonally);
|
||||
await this.stateService.setHasPremiumFromOrganization(response.premiumFromOrganization);
|
||||
await this.stateService.setForcePasswordReset(response.forcePasswordReset);
|
||||
await this.keyConnectorService.setUsesKeyConnector(response.usesKeyConnector);
|
||||
|
||||
|
@ -169,15 +169,6 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
return decoded.name as string;
|
||||
}
|
||||
|
||||
async getPremium(): Promise<boolean> {
|
||||
const decoded = await this.decodeToken();
|
||||
if (typeof decoded.premium === "undefined") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return decoded.premium as boolean;
|
||||
}
|
||||
|
||||
async getIssuer(): Promise<string> {
|
||||
const decoded = await this.decodeToken();
|
||||
if (typeof decoded.iss === "undefined") {
|
||||
|
Loading…
Reference in New Issue
Block a user