import { firstValueFrom, map, switchMap } from "rxjs"; import { ApiService } from "../../../abstractions/api.service"; import { AccountService } from "../../../auth/abstractions/account.service"; import { getUserId } from "../../../auth/services/account.service"; import { HttpStatusCode } from "../../../enums"; import { ErrorResponse } from "../../../models/response/error.response"; import { ListResponse } from "../../../models/response/list.response"; import { Utils } from "../../../platform/misc/utils"; import { PolicyApiServiceAbstraction } from "../../abstractions/policy/policy-api.service.abstraction"; import { InternalPolicyService } from "../../abstractions/policy/policy.service.abstraction"; import { PolicyType } from "../../enums"; import { PolicyData } from "../../models/data/policy.data"; import { MasterPasswordPolicyOptions } from "../../models/domain/master-password-policy-options"; import { Policy } from "../../models/domain/policy"; import { PolicyRequest } from "../../models/request/policy.request"; import { PolicyResponse } from "../../models/response/policy.response"; export class PolicyApiService implements PolicyApiServiceAbstraction { constructor( private policyService: InternalPolicyService, private apiService: ApiService, private accountService: AccountService, ) {} async getPolicy(organizationId: string, type: PolicyType): Promise { const r = await this.apiService.send( "GET", "/organizations/" + organizationId + "/policies/" + type, null, true, true, ); return new PolicyResponse(r); } async getPolicies(organizationId: string): Promise> { const r = await this.apiService.send( "GET", "/organizations/" + organizationId + "/policies", null, true, true, ); return new ListResponse(r, PolicyResponse); } async getPoliciesByToken( organizationId: string, token: string, email: string, organizationUserId: string, ): Promise { const r = await this.apiService.send( "GET", "/organizations/" + organizationId + "/policies/token?" + "token=" + encodeURIComponent(token) + "&email=" + Utils.encodeRFC3986URIComponent(email) + "&organizationUserId=" + organizationUserId, null, false, true, ); return Policy.fromListResponse(new ListResponse(r, PolicyResponse)); } private async getMasterPasswordPolicyResponseForOrgUser( organizationId: string, ): Promise { const response = await this.apiService.send( "GET", "/organizations/" + organizationId + "/policies/master-password", null, true, true, ); return new PolicyResponse(response); } async getMasterPasswordPolicyOptsForOrgUser( orgId: string, ): Promise { try { const masterPasswordPolicyResponse = await this.getMasterPasswordPolicyResponseForOrgUser(orgId); const masterPasswordPolicy = Policy.fromResponse(masterPasswordPolicyResponse); if (!masterPasswordPolicy) { return null; } return firstValueFrom( this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId, [masterPasswordPolicy]), ), map((policy) => policy ?? null), ), ); } catch (error) { // If policy not found, return null if (error instanceof ErrorResponse && error.statusCode === HttpStatusCode.NotFound) { return null; } // otherwise rethrow error throw error; } } async putPolicy(organizationId: string, type: PolicyType, request: PolicyRequest): Promise { const response = await this.apiService.send( "PUT", "/organizations/" + organizationId + "/policies/" + type, request, true, true, ); await this.handleResponse(response); } async putPolicyVNext(organizationId: string, type: PolicyType, request: any): Promise { const response = await this.apiService.send( "PUT", `/organizations/${organizationId}/policies/${type}/vnext`, request, true, true, ); await this.handleResponse(response); } private async handleResponse(response: any): Promise { const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); const policyResponse = new PolicyResponse(response); const data = new PolicyData(policyResponse); await this.policyService.upsert(data, userId); } }