mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 09:13:33 +00:00
Assign ownership to many libs files (#6928)
Assign ownership to many of the remaining libs/common files. Criteria for ownership: * Files used by a single team, is now owned by that team. * Files related to a domain owned by a team is now owned by that team. * Where ownership is unclear the "lowest level" service takes ownership.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { UriMatchType } from "../../enums";
|
||||
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key";
|
||||
import { UriMatchType } from "../enums";
|
||||
import { CipherType } from "../enums/cipher-type";
|
||||
import { CipherData } from "../models/data/cipher.data";
|
||||
import { Cipher } from "../models/domain/cipher";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { TreeNode } from "../../models/domain/tree-node";
|
||||
import { CollectionData } from "../models/data/collection.data";
|
||||
import { Collection } from "../models/domain/collection";
|
||||
import { TreeNode } from "../models/domain/tree-node";
|
||||
import { CollectionView } from "../models/view/collection.view";
|
||||
|
||||
export abstract class CollectionService {
|
||||
|
||||
4
libs/common/src/vault/abstractions/totp.service.ts
Normal file
4
libs/common/src/vault/abstractions/totp.service.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export abstract class TotpService {
|
||||
getCode: (key: string) => Promise<string>;
|
||||
getTimeInterval: (key: string) => number;
|
||||
}
|
||||
6
libs/common/src/vault/enums/field-type.enum.ts
Normal file
6
libs/common/src/vault/enums/field-type.enum.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export enum FieldType {
|
||||
Text = 0,
|
||||
Hidden = 1,
|
||||
Boolean = 2,
|
||||
Linked = 3,
|
||||
}
|
||||
6
libs/common/src/vault/enums/index.ts
Normal file
6
libs/common/src/vault/enums/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from "./cipher-reprompt-type";
|
||||
export * from "./cipher-type";
|
||||
export * from "./field-type.enum";
|
||||
export * from "./linked-id-type.enum";
|
||||
export * from "./secure-note-type.enum";
|
||||
export * from "./uri-match-type.enum";
|
||||
40
libs/common/src/vault/enums/linked-id-type.enum.ts
Normal file
40
libs/common/src/vault/enums/linked-id-type.enum.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
export type LinkedIdType = LoginLinkedId | CardLinkedId | IdentityLinkedId;
|
||||
|
||||
// LoginView
|
||||
export enum LoginLinkedId {
|
||||
Username = 100,
|
||||
Password = 101,
|
||||
}
|
||||
|
||||
// CardView
|
||||
export enum CardLinkedId {
|
||||
CardholderName = 300,
|
||||
ExpMonth = 301,
|
||||
ExpYear = 302,
|
||||
Code = 303,
|
||||
Brand = 304,
|
||||
Number = 305,
|
||||
}
|
||||
|
||||
// IdentityView
|
||||
export enum IdentityLinkedId {
|
||||
Title = 400,
|
||||
MiddleName = 401,
|
||||
Address1 = 402,
|
||||
Address2 = 403,
|
||||
Address3 = 404,
|
||||
City = 405,
|
||||
State = 406,
|
||||
PostalCode = 407,
|
||||
Country = 408,
|
||||
Company = 409,
|
||||
Email = 410,
|
||||
Phone = 411,
|
||||
Ssn = 412,
|
||||
Username = 413,
|
||||
PassportNumber = 414,
|
||||
LicenseNumber = 415,
|
||||
FirstName = 416,
|
||||
LastName = 417,
|
||||
FullName = 418,
|
||||
}
|
||||
3
libs/common/src/vault/enums/secure-note-type.enum.ts
Normal file
3
libs/common/src/vault/enums/secure-note-type.enum.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export enum SecureNoteType {
|
||||
Generic = 0,
|
||||
}
|
||||
8
libs/common/src/vault/enums/uri-match-type.enum.ts
Normal file
8
libs/common/src/vault/enums/uri-match-type.enum.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export enum UriMatchType {
|
||||
Domain = 0,
|
||||
Host = 1,
|
||||
StartsWith = 2,
|
||||
Exact = 3,
|
||||
RegularExpression = 4,
|
||||
Never = 5,
|
||||
}
|
||||
27
libs/common/src/vault/linked-field-option.decorator.ts
Normal file
27
libs/common/src/vault/linked-field-option.decorator.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { LinkedIdType } from "./enums";
|
||||
import { ItemView } from "./models/view/item.view";
|
||||
|
||||
export class LinkedMetadata {
|
||||
constructor(readonly propertyKey: string, private readonly _i18nKey?: string) {}
|
||||
|
||||
get i18nKey() {
|
||||
return this._i18nKey ?? this.propertyKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A decorator used to set metadata used by Linked custom fields. Apply it to a class property or getter to make it
|
||||
* available as a Linked custom field option.
|
||||
* @param id - A unique value that is saved in the Field model. It is used to look up the decorated class property.
|
||||
* @param i18nKey - The i18n key used to describe the decorated class property in the UI. If it is null, then the name
|
||||
* of the class property will be used as the i18n key.
|
||||
*/
|
||||
export function linkedFieldOption(id: LinkedIdType, i18nKey?: string) {
|
||||
return (prototype: ItemView, propertyKey: string) => {
|
||||
if (prototype.linkedFieldOptions == null) {
|
||||
prototype.linkedFieldOptions = new Map<LinkedIdType, LinkedMetadata>();
|
||||
}
|
||||
|
||||
prototype.linkedFieldOptions.set(id, new LinkedMetadata(propertyKey, i18nKey));
|
||||
};
|
||||
}
|
||||
23
libs/common/src/vault/models/api/card.api.ts
Normal file
23
libs/common/src/vault/models/api/card.api.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
|
||||
export class CardApi extends BaseResponse {
|
||||
cardholderName: string;
|
||||
brand: string;
|
||||
number: string;
|
||||
expMonth: string;
|
||||
expYear: string;
|
||||
code: string;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.cardholderName = this.getResponseProperty("CardholderName");
|
||||
this.brand = this.getResponseProperty("Brand");
|
||||
this.number = this.getResponseProperty("Number");
|
||||
this.expMonth = this.getResponseProperty("ExpMonth");
|
||||
this.expYear = this.getResponseProperty("ExpYear");
|
||||
this.code = this.getResponseProperty("Code");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseResponse } from "../../models/response/base.response";
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
|
||||
export class Fido2CredentialApi extends BaseResponse {
|
||||
credentialId: string;
|
||||
20
libs/common/src/vault/models/api/field.api.ts
Normal file
20
libs/common/src/vault/models/api/field.api.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import { FieldType, LinkedIdType } from "../../enums";
|
||||
|
||||
export class FieldApi extends BaseResponse {
|
||||
name: string;
|
||||
value: string;
|
||||
type: FieldType;
|
||||
linkedId: LinkedIdType;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.value = this.getResponseProperty("Value");
|
||||
this.linkedId = this.getResponseProperty("linkedId");
|
||||
}
|
||||
}
|
||||
47
libs/common/src/vault/models/api/identity.api.ts
Normal file
47
libs/common/src/vault/models/api/identity.api.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
|
||||
export class IdentityApi extends BaseResponse {
|
||||
title: string;
|
||||
firstName: string;
|
||||
middleName: string;
|
||||
lastName: string;
|
||||
address1: string;
|
||||
address2: string;
|
||||
address3: string;
|
||||
city: string;
|
||||
state: string;
|
||||
postalCode: string;
|
||||
country: string;
|
||||
company: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
ssn: string;
|
||||
username: string;
|
||||
passportNumber: string;
|
||||
licenseNumber: string;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.title = this.getResponseProperty("Title");
|
||||
this.firstName = this.getResponseProperty("FirstName");
|
||||
this.middleName = this.getResponseProperty("MiddleName");
|
||||
this.lastName = this.getResponseProperty("LastName");
|
||||
this.address1 = this.getResponseProperty("Address1");
|
||||
this.address2 = this.getResponseProperty("Address2");
|
||||
this.address3 = this.getResponseProperty("Address3");
|
||||
this.city = this.getResponseProperty("City");
|
||||
this.state = this.getResponseProperty("State");
|
||||
this.postalCode = this.getResponseProperty("PostalCode");
|
||||
this.country = this.getResponseProperty("Country");
|
||||
this.company = this.getResponseProperty("Company");
|
||||
this.email = this.getResponseProperty("Email");
|
||||
this.phone = this.getResponseProperty("Phone");
|
||||
this.ssn = this.getResponseProperty("SSN");
|
||||
this.username = this.getResponseProperty("Username");
|
||||
this.passportNumber = this.getResponseProperty("PassportNumber");
|
||||
this.licenseNumber = this.getResponseProperty("LicenseNumber");
|
||||
}
|
||||
}
|
||||
17
libs/common/src/vault/models/api/login-uri.api.ts
Normal file
17
libs/common/src/vault/models/api/login-uri.api.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import { UriMatchType } from "../../enums";
|
||||
|
||||
export class LoginUriApi extends BaseResponse {
|
||||
uri: string;
|
||||
match: UriMatchType = null;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.uri = this.getResponseProperty("Uri");
|
||||
const match = this.getResponseProperty("Match");
|
||||
this.match = match != null ? match : null;
|
||||
}
|
||||
}
|
||||
40
libs/common/src/vault/models/api/login.api.ts
Normal file
40
libs/common/src/vault/models/api/login.api.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { JsonObject } from "type-fest";
|
||||
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
|
||||
import { Fido2CredentialApi } from "./fido2-credential.api";
|
||||
import { LoginUriApi } from "./login-uri.api";
|
||||
|
||||
export class LoginApi extends BaseResponse {
|
||||
uris: LoginUriApi[];
|
||||
username: string;
|
||||
password: string;
|
||||
passwordRevisionDate: string;
|
||||
totp: string;
|
||||
autofillOnPageLoad: boolean;
|
||||
fido2Credentials?: Fido2CredentialApi[];
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.username = this.getResponseProperty("Username");
|
||||
this.password = this.getResponseProperty("Password");
|
||||
this.passwordRevisionDate = this.getResponseProperty("PasswordRevisionDate");
|
||||
this.totp = this.getResponseProperty("Totp");
|
||||
this.autofillOnPageLoad = this.getResponseProperty("AutofillOnPageLoad");
|
||||
|
||||
const uris = this.getResponseProperty("Uris");
|
||||
if (uris != null) {
|
||||
this.uris = uris.map((u: any) => new LoginUriApi(u));
|
||||
}
|
||||
|
||||
const fido2Credentials = this.getResponseProperty("Fido2Credentials");
|
||||
if (fido2Credentials != null) {
|
||||
this.fido2Credentials = fido2Credentials.map(
|
||||
(key: JsonObject) => new Fido2CredentialApi(key)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
libs/common/src/vault/models/api/secure-note.api.ts
Normal file
14
libs/common/src/vault/models/api/secure-note.api.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import { SecureNoteType } from "../../enums";
|
||||
|
||||
export class SecureNoteApi extends BaseResponse {
|
||||
type: SecureNoteType;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.type = this.getResponseProperty("Type");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CardApi } from "../../../models/api/card.api";
|
||||
import { CardApi } from "../api/card.api";
|
||||
|
||||
export class CardData {
|
||||
cardholderName: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Fido2CredentialApi } from "../../api/fido2-credential.api";
|
||||
import { Fido2CredentialApi } from "../api/fido2-credential.api";
|
||||
|
||||
export class Fido2CredentialData {
|
||||
credentialId: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FieldType, LinkedIdType } from "../../../enums";
|
||||
import { FieldApi } from "../../../models/api/field.api";
|
||||
import { FieldType, LinkedIdType } from "../../enums";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
|
||||
export class FieldData {
|
||||
type: FieldType;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IdentityApi } from "../../../models/api/identity.api";
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
|
||||
export class IdentityData {
|
||||
title: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UriMatchType } from "../../../enums";
|
||||
import { LoginUriApi } from "../../../models/api/login-uri.api";
|
||||
import { UriMatchType } from "../../enums";
|
||||
import { LoginUriApi } from "../api/login-uri.api";
|
||||
|
||||
export class LoginUriData {
|
||||
uri: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LoginApi } from "../../../models/api/login.api";
|
||||
import { LoginApi } from "../api/login.api";
|
||||
|
||||
import { Fido2CredentialData } from "./fido2-credential.data";
|
||||
import { LoginUriData } from "./login-uri.data";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SecureNoteType } from "../../../enums";
|
||||
import { SecureNoteApi } from "../../../models/api/secure-note.api";
|
||||
import { SecureNoteType } from "../../enums";
|
||||
import { SecureNoteApi } from "../api/secure-note.api";
|
||||
|
||||
export class SecureNoteData {
|
||||
type: SecureNoteType;
|
||||
|
||||
@@ -2,13 +2,13 @@ import { mock } from "jest-mock-extended";
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { makeStaticByteArray, mockEnc, mockFromJson } from "../../../../spec/utils";
|
||||
import { FieldType, SecureNoteType, UriMatchType } from "../../../enums";
|
||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
|
||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { ContainerService } from "../../../platform/services/container.service";
|
||||
import { InitializerKey } from "../../../platform/services/cryptography/initializer-key";
|
||||
import { CipherService } from "../../abstractions/cipher.service";
|
||||
import { FieldType, SecureNoteType, UriMatchType } from "../../enums";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../../enums/cipher-type";
|
||||
import { CipherData } from "../../models/data/cipher.data";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { mockEnc } from "../../../../spec";
|
||||
import { EncryptionType } from "../../../enums";
|
||||
import { EncryptionType } from "../../../platform/enums";
|
||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { Fido2CredentialData } from "../data/fido2-credential.data";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { mockEnc, mockFromJson } from "../../../../spec";
|
||||
import { FieldType } from "../../../enums";
|
||||
import { EncryptedString, EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { FieldType } from "../../enums";
|
||||
import { FieldData } from "../../models/data/field.data";
|
||||
import { Field } from "../../models/domain/field";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { FieldType, LinkedIdType } from "../../../enums";
|
||||
import Domain from "../../../platform/models/domain/domain-base";
|
||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { FieldType, LinkedIdType } from "../../enums";
|
||||
import { FieldData } from "../data/field.data";
|
||||
import { FieldView } from "../view/field.view";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { mockEnc, mockFromJson } from "../../../../spec";
|
||||
import { UriMatchType } from "../../../enums";
|
||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { UriMatchType } from "../../enums";
|
||||
import { LoginUriData } from "../data/login-uri.data";
|
||||
|
||||
import { LoginUri } from "./login-uri";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { UriMatchType } from "../../../enums";
|
||||
import Domain from "../../../platform/models/domain/domain-base";
|
||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { UriMatchType } from "../../enums";
|
||||
import { LoginUriData } from "../data/login-uri.data";
|
||||
import { LoginUriView } from "../view/login-uri.view";
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { mockEnc, mockFromJson } from "../../../../spec";
|
||||
import { UriMatchType } from "../../../enums";
|
||||
import { EncryptedString, EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { Fido2CredentialApi } from "../../api/fido2-credential.api";
|
||||
import { UriMatchType } from "../../enums";
|
||||
import { LoginData } from "../../models/data/login.data";
|
||||
import { Login } from "../../models/domain/login";
|
||||
import { LoginUri } from "../../models/domain/login-uri";
|
||||
import { LoginUriView } from "../../models/view/login-uri.view";
|
||||
import { Fido2CredentialApi } from "../api/fido2-credential.api";
|
||||
import { Fido2CredentialData } from "../data/fido2-credential.data";
|
||||
import { Fido2CredentialView } from "../view/fido2-credential.view";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SecureNoteType } from "../../../enums";
|
||||
import { SecureNoteType } from "../../enums";
|
||||
import { SecureNoteData } from "../data/secure-note.data";
|
||||
|
||||
import { SecureNote } from "./secure-note";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SecureNoteType } from "../../../enums";
|
||||
import Domain from "../../../platform/models/domain/domain-base";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { SecureNoteType } from "../../enums";
|
||||
import { SecureNoteData } from "../data/secure-note.data";
|
||||
import { SecureNoteView } from "../view/secure-note.view";
|
||||
|
||||
|
||||
21
libs/common/src/vault/models/domain/tree-node.ts
Normal file
21
libs/common/src/vault/models/domain/tree-node.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export class TreeNode<T extends ITreeNodeObject> {
|
||||
node: T;
|
||||
parent: TreeNode<T>;
|
||||
children: TreeNode<T>[] = [];
|
||||
|
||||
constructor(node: T, parent: TreeNode<T>, name?: string, id?: string) {
|
||||
this.parent = parent;
|
||||
this.node = node;
|
||||
if (name) {
|
||||
this.node.name = name;
|
||||
}
|
||||
if (id) {
|
||||
this.node.id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface ITreeNodeObject {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { CardApi } from "../../../models/api/card.api";
|
||||
import { FieldApi } from "../../../models/api/field.api";
|
||||
import { IdentityApi } from "../../../models/api/identity.api";
|
||||
import { LoginUriApi } from "../../../models/api/login-uri.api";
|
||||
import { LoginApi } from "../../../models/api/login.api";
|
||||
import { SecureNoteApi } from "../../../models/api/secure-note.api";
|
||||
import { Fido2CredentialApi } from "../../api/fido2-credential.api";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../../enums/cipher-type";
|
||||
import { CardApi } from "../api/card.api";
|
||||
import { Fido2CredentialApi } from "../api/fido2-credential.api";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
import { LoginUriApi } from "../api/login-uri.api";
|
||||
import { LoginApi } from "../api/login.api";
|
||||
import { SecureNoteApi } from "../api/secure-note.api";
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
import { AttachmentRequest } from "./attachment.request";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FileUploadType } from "../../../enums";
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import { FileUploadType } from "../../../platform/enums";
|
||||
|
||||
import { CipherResponse } from "./cipher.response";
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { CardApi } from "../../../models/api/card.api";
|
||||
import { FieldApi } from "../../../models/api/field.api";
|
||||
import { IdentityApi } from "../../../models/api/identity.api";
|
||||
import { LoginApi } from "../../../models/api/login.api";
|
||||
import { SecureNoteApi } from "../../../models/api/secure-note.api";
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CardApi } from "../api/card.api";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
import { LoginApi } from "../api/login.api";
|
||||
import { SecureNoteApi } from "../api/secure-note.api";
|
||||
|
||||
import { AttachmentResponse } from "./attachment.response";
|
||||
import { PasswordHistoryResponse } from "./password-history.response";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { CardLinkedId as LinkedId } from "../../../enums";
|
||||
import { linkedFieldOption } from "../../../misc/linkedFieldOption.decorator";
|
||||
import { CardLinkedId as LinkedId } from "../../enums";
|
||||
import { linkedFieldOption } from "../../linked-field-option.decorator";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { LinkedIdType } from "../../../enums";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { InitializerMetadata } from "../../../platform/interfaces/initializer-metadata.interface";
|
||||
import { InitializerKey } from "../../../platform/services/cryptography/initializer-key";
|
||||
import { LinkedIdType } from "../../enums";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../../enums/cipher-type";
|
||||
import { LocalData } from "../data/local.data";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Organization } from "../../../admin-console/models/domain/organization";
|
||||
import { ITreeNodeObject } from "../../../models/domain/tree-node";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { Collection } from "../domain/collection";
|
||||
import { ITreeNodeObject } from "../domain/tree-node";
|
||||
import { CollectionAccessDetailsResponse } from "../response/collection.response";
|
||||
|
||||
export const NestingDelimiter = "/";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { FieldType, LinkedIdType } from "../../../enums";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { FieldType, LinkedIdType } from "../../enums";
|
||||
import { Field } from "../domain/field";
|
||||
|
||||
export class FieldView implements View {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { ITreeNodeObject } from "../../../models/domain/tree-node";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { Folder } from "../domain/folder";
|
||||
import { ITreeNodeObject } from "../domain/tree-node";
|
||||
|
||||
export class FolderView implements View, ITreeNodeObject {
|
||||
id: string = null;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { IdentityLinkedId as LinkedId } from "../../../enums";
|
||||
import { linkedFieldOption } from "../../../misc/linkedFieldOption.decorator";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import { IdentityLinkedId as LinkedId } from "../../enums";
|
||||
import { linkedFieldOption } from "../../linked-field-option.decorator";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LinkedMetadata } from "../../../misc/linkedFieldOption.decorator";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { LinkedMetadata } from "../../linked-field-option.decorator";
|
||||
|
||||
export abstract class ItemView implements View {
|
||||
linkedFieldOptions: Map<number, LinkedMetadata>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UriMatchType } from "../../../enums";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import { UriMatchType } from "../../enums";
|
||||
|
||||
import { LoginUriView } from "./login-uri.view";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { UriMatchType } from "../../../enums";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { SafeUrls } from "../../../platform/misc/safe-urls";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import { UriMatchType } from "../../enums";
|
||||
import { LoginUri } from "../domain/login-uri";
|
||||
|
||||
export class LoginUriView implements View {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { LoginLinkedId as LinkedId, UriMatchType } from "../../../enums";
|
||||
import { linkedFieldOption } from "../../../misc/linkedFieldOption.decorator";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import { LoginLinkedId as LinkedId, UriMatchType } from "../../enums";
|
||||
import { linkedFieldOption } from "../../linked-field-option.decorator";
|
||||
import { Login } from "../domain/login";
|
||||
|
||||
import { Fido2CredentialView } from "./fido2-credential.view";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SecureNoteType } from "../../../enums";
|
||||
import { SecureNoteType } from "../../enums";
|
||||
import { SecureNote } from "../domain/secure-note";
|
||||
|
||||
import { ItemView } from "./item.view";
|
||||
|
||||
71
libs/common/src/vault/service-utils.spec.ts
Normal file
71
libs/common/src/vault/service-utils.spec.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { ITreeNodeObject, TreeNode } from "./models/domain/tree-node";
|
||||
import { ServiceUtils } from "./service-utils";
|
||||
|
||||
type FakeObject = { id: string; name: string };
|
||||
|
||||
describe("serviceUtils", () => {
|
||||
let nodeTree: TreeNode<FakeObject>[];
|
||||
beforeEach(() => {
|
||||
nodeTree = [
|
||||
createTreeNode({ id: "1", name: "1" }, [
|
||||
createTreeNode({ id: "1.1", name: "1.1" }, [
|
||||
createTreeNode({ id: "1.1.1", name: "1.1.1" }),
|
||||
]),
|
||||
createTreeNode({ id: "1.2", name: "1.2" }),
|
||||
])(null),
|
||||
createTreeNode({ id: "2", name: "2" }, [createTreeNode({ id: "2.1", name: "2.1" })])(null),
|
||||
createTreeNode({ id: "3", name: "3" }, [])(null),
|
||||
];
|
||||
});
|
||||
|
||||
describe("nestedTraverse", () => {
|
||||
it("should traverse a tree and add a node at the correct position given a valid path", () => {
|
||||
const nodeToBeAdded: FakeObject = { id: "1.2.1", name: "1.2.1" };
|
||||
const path = ["1", "1.2", "1.2.1"];
|
||||
|
||||
ServiceUtils.nestedTraverse(nodeTree, 0, path, nodeToBeAdded, null, "/");
|
||||
expect(nodeTree[0].children[1].children[0].node).toEqual(nodeToBeAdded);
|
||||
});
|
||||
|
||||
it("should combine the path for missing nodes and use as the added node name given an invalid path", () => {
|
||||
const nodeToBeAdded: FakeObject = { id: "blank", name: "blank" };
|
||||
const path = ["3", "3.1", "3.1.1"];
|
||||
|
||||
ServiceUtils.nestedTraverse(nodeTree, 0, path, nodeToBeAdded, null, "/");
|
||||
expect(nodeTree[2].children[0].node.name).toEqual("3.1/3.1.1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getTreeNodeObject", () => {
|
||||
it("should return a matching node given a single tree branch and a valid id", () => {
|
||||
const id = "1.1.1";
|
||||
const given = ServiceUtils.getTreeNodeObject(nodeTree[0], id);
|
||||
expect(given.node.id).toEqual(id);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getTreeNodeObjectFromList", () => {
|
||||
it("should return a matching node given a list of branches and a valid id", () => {
|
||||
const id = "1.1.1";
|
||||
const given = ServiceUtils.getTreeNodeObjectFromList(nodeTree, id);
|
||||
expect(given.node.id).toEqual(id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
type TreeNodeFactory<T extends ITreeNodeObject> = (
|
||||
obj: T,
|
||||
children?: TreeNodeFactoryWithoutParent<T>[]
|
||||
) => TreeNodeFactoryWithoutParent<T>;
|
||||
|
||||
type TreeNodeFactoryWithoutParent<T extends ITreeNodeObject> = (
|
||||
parent?: TreeNode<T>
|
||||
) => TreeNode<T>;
|
||||
|
||||
const createTreeNode: TreeNodeFactory<FakeObject> =
|
||||
(obj, children = []) =>
|
||||
(parent) => {
|
||||
const node = new TreeNode<FakeObject>(obj, parent, obj.name, obj.id);
|
||||
node.children = children.map((childFunc) => childFunc(node));
|
||||
return node;
|
||||
};
|
||||
117
libs/common/src/vault/service-utils.ts
Normal file
117
libs/common/src/vault/service-utils.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { ITreeNodeObject, TreeNode } from "./models/domain/tree-node";
|
||||
|
||||
export class ServiceUtils {
|
||||
/**
|
||||
* Recursively adds a node to nodeTree
|
||||
* @param {TreeNode<ITreeNodeObject>[]} nodeTree - An array of TreeNodes that the node will be added to
|
||||
* @param {number} partIndex - Index of the `parts` array that is being processed
|
||||
* @param {string[]} parts - Array of strings that represent the path to the `obj` node
|
||||
* @param {ITreeNodeObject} obj - The node to be added to the tree
|
||||
* @param {ITreeNodeObject} parent - The parent node of the `obj` node
|
||||
* @param {string} delimiter - The delimiter used to split the path string, will be used to combine the path for missing nodes
|
||||
*/
|
||||
static nestedTraverse(
|
||||
nodeTree: TreeNode<ITreeNodeObject>[],
|
||||
partIndex: number,
|
||||
parts: string[],
|
||||
obj: ITreeNodeObject,
|
||||
parent: TreeNode<ITreeNodeObject> | undefined,
|
||||
delimiter: string
|
||||
) {
|
||||
if (parts.length <= partIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
const end: boolean = partIndex === parts.length - 1;
|
||||
const partName: string = parts[partIndex];
|
||||
|
||||
for (let i = 0; i < nodeTree.length; i++) {
|
||||
if (nodeTree[i].node.name !== partName) {
|
||||
continue;
|
||||
}
|
||||
if (end && nodeTree[i].node.id !== obj.id) {
|
||||
// Another node exists with the same name as the node being added
|
||||
nodeTree.push(new TreeNode(obj, parent, partName));
|
||||
return;
|
||||
}
|
||||
// Move down the tree to the next level
|
||||
ServiceUtils.nestedTraverse(
|
||||
nodeTree[i].children,
|
||||
partIndex + 1,
|
||||
parts,
|
||||
obj,
|
||||
nodeTree[i],
|
||||
delimiter
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's no node here with the same name...
|
||||
if (nodeTree.filter((n) => n.node.name === partName).length === 0) {
|
||||
// And we're at the end of the path given, add the node
|
||||
if (end) {
|
||||
nodeTree.push(new TreeNode(obj, parent, partName));
|
||||
return;
|
||||
}
|
||||
// And we're not at the end of the path, combine the current name with the next name
|
||||
// 1, *1.2, 1.2.1 becomes
|
||||
// 1, *1.2/1.2.1
|
||||
const newPartName = partName + delimiter + parts[partIndex + 1];
|
||||
ServiceUtils.nestedTraverse(
|
||||
nodeTree,
|
||||
0,
|
||||
[newPartName, ...parts.slice(partIndex + 2)],
|
||||
obj,
|
||||
parent,
|
||||
delimiter
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a tree for a node with a matching `id`
|
||||
* @param {TreeNode<T>} nodeTree - A single TreeNode branch that will be searched
|
||||
* @param {string} id - The id of the node to be found
|
||||
* @returns {TreeNode<T>} The node with a matching `id`
|
||||
*/
|
||||
static getTreeNodeObject<T extends ITreeNodeObject>(
|
||||
nodeTree: TreeNode<T>,
|
||||
id: string
|
||||
): TreeNode<T> {
|
||||
if (nodeTree.node.id === id) {
|
||||
return nodeTree;
|
||||
}
|
||||
for (let i = 0; i < nodeTree.children.length; i++) {
|
||||
if (nodeTree.children[i].children != null) {
|
||||
const node = ServiceUtils.getTreeNodeObject(nodeTree.children[i], id);
|
||||
if (node !== null) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches an array of tree nodes for a node with a matching `id`
|
||||
* @param {TreeNode<T>} nodeTree - An array of TreeNode branches that will be searched
|
||||
* @param {string} id - The id of the node to be found
|
||||
* @returns {TreeNode<T>} The node with a matching `id`
|
||||
*/
|
||||
static getTreeNodeObjectFromList<T extends ITreeNodeObject>(
|
||||
nodeTree: TreeNode<T>[],
|
||||
id: string
|
||||
): TreeNode<T> {
|
||||
for (let i = 0; i < nodeTree.length; i++) {
|
||||
if (nodeTree[i].node.id === id) {
|
||||
return nodeTree[i];
|
||||
} else if (nodeTree[i].children != null) {
|
||||
const node = ServiceUtils.getTreeNodeObjectFromList(nodeTree[i].children, id);
|
||||
if (node !== null) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import { makeStaticByteArray } from "../../../spec/utils";
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
import { SearchService } from "../../abstractions/search.service";
|
||||
import { SettingsService } from "../../abstractions/settings.service";
|
||||
import { UriMatchType, FieldType } from "../../enums";
|
||||
import { ConfigServiceAbstraction } from "../../platform/abstractions/config/config.service.abstraction";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../platform/abstractions/encrypt.service";
|
||||
@@ -20,6 +19,7 @@ import {
|
||||
} from "../../platform/models/domain/symmetric-crypto-key";
|
||||
import { ContainerService } from "../../platform/services/container.service";
|
||||
import { CipherFileUploadService } from "../abstractions/file-upload/cipher-file-upload.service";
|
||||
import { UriMatchType, FieldType } from "../enums";
|
||||
import { CipherRepromptType } from "../enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../enums/cipher-type";
|
||||
import { CipherData } from "../models/data/cipher.data";
|
||||
|
||||
@@ -4,7 +4,6 @@ import { SemVer } from "semver";
|
||||
import { ApiService } from "../../abstractions/api.service";
|
||||
import { SearchService } from "../../abstractions/search.service";
|
||||
import { SettingsService } from "../../abstractions/settings.service";
|
||||
import { FieldType, UriMatchType } from "../../enums";
|
||||
import { ErrorResponse } from "../../models/response/error.response";
|
||||
import { View } from "../../models/view/view";
|
||||
import { ConfigServiceAbstraction } from "../../platform/abstractions/config/config.service.abstraction";
|
||||
@@ -25,6 +24,7 @@ import {
|
||||
} from "../../platform/models/domain/symmetric-crypto-key";
|
||||
import { CipherService as CipherServiceAbstraction } from "../abstractions/cipher.service";
|
||||
import { CipherFileUploadService } from "../abstractions/file-upload/cipher-file-upload.service";
|
||||
import { FieldType, UriMatchType } from "../enums";
|
||||
import { CipherType } from "../enums/cipher-type";
|
||||
import { CipherData } from "../models/data/cipher.data";
|
||||
import { Attachment } from "../models/domain/attachment";
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ServiceUtils } from "../../misc/serviceUtils";
|
||||
import { TreeNode } from "../../models/domain/tree-node";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { StateService } from "../../platform/abstractions/state.service";
|
||||
@@ -7,7 +5,9 @@ import { Utils } from "../../platform/misc/utils";
|
||||
import { CollectionService as CollectionServiceAbstraction } from "../../vault/abstractions/collection.service";
|
||||
import { CollectionData } from "../models/data/collection.data";
|
||||
import { Collection } from "../models/domain/collection";
|
||||
import { TreeNode } from "../models/domain/tree-node";
|
||||
import { CollectionView } from "../models/view/collection.view";
|
||||
import { ServiceUtils } from "../service-utils";
|
||||
|
||||
const NestingDelimiter = "/";
|
||||
|
||||
|
||||
168
libs/common/src/vault/services/totp.service.ts
Normal file
168
libs/common/src/vault/services/totp.service.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import { CryptoFunctionService } from "../../platform/abstractions/crypto-function.service";
|
||||
import { LogService } from "../../platform/abstractions/log.service";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import { TotpService as TotpServiceAbstraction } from "../abstractions/totp.service";
|
||||
|
||||
const B32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
const SteamChars = "23456789BCDFGHJKMNPQRTVWXY";
|
||||
|
||||
export class TotpService implements TotpServiceAbstraction {
|
||||
constructor(
|
||||
private cryptoFunctionService: CryptoFunctionService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
async getCode(key: string): Promise<string> {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
let period = 30;
|
||||
let alg: "sha1" | "sha256" | "sha512" = "sha1";
|
||||
let digits = 6;
|
||||
let keyB32 = key;
|
||||
const isOtpAuth = key.toLowerCase().indexOf("otpauth://") === 0;
|
||||
const isSteamAuth = !isOtpAuth && key.toLowerCase().indexOf("steam://") === 0;
|
||||
if (isOtpAuth) {
|
||||
const params = Utils.getQueryParams(key);
|
||||
if (params.has("digits") && params.get("digits") != null) {
|
||||
try {
|
||||
const digitParams = parseInt(params.get("digits").trim(), null);
|
||||
if (digitParams > 10) {
|
||||
digits = 10;
|
||||
} else if (digitParams > 0) {
|
||||
digits = digitParams;
|
||||
}
|
||||
} catch {
|
||||
this.logService.error("Invalid digits param.");
|
||||
}
|
||||
}
|
||||
if (params.has("period") && params.get("period") != null) {
|
||||
try {
|
||||
const periodParam = parseInt(params.get("period").trim(), null);
|
||||
if (periodParam > 0) {
|
||||
period = periodParam;
|
||||
}
|
||||
} catch {
|
||||
this.logService.error("Invalid period param.");
|
||||
}
|
||||
}
|
||||
if (params.has("secret") && params.get("secret") != null) {
|
||||
keyB32 = params.get("secret");
|
||||
}
|
||||
if (params.has("algorithm") && params.get("algorithm") != null) {
|
||||
const algParam = params.get("algorithm").toLowerCase();
|
||||
if (algParam === "sha1" || algParam === "sha256" || algParam === "sha512") {
|
||||
alg = algParam;
|
||||
}
|
||||
}
|
||||
} else if (isSteamAuth) {
|
||||
keyB32 = key.substr("steam://".length);
|
||||
digits = 5;
|
||||
}
|
||||
|
||||
const epoch = Math.round(new Date().getTime() / 1000.0);
|
||||
const timeHex = this.leftPad(this.decToHex(Math.floor(epoch / period)), 16, "0");
|
||||
const timeBytes = Utils.fromHexToArray(timeHex);
|
||||
const keyBytes = this.b32ToBytes(keyB32);
|
||||
|
||||
if (!keyBytes.length || !timeBytes.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const hash = await this.sign(keyBytes, timeBytes, alg);
|
||||
if (hash.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const offset = hash[hash.length - 1] & 0xf;
|
||||
const binary =
|
||||
((hash[offset] & 0x7f) << 24) |
|
||||
((hash[offset + 1] & 0xff) << 16) |
|
||||
((hash[offset + 2] & 0xff) << 8) |
|
||||
(hash[offset + 3] & 0xff);
|
||||
|
||||
let otp = "";
|
||||
if (isSteamAuth) {
|
||||
let fullCode = binary & 0x7fffffff;
|
||||
for (let i = 0; i < digits; i++) {
|
||||
otp += SteamChars[fullCode % SteamChars.length];
|
||||
fullCode = Math.trunc(fullCode / SteamChars.length);
|
||||
}
|
||||
} else {
|
||||
otp = (binary % Math.pow(10, digits)).toString();
|
||||
otp = this.leftPad(otp, digits, "0");
|
||||
}
|
||||
|
||||
return otp;
|
||||
}
|
||||
|
||||
getTimeInterval(key: string): number {
|
||||
let period = 30;
|
||||
if (key != null && key.toLowerCase().indexOf("otpauth://") === 0) {
|
||||
const params = Utils.getQueryParams(key);
|
||||
if (params.has("period") && params.get("period") != null) {
|
||||
try {
|
||||
period = parseInt(params.get("period").trim(), null);
|
||||
} catch {
|
||||
this.logService.error("Invalid period param.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return period;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
private leftPad(s: string, l: number, p: string): string {
|
||||
if (l + 1 >= s.length) {
|
||||
s = Array(l + 1 - s.length).join(p) + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private decToHex(d: number): string {
|
||||
return (d < 15.5 ? "0" : "") + Math.round(d).toString(16);
|
||||
}
|
||||
|
||||
private b32ToHex(s: string): string {
|
||||
s = s.toUpperCase();
|
||||
let cleanedInput = "";
|
||||
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
if (B32Chars.indexOf(s[i]) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cleanedInput += s[i];
|
||||
}
|
||||
s = cleanedInput;
|
||||
|
||||
let bits = "";
|
||||
let hex = "";
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
const byteIndex = B32Chars.indexOf(s.charAt(i));
|
||||
if (byteIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
bits += this.leftPad(byteIndex.toString(2), 5, "0");
|
||||
}
|
||||
for (let i = 0; i + 4 <= bits.length; i += 4) {
|
||||
const chunk = bits.substr(i, 4);
|
||||
hex = hex + parseInt(chunk, 2).toString(16);
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
private b32ToBytes(s: string): Uint8Array {
|
||||
return Utils.fromHexToArray(this.b32ToHex(s));
|
||||
}
|
||||
|
||||
private async sign(
|
||||
keyBytes: Uint8Array,
|
||||
timeBytes: Uint8Array,
|
||||
alg: "sha1" | "sha256" | "sha512"
|
||||
) {
|
||||
const signature = await this.cryptoFunctionService.hmac(timeBytes, keyBytes, alg);
|
||||
return new Uint8Array(signature);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user