Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
Feature/families for enterprise (#549)
Browse files Browse the repository at this point in the history
* Families for enterprise/account settings (#541)

* Add node tests to pipeline (#525)

* Add support for crypto agent (#520)

* feat: add an importer for Safari (CSV) (#512)

* feat(importers/safariCsvImporter): add the importer for Safari (CSV)

* Revert changes to package-lock.json

Co-authored-by: Thomas Rittson <trittson@bitwarden.com>

* Dynamically set electron user agent (#524)

* Dynamically set electron user agent

* PR review

* linter fixes

* Test agent static version does not change

* Fix formatting

* Add role="alert" to callouts only when enforceAlert is passed (#528)

* Add role="alert" to callouts when enforceAlert is passed

* Remove ElementRef and do a different way

* Rename input variable

* Add PR template (#529)

* Allow managers to create collections (#530)

* Pass in null for sso organziation for now. (#531)

This will bypass cryptoagent

* Add Linked Field as custom field type (#431)

* Basic proof of concept of Linked custom fields

* Linked Fields for all cipher types, use dropdown

* Move linkedFieldOptions to view models

* Move add-edit custom fields to own component

* Fix change handling if cipherType changes

* Use Field.LinkedId to store linked field info

* Refactor accessors in cipherView for type safety

* Use map for linkedFieldOptions

* Refactor: use decorators to record linkable info

* Add ItemView

* Use enums for linked field ids

* Add union type for linkedId enums, add jsdoc comment

* Use parameter properties for linkedFieldOption

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Fix type casting

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Update electron to 14.2.0 (#534)

* Update electron to 14.1.1

* Update electron to 14.2.0 and fix it to this version

* Removed ^ from electron in electron/package-lock.json

* [Linked fields] Reset linkedIds if cipher type changes (#535)

* Reset linkedIds if cipher type changes

* Only reset linkedId if !editmode

* Add call to server

* Fix linting

* Add call to server

* Fix linting

* Run linting

* Add new properties to organization

* Remove organizationUserId from request model

* Added in org sponsorship calls

* Sponsorship redeem existing org flow

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>
Co-authored-by: Oscar Hinton <oscar@oscarhinton.com>
Co-authored-by: pan93412 <pan93412@gmail.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Robyn MacCallum <nickersthecat@gmail.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>

* Revoke sponsorship uses organization id

* Expect information in billing items on whether the item is sponsored

* Families for enterprise/redeem card (#546)

* Add userservice helper

* Run linter

* Add resend email to api service (#548)

* Remove unneeded imports

* Remove unneeded files

* Add newline

* Reorder import

* Remove accidental newline

* Fix lint issue

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>
Co-authored-by: Oscar Hinton <oscar@oscarhinton.com>
Co-authored-by: pan93412 <pan93412@gmail.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Robyn MacCallum <nickersthecat@gmail.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
  • Loading branch information
8 people committed Nov 19, 2021
1 parent f4c66b2 commit b4f4752
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 0 deletions.
8 changes: 8 additions & 0 deletions common/src/abstractions/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import { ImportOrganizationCiphersRequest } from '../models/request/importOrgani
import { KdfRequest } from '../models/request/kdfRequest';
import { KeyConnectorUserKeyRequest } from '../models/request/keyConnectorUserKeyRequest';
import { KeysRequest } from '../models/request/keysRequest';
import { OrganizationSponsorshipCreateRequest } from '../models/request/organization/organizationSponsorshipCreateRequest';
import { OrganizationSponsorshipRedeemRequest } from '../models/request/organization/organizationSponsorshipRedeemRequest';
import { OrganizationSsoRequest } from '../models/request/organization/organizationSsoRequest';
import { OrganizationCreateRequest } from '../models/request/organizationCreateRequest';
import { OrganizationImportRequest } from '../models/request/organizationImportRequest';
Expand Down Expand Up @@ -453,6 +455,12 @@ export abstract class ApiService {

preValidateSso: (identifier: string) => Promise<boolean>;

postCreateSponsorship: (sponsorshipOrgId: string, request: OrganizationSponsorshipCreateRequest) => Promise<void>;
deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise<void>;
deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise<void>;
postRedeemSponsorship: (sponsorshipToken: string, request: OrganizationSponsorshipRedeemRequest) => Promise<void>;
postResendSponsorshipOffer: (sponsoringOrgId: string) => Promise<void>;

getUserKeyFromKeyConnector: (keyConnectorUrl: string) => Promise<KeyConnectorUserKeyResponse>;
postUserKeyToKeyConnector: (keyConnectorUrl: string, request: KeyConnectorUserKeyRequest) => Promise<void>;
getKeyConnectorAlive: (keyConnectorUrl: string) => Promise<void>;
Expand Down
1 change: 1 addition & 0 deletions common/src/abstractions/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export abstract class UserService {
clear: () => Promise<any>;
isAuthenticated: () => Promise<boolean>;
canAccessPremium: () => Promise<boolean>;
canManageSponsorships: () => Promise<boolean>;
getOrganization: (id: string) => Promise<Organization>;
getOrganizationByIdentifier: (identifier: string) => Promise<Organization>;
getAllOrganizations: () => Promise<Organization[]>;
Expand Down
3 changes: 3 additions & 0 deletions common/src/enums/planSponsorshipType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum PlanSponsorshipType {
FamiliesForEnterprise = 0,
}
8 changes: 8 additions & 0 deletions common/src/models/data/organizationData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { ProfileOrganizationResponse } from '../response/profileOrganizationResp

import { OrganizationUserStatusType } from '../../enums/organizationUserStatusType';
import { OrganizationUserType } from '../../enums/organizationUserType';
import { ProductType } from '../../enums/productType';

import { PermissionsApi } from '../api/permissionsApi';

export class OrganizationData {
Expand Down Expand Up @@ -34,6 +36,9 @@ export class OrganizationData {
providerId: string;
providerName: string;
isProviderUser: boolean;
familySponsorshipFriendlyName: string;
familySponsorshipAvailable: boolean;
planProductType: ProductType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;

Expand Down Expand Up @@ -66,6 +71,9 @@ export class OrganizationData {
this.hasPublicAndPrivateKeys = response.hasPublicAndPrivateKeys;
this.providerId = response.providerId;
this.providerName = response.providerName;
this.familySponsorshipFriendlyName = response.familySponsorshipFriendlyName;
this.familySponsorshipAvailable = response.familySponsorshipAvailable;
this.planProductType = response.planProductType;
this.keyConnectorEnabled = response.keyConnectorEnabled;
this.keyConnectorUrl = response.keyConnectorUrl;
}
Expand Down
7 changes: 7 additions & 0 deletions common/src/models/domain/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { OrganizationData } from '../data/organizationData';

import { OrganizationUserStatusType } from '../../enums/organizationUserStatusType';
import { OrganizationUserType } from '../../enums/organizationUserType';
import { ProductType } from '../../enums/productType';
import { PermissionsApi } from '../api/permissionsApi';


Expand Down Expand Up @@ -35,6 +36,9 @@ export class Organization {
providerId: string;
providerName: string;
isProviderUser: boolean;
familySponsorshipFriendlyName: string;
familySponsorshipAvailable: boolean;
planProductType: ProductType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;

Expand Down Expand Up @@ -72,6 +76,9 @@ export class Organization {
this.providerId = obj.providerId;
this.providerName = obj.providerName;
this.isProviderUser = obj.isProviderUser;
this.familySponsorshipFriendlyName = obj.familySponsorshipFriendlyName;
this.familySponsorshipAvailable = obj.familySponsorshipAvailable;
this.planProductType = obj.planProductType;
this.keyConnectorEnabled = obj.keyConnectorEnabled;
this.keyConnectorUrl = obj.keyConnectorUrl;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PlanSponsorshipType } from '../../../enums/planSponsorshipType';

export class OrganizationSponsorshipCreateRequest {
sponsoredEmail: string;
planSponsorshipType: PlanSponsorshipType;
friendlyName: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { PlanSponsorshipType } from '../../../enums/planSponsorshipType';

export class OrganizationSponsorshipRedeemRequest {
planSponsorshipType: PlanSponsorshipType;
sponsoredOrganizationId: string;
}
7 changes: 7 additions & 0 deletions common/src/models/response/profileOrganizationResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BaseResponse } from './baseResponse';

import { OrganizationUserStatusType } from '../../enums/organizationUserStatusType';
import { OrganizationUserType } from '../../enums/organizationUserType';
import { ProductType } from '../../enums/productType';
import { PermissionsApi } from '../api/permissionsApi';

export class ProfileOrganizationResponse extends BaseResponse {
Expand Down Expand Up @@ -34,6 +35,9 @@ export class ProfileOrganizationResponse extends BaseResponse {
userId: string;
providerId: string;
providerName: string;
familySponsorshipFriendlyName: string;
familySponsorshipAvailable: boolean;
planProductType: ProductType;
keyConnectorEnabled: boolean;
keyConnectorUrl: string;

Expand Down Expand Up @@ -68,6 +72,9 @@ export class ProfileOrganizationResponse extends BaseResponse {
this.userId = this.getResponseProperty('UserId');
this.providerId = this.getResponseProperty('ProviderId');
this.providerName = this.getResponseProperty('ProviderName');
this.familySponsorshipFriendlyName = this.getResponseProperty('FamilySponsorshipFriendlyName');
this.familySponsorshipAvailable = this.getResponseProperty('FamilySponsorshipAvailable');
this.planProductType = this.getResponseProperty('PlanProductType');
this.keyConnectorEnabled = this.getResponseProperty('KeyConnectorEnabled') ?? false;
this.keyConnectorUrl = this.getResponseProperty('KeyConnectorUrl');
}
Expand Down
2 changes: 2 additions & 0 deletions common/src/models/response/subscriptionResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,15 @@ export class BillingSubscriptionItemResponse extends BaseResponse {
amount: number;
quantity: number;
interval: string;
sponsoredSubscriptionItem: boolean;

constructor(response: any) {
super(response);
this.name = this.getResponseProperty('Name');
this.amount = this.getResponseProperty('Amount');
this.quantity = this.getResponseProperty('Quantity');
this.interval = this.getResponseProperty('Interval');
this.sponsoredSubscriptionItem = this.getResponseProperty('SponsoredSubscriptionItem');
}
}

Expand Down
33 changes: 33 additions & 0 deletions common/src/services/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import { ImportDirectoryRequest } from '../models/request/importDirectoryRequest
import { ImportOrganizationCiphersRequest } from '../models/request/importOrganizationCiphersRequest';
import { KdfRequest } from '../models/request/kdfRequest';
import { KeysRequest } from '../models/request/keysRequest';
import { OrganizationSponsorshipCreateRequest } from '../models/request/organization/organizationSponsorshipCreateRequest';
import { OrganizationSponsorshipRedeemRequest } from '../models/request/organization/organizationSponsorshipRedeemRequest';
import { OrganizationSsoRequest } from '../models/request/organization/organizationSsoRequest';
import { OrganizationCreateRequest } from '../models/request/organizationCreateRequest';
import { OrganizationImportRequest } from '../models/request/organizationImportRequest';
Expand Down Expand Up @@ -172,6 +174,8 @@ import { KeyConnectorUserKeyRequest } from '../models/request/keyConnectorUserKe
import { KeyConnectorUserKeyResponse } from '../models/response/keyConnectorUserKeyResponse';
import { SendAccessView } from '../models/view/sendAccessView';



export class ApiService implements ApiServiceAbstraction {
protected apiKeyRefresh: (clientId: string, clientSecret: string) => Promise<any>;
private device: DeviceType;
Expand Down Expand Up @@ -1558,6 +1562,35 @@ export class ApiService implements ApiServiceAbstraction {
}
}

async postCreateSponsorship(sponsoredOrgId: string, request: OrganizationSponsorshipCreateRequest): Promise<void> {
return await this.send('POST',
'/organization/sponsorship/' + sponsoredOrgId + '/families-for-enterprise',
request, true, false);
}

async deleteRevokeSponsorship(sponsoringOrganizationId: string): Promise<void> {
return await this.send('DELETE',
'/organization/sponsorship/' + sponsoringOrganizationId,
null, true, false);
}

async deleteRemoveSponsorship(sponsoringOrgId: string): Promise<void> {
return await this.send('DELETE',
'/organization/sponsorship/sponsored/' + sponsoringOrgId,
null, true, false);
}
async postRedeemSponsorship(sponsorshipToken: string, request: OrganizationSponsorshipRedeemRequest): Promise<void> {
return await this.send('POST', '/organization/sponsorship/redeem?sponsorshipToken=' + encodeURIComponent(sponsorshipToken),
request, true, false);
}

async postResendSponsorshipOffer(sponsoringOrgId: string): Promise<void> {
return await this.send('POST',
'/organization/sponsorship/' + sponsoringOrgId + '/families-for-enterprise/resend',
null, true, false);
}


protected async doAuthRefresh(): Promise<void> {
const refreshToken = await this.tokenService.getRefreshToken();
if (refreshToken != null && refreshToken !== '') {
Expand Down
5 changes: 5 additions & 0 deletions common/src/services/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ export class UserService implements UserServiceAbstraction {
return false;
}

async canManageSponsorships(): Promise<boolean> {
const orgs = await this.getAllOrganizations();
return orgs.some(o => o.familySponsorshipAvailable || o.familySponsorshipFriendlyName !== null);
}

async getOrganization(id: string): Promise<Organization> {
const userId = await this.getUserId();
const organizations = await this.storageService.get<{ [id: string]: OrganizationData; }>(
Expand Down

0 comments on commit b4f4752

Please sign in to comment.