1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

[PM-328] Move Send to Tools (#5104)

* Move send in libs/common

* Move send in libs/angular

* Move send in browser

* Move send in cli

* Move send in desktop

* Move send in web
This commit is contained in:
Daniel James Smith
2023-03-29 16:23:37 +02:00
committed by GitHub
parent e645688f8a
commit e238ea20a9
105 changed files with 328 additions and 321 deletions

View File

@@ -0,0 +1,19 @@
import { BaseResponse } from "../../../../models/response/base.response";
export class SendFileApi extends BaseResponse {
id: string;
fileName: string;
size: string;
sizeName: string;
constructor(data: any = null) {
super(data);
if (data == null) {
return;
}
this.id = this.getResponseProperty("Id");
this.fileName = this.getResponseProperty("FileName");
this.size = this.getResponseProperty("Size");
this.sizeName = this.getResponseProperty("SizeName");
}
}

View File

@@ -0,0 +1,15 @@
import { BaseResponse } from "../../../../models/response/base.response";
export class SendTextApi extends BaseResponse {
text: string;
hidden: boolean;
constructor(data: any = null) {
super(data);
if (data == null) {
return;
}
this.text = this.getResponseProperty("Text");
this.hidden = this.getResponseProperty("Hidden") || false;
}
}

View File

@@ -0,0 +1,19 @@
import { SendFileApi } from "../api/send-file.api";
export class SendFileData {
id: string;
fileName: string;
size: string;
sizeName: string;
constructor(data?: SendFileApi) {
if (data == null) {
return;
}
this.id = data.id;
this.fileName = data.fileName;
this.size = data.size;
this.sizeName = data.sizeName;
}
}

View File

@@ -0,0 +1,15 @@
import { SendTextApi } from "../api/send-text.api";
export class SendTextData {
text: string;
hidden: boolean;
constructor(data?: SendTextApi) {
if (data == null) {
return;
}
this.text = data.text;
this.hidden = data.hidden;
}
}

View File

@@ -0,0 +1,56 @@
import { SendType } from "../../enums/send-type";
import { SendResponse } from "../response/send.response";
import { SendFileData } from "./send-file.data";
import { SendTextData } from "./send-text.data";
export class SendData {
id: string;
accessId: string;
type: SendType;
name: string;
notes: string;
file: SendFileData;
text: SendTextData;
key: string;
maxAccessCount?: number;
accessCount: number;
revisionDate: string;
expirationDate: string;
deletionDate: string;
password: string;
disabled: boolean;
hideEmail: boolean;
constructor(response?: SendResponse) {
if (response == null) {
return;
}
this.id = response.id;
this.accessId = response.accessId;
this.type = response.type;
this.name = response.name;
this.notes = response.notes;
this.key = response.key;
this.maxAccessCount = response.maxAccessCount;
this.accessCount = response.accessCount;
this.revisionDate = response.revisionDate;
this.expirationDate = response.expirationDate;
this.deletionDate = response.deletionDate;
this.password = response.password;
this.disabled = response.disable;
this.hideEmail = response.hideEmail;
switch (this.type) {
case SendType.Text:
this.text = new SendTextData(response.text);
break;
case SendType.File:
this.file = new SendFileData(response.file);
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,85 @@
// eslint-disable-next-line no-restricted-imports
import { Substitute, Arg } from "@fluffy-spoon/substitute";
import { mockEnc } from "../../../../../spec/utils";
import { SendType } from "../../enums/send-type";
import { SendAccessResponse } from "../response/send-access.response";
import { SendAccess } from "./send-access";
import { SendText } from "./send-text";
describe("SendAccess", () => {
let request: SendAccessResponse;
beforeEach(() => {
request = {
id: "id",
type: SendType.Text,
name: "encName",
file: null,
text: {
text: "encText",
hidden: true,
},
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
creatorIdentifier: "creatorIdentifier",
} as SendAccessResponse;
});
it("Convert from empty", () => {
const request = new SendAccessResponse({});
const sendAccess = new SendAccess(request);
expect(sendAccess).toEqual({
id: null,
type: undefined,
name: null,
creatorIdentifier: null,
expirationDate: null,
});
});
it("Convert", () => {
const sendAccess = new SendAccess(request);
expect(sendAccess).toEqual({
id: "id",
type: 0,
name: { encryptedString: "encName", encryptionType: 0 },
text: {
hidden: true,
text: { encryptedString: "encText", encryptionType: 0 },
},
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
creatorIdentifier: "creatorIdentifier",
});
});
it("Decrypt", async () => {
const sendAccess = new SendAccess();
sendAccess.id = "id";
sendAccess.type = SendType.Text;
sendAccess.name = mockEnc("name");
const text = Substitute.for<SendText>();
text.decrypt(Arg.any()).resolves({} as any);
sendAccess.text = text;
sendAccess.expirationDate = new Date("2022-01-31T12:00:00.000Z");
sendAccess.creatorIdentifier = "creatorIdentifier";
const view = await sendAccess.decrypt(null);
text.received(1).decrypt(Arg.any());
expect(view).toEqual({
id: "id",
type: 0,
name: "name",
text: {},
file: expect.anything(),
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
creatorIdentifier: "creatorIdentifier",
});
});
});

View File

@@ -0,0 +1,77 @@
import Domain from "../../../../models/domain/domain-base";
import { EncString } from "../../../../models/domain/enc-string";
import { SymmetricCryptoKey } from "../../../../models/domain/symmetric-crypto-key";
import { SendType } from "../../enums/send-type";
import { SendAccessResponse } from "../response/send-access.response";
import { SendAccessView } from "../view/send-access.view";
import { SendFile } from "./send-file";
import { SendText } from "./send-text";
export class SendAccess extends Domain {
id: string;
type: SendType;
name: EncString;
file: SendFile;
text: SendText;
expirationDate: Date;
creatorIdentifier: string;
constructor(obj?: SendAccessResponse) {
super();
if (obj == null) {
return;
}
this.buildDomainModel(
this,
obj,
{
id: null,
name: null,
expirationDate: null,
creatorIdentifier: null,
},
["id", "expirationDate", "creatorIdentifier"]
);
this.type = obj.type;
switch (this.type) {
case SendType.Text:
this.text = new SendText(obj.text);
break;
case SendType.File:
this.file = new SendFile(obj.file);
break;
default:
break;
}
}
async decrypt(key: SymmetricCryptoKey): Promise<SendAccessView> {
const model = new SendAccessView(this);
await this.decryptObj(
model,
{
name: null,
},
null,
key
);
switch (this.type) {
case SendType.File:
model.file = await this.file.decrypt(key);
break;
case SendType.Text:
model.text = await this.text.decrypt(key);
break;
default:
break;
}
return model;
}
}

View File

@@ -0,0 +1,57 @@
import { mockEnc } from "../../../../../spec/utils";
import { SendFileData } from "../data/send-file.data";
import { SendFile } from "./send-file";
describe("SendFile", () => {
let data: SendFileData;
beforeEach(() => {
data = {
id: "id",
size: "1100",
sizeName: "1.1 KB",
fileName: "encFileName",
};
});
it("Convert from empty", () => {
const data = new SendFileData();
const sendFile = new SendFile(data);
expect(sendFile).toEqual({
fileName: null,
id: null,
size: undefined,
sizeName: null,
});
});
it("Convert", () => {
const sendFile = new SendFile(data);
expect(sendFile).toEqual({
id: "id",
size: "1100",
sizeName: "1.1 KB",
fileName: { encryptedString: "encFileName", encryptionType: 0 },
});
});
it("Decrypt", async () => {
const sendFile = new SendFile();
sendFile.id = "id";
sendFile.size = "1100";
sendFile.sizeName = "1.1 KB";
sendFile.fileName = mockEnc("fileName");
const view = await sendFile.decrypt(null);
expect(view).toEqual({
fileName: "fileName",
id: "id",
size: "1100",
sizeName: "1.1 KB",
});
});
});

View File

@@ -0,0 +1,55 @@
import { Jsonify } from "type-fest";
import Domain from "../../../../models/domain/domain-base";
import { EncString } from "../../../../models/domain/enc-string";
import { SymmetricCryptoKey } from "../../../../models/domain/symmetric-crypto-key";
import { SendFileData } from "../data/send-file.data";
import { SendFileView } from "../view/send-file.view";
export class SendFile extends Domain {
id: string;
size: string;
sizeName: string;
fileName: EncString;
constructor(obj?: SendFileData) {
super();
if (obj == null) {
return;
}
this.size = obj.size;
this.buildDomainModel(
this,
obj,
{
id: null,
sizeName: null,
fileName: null,
},
["id", "sizeName"]
);
}
async decrypt(key: SymmetricCryptoKey): Promise<SendFileView> {
const view = await this.decryptObj(
new SendFileView(this),
{
fileName: null,
},
null,
key
);
return view;
}
static fromJSON(obj: Jsonify<SendFile>) {
if (obj == null) {
return null;
}
return Object.assign(new SendFile(), obj, {
fileName: EncString.fromJSON(obj.fileName),
});
}
}

View File

@@ -0,0 +1,47 @@
import { mockEnc } from "../../../../../spec/utils";
import { SendTextData } from "../data/send-text.data";
import { SendText } from "./send-text";
describe("SendText", () => {
let data: SendTextData;
beforeEach(() => {
data = {
text: "encText",
hidden: false,
};
});
it("Convert from empty", () => {
const data = new SendTextData();
const secureNote = new SendText(data);
expect(secureNote).toEqual({
hidden: undefined,
text: null,
});
});
it("Convert", () => {
const secureNote = new SendText(data);
expect(secureNote).toEqual({
hidden: false,
text: { encryptedString: "encText", encryptionType: 0 },
});
});
it("Decrypt", async () => {
const secureNote = new SendText();
secureNote.text = mockEnc("text");
secureNote.hidden = true;
const view = await secureNote.decrypt(null);
expect(view).toEqual({
text: "text",
hidden: true,
});
});
});

View File

@@ -0,0 +1,50 @@
import { Jsonify } from "type-fest";
import Domain from "../../../../models/domain/domain-base";
import { EncString } from "../../../../models/domain/enc-string";
import { SymmetricCryptoKey } from "../../../../models/domain/symmetric-crypto-key";
import { SendTextData } from "../data/send-text.data";
import { SendTextView } from "../view/send-text.view";
export class SendText extends Domain {
text: EncString;
hidden: boolean;
constructor(obj?: SendTextData) {
super();
if (obj == null) {
return;
}
this.hidden = obj.hidden;
this.buildDomainModel(
this,
obj,
{
text: null,
},
[]
);
}
decrypt(key: SymmetricCryptoKey): Promise<SendTextView> {
return this.decryptObj(
new SendTextView(this),
{
text: null,
},
null,
key
);
}
static fromJSON(obj: Jsonify<SendText>) {
if (obj == null) {
return null;
}
return Object.assign(new SendText(), obj, {
text: EncString.fromJSON(obj.text),
});
}
}

View File

@@ -0,0 +1,144 @@
// eslint-disable-next-line no-restricted-imports
import { Substitute, Arg, SubstituteOf } from "@fluffy-spoon/substitute";
import { makeStaticByteArray, mockEnc } from "../../../../../spec/utils";
import { CryptoService } from "../../../../abstractions/crypto.service";
import { EncryptService } from "../../../../abstractions/encrypt.service";
import { EncString } from "../../../../models/domain/enc-string";
import { ContainerService } from "../../../../services/container.service";
import { SendType } from "../../enums/send-type";
import { SendData } from "../data/send.data";
import { Send } from "./send";
import { SendText } from "./send-text";
describe("Send", () => {
let data: SendData;
beforeEach(() => {
data = {
id: "id",
accessId: "accessId",
type: SendType.Text,
name: "encName",
notes: "encNotes",
text: {
text: "encText",
hidden: true,
},
file: null,
key: "encKey",
maxAccessCount: null,
accessCount: 10,
revisionDate: "2022-01-31T12:00:00.000Z",
expirationDate: "2022-01-31T12:00:00.000Z",
deletionDate: "2022-01-31T12:00:00.000Z",
password: "password",
disabled: false,
hideEmail: true,
};
});
it("Convert from empty", () => {
const data = new SendData();
const send = new Send(data);
expect(send).toEqual({
id: null,
accessId: null,
type: undefined,
name: null,
notes: null,
text: undefined,
file: undefined,
key: null,
maxAccessCount: undefined,
accessCount: undefined,
revisionDate: null,
expirationDate: null,
deletionDate: null,
password: undefined,
disabled: undefined,
hideEmail: undefined,
});
});
it("Convert", () => {
const send = new Send(data);
expect(send).toEqual({
id: "id",
accessId: "accessId",
type: SendType.Text,
name: { encryptedString: "encName", encryptionType: 0 },
notes: { encryptedString: "encNotes", encryptionType: 0 },
text: {
text: { encryptedString: "encText", encryptionType: 0 },
hidden: true,
},
key: { encryptedString: "encKey", encryptionType: 0 },
maxAccessCount: null,
accessCount: 10,
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
deletionDate: new Date("2022-01-31T12:00:00.000Z"),
password: "password",
disabled: false,
hideEmail: true,
});
});
it("Decrypt", async () => {
const text = Substitute.for<SendText>();
text.decrypt(Arg.any()).resolves("textView" as any);
const send = new Send();
send.id = "id";
send.accessId = "accessId";
send.type = SendType.Text;
send.name = mockEnc("name");
send.notes = mockEnc("notes");
send.text = text;
send.key = mockEnc("key");
send.accessCount = 10;
send.revisionDate = new Date("2022-01-31T12:00:00.000Z");
send.expirationDate = new Date("2022-01-31T12:00:00.000Z");
send.deletionDate = new Date("2022-01-31T12:00:00.000Z");
send.password = "password";
send.disabled = false;
send.hideEmail = true;
const cryptoService = Substitute.for<CryptoService>();
cryptoService.decryptToBytes(send.key, null).resolves(makeStaticByteArray(32));
cryptoService.makeSendKey(Arg.any()).resolves("cryptoKey" as any);
const encryptService = Substitute.for<EncryptService>();
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
const view = await send.decrypt();
text.received(1).decrypt("cryptoKey" as any);
(send.name as SubstituteOf<EncString>).received(1).decrypt(null, "cryptoKey" as any);
expect(view).toMatchObject({
id: "id",
accessId: "accessId",
name: "name",
notes: "notes",
type: 0,
key: expect.anything(),
cryptoKey: "cryptoKey",
file: expect.anything(),
text: "textView",
maxAccessCount: undefined,
accessCount: 10,
revisionDate: new Date("2022-01-31T12:00:00.000Z"),
expirationDate: new Date("2022-01-31T12:00:00.000Z"),
deletionDate: new Date("2022-01-31T12:00:00.000Z"),
password: "password",
disabled: false,
hideEmail: true,
});
});
});

View File

@@ -0,0 +1,128 @@
import { Jsonify } from "type-fest";
import { Utils } from "../../../../misc/utils";
import Domain from "../../../../models/domain/domain-base";
import { EncString } from "../../../../models/domain/enc-string";
import { SendType } from "../../enums/send-type";
import { SendData } from "../data/send.data";
import { SendView } from "../view/send.view";
import { SendFile } from "./send-file";
import { SendText } from "./send-text";
export class Send extends Domain {
id: string;
accessId: string;
type: SendType;
name: EncString;
notes: EncString;
file: SendFile;
text: SendText;
key: EncString;
maxAccessCount?: number;
accessCount: number;
revisionDate: Date;
expirationDate: Date;
deletionDate: Date;
password: string;
disabled: boolean;
hideEmail: boolean;
constructor(obj?: SendData) {
super();
if (obj == null) {
return;
}
this.buildDomainModel(
this,
obj,
{
id: null,
accessId: null,
name: null,
notes: null,
key: null,
},
["id", "accessId"]
);
this.type = obj.type;
this.maxAccessCount = obj.maxAccessCount;
this.accessCount = obj.accessCount;
this.password = obj.password;
this.disabled = obj.disabled;
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
this.deletionDate = obj.deletionDate != null ? new Date(obj.deletionDate) : null;
this.expirationDate = obj.expirationDate != null ? new Date(obj.expirationDate) : null;
this.hideEmail = obj.hideEmail;
switch (this.type) {
case SendType.Text:
this.text = new SendText(obj.text);
break;
case SendType.File:
this.file = new SendFile(obj.file);
break;
default:
break;
}
}
async decrypt(): Promise<SendView> {
const model = new SendView(this);
const cryptoService = Utils.getContainerService().getCryptoService();
try {
model.key = await cryptoService.decryptToBytes(this.key, null);
model.cryptoKey = await cryptoService.makeSendKey(model.key);
} catch (e) {
// TODO: error?
}
await this.decryptObj(
model,
{
name: null,
notes: null,
},
null,
model.cryptoKey
);
switch (this.type) {
case SendType.File:
model.file = await this.file.decrypt(model.cryptoKey);
break;
case SendType.Text:
model.text = await this.text.decrypt(model.cryptoKey);
break;
default:
break;
}
return model;
}
static fromJSON(obj: Jsonify<Send>) {
if (obj == null) {
return null;
}
const revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate);
const expirationDate = obj.expirationDate == null ? null : new Date(obj.expirationDate);
const deletionDate = obj.deletionDate == null ? null : new Date(obj.deletionDate);
return Object.assign(new Send(), obj, {
key: EncString.fromJSON(obj.key),
name: EncString.fromJSON(obj.name),
notes: EncString.fromJSON(obj.notes),
text: SendText.fromJSON(obj.text),
file: SendFile.fromJSON(obj.file),
revisionDate,
expirationDate,
deletionDate,
});
}
}

View File

@@ -0,0 +1,3 @@
export class SendAccessRequest {
password: string;
}

View File

@@ -0,0 +1,12 @@
import { Send } from "../domain/send";
import { SendRequest } from "./send.request";
export class SendWithIdRequest extends SendRequest {
id: string;
constructor(send: Send) {
super(send);
this.id = send.id;
}
}

View File

@@ -0,0 +1,48 @@
import { SendType } from "../../enums/send-type";
import { SendFileApi } from "../api/send-file.api";
import { SendTextApi } from "../api/send-text.api";
import { Send } from "../domain/send";
export class SendRequest {
type: SendType;
fileLength?: number;
name: string;
notes: string;
key: string;
maxAccessCount?: number;
expirationDate: string;
deletionDate: string;
text: SendTextApi;
file: SendFileApi;
password: string;
disabled: boolean;
hideEmail: boolean;
constructor(send: Send, fileLength?: number) {
this.type = send.type;
this.fileLength = fileLength;
this.name = send.name ? send.name.encryptedString : null;
this.notes = send.notes ? send.notes.encryptedString : null;
this.maxAccessCount = send.maxAccessCount;
this.expirationDate = send.expirationDate != null ? send.expirationDate.toISOString() : null;
this.deletionDate = send.deletionDate != null ? send.deletionDate.toISOString() : null;
this.key = send.key != null ? send.key.encryptedString : null;
this.password = send.password;
this.disabled = send.disabled;
this.hideEmail = send.hideEmail;
switch (this.type) {
case SendType.Text:
this.text = new SendTextApi();
this.text.text = send.text.text != null ? send.text.text.encryptedString : null;
this.text.hidden = send.text.hidden;
break;
case SendType.File:
this.file = new SendFileApi();
this.file.fileName = send.file.fileName != null ? send.file.fileName.encryptedString : null;
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,34 @@
import { BaseResponse } from "../../../../models/response/base.response";
import { SendType } from "../../enums/send-type";
import { SendFileApi } from "../api/send-file.api";
import { SendTextApi } from "../api/send-text.api";
export class SendAccessResponse extends BaseResponse {
id: string;
type: SendType;
name: string;
file: SendFileApi;
text: SendTextApi;
expirationDate: Date;
creatorIdentifier: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.type = this.getResponseProperty("Type");
this.name = this.getResponseProperty("Name");
const text = this.getResponseProperty("Text");
if (text != null) {
this.text = new SendTextApi(text);
}
const file = this.getResponseProperty("File");
if (file != null) {
this.file = new SendFileApi(file);
}
this.expirationDate = this.getResponseProperty("ExpirationDate");
this.creatorIdentifier = this.getResponseProperty("CreatorIdentifier");
}
}

View File

@@ -0,0 +1,11 @@
import { BaseResponse } from "../../../../models/response/base.response";
export class SendFileDownloadDataResponse extends BaseResponse {
id: string = null;
url: string = null;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.url = this.getResponseProperty("Url");
}
}

View File

@@ -0,0 +1,17 @@
import { FileUploadType } from "../../../../enums/fileUploadType";
import { BaseResponse } from "../../../../models/response/base.response";
import { SendResponse } from "./send.response";
export class SendFileUploadDataResponse extends BaseResponse {
fileUploadType: FileUploadType;
sendResponse: SendResponse;
url: string = null;
constructor(response: any) {
super(response);
this.fileUploadType = this.getResponseProperty("FileUploadType");
const sendResponse = this.getResponseProperty("SendResponse");
this.sendResponse = sendResponse == null ? null : new SendResponse(sendResponse);
this.url = this.getResponseProperty("Url");
}
}

View File

@@ -0,0 +1,51 @@
import { BaseResponse } from "../../../../models/response/base.response";
import { SendType } from "../../enums/send-type";
import { SendFileApi } from "../api/send-file.api";
import { SendTextApi } from "../api/send-text.api";
export class SendResponse extends BaseResponse {
id: string;
accessId: string;
type: SendType;
name: string;
notes: string;
file: SendFileApi;
text: SendTextApi;
key: string;
maxAccessCount?: number;
accessCount: number;
revisionDate: string;
expirationDate: string;
deletionDate: string;
password: string;
disable: boolean;
hideEmail: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.accessId = this.getResponseProperty("AccessId");
this.type = this.getResponseProperty("Type");
this.name = this.getResponseProperty("Name");
this.notes = this.getResponseProperty("Notes");
this.key = this.getResponseProperty("Key");
this.maxAccessCount = this.getResponseProperty("MaxAccessCount");
this.accessCount = this.getResponseProperty("AccessCount");
this.revisionDate = this.getResponseProperty("RevisionDate");
this.expirationDate = this.getResponseProperty("ExpirationDate");
this.deletionDate = this.getResponseProperty("DeletionDate");
this.password = this.getResponseProperty("Password");
this.disable = this.getResponseProperty("Disabled") || false;
this.hideEmail = this.getResponseProperty("HideEmail") || false;
const text = this.getResponseProperty("Text");
if (text != null) {
this.text = new SendTextApi(text);
}
const file = this.getResponseProperty("File");
if (file != null) {
this.file = new SendFileApi(file);
}
}
}

View File

@@ -0,0 +1,27 @@
import { View } from "../../../../models/view/view";
import { SendType } from "../../enums/send-type";
import { SendAccess } from "../domain/send-access";
import { SendFileView } from "./send-file.view";
import { SendTextView } from "./send-text.view";
export class SendAccessView implements View {
id: string = null;
name: string = null;
type: SendType = null;
text = new SendTextView();
file = new SendFileView();
expirationDate: Date = null;
creatorIdentifier: string = null;
constructor(s?: SendAccess) {
if (!s) {
return;
}
this.id = s.id;
this.type = s.type;
this.expirationDate = s.expirationDate;
this.creatorIdentifier = s.creatorIdentifier;
}
}

View File

@@ -0,0 +1,39 @@
import { View } from "../../../../models/view/view";
import { DeepJsonify } from "../../../../types/deep-jsonify";
import { SendFile } from "../domain/send-file";
export class SendFileView implements View {
id: string = null;
size: string = null;
sizeName: string = null;
fileName: string = null;
constructor(f?: SendFile) {
if (!f) {
return;
}
this.id = f.id;
this.size = f.size;
this.sizeName = f.sizeName;
}
get fileSize(): number {
try {
if (this.size != null) {
return parseInt(this.size, null);
}
} catch {
// Invalid file size.
}
return 0;
}
static fromJSON(json: DeepJsonify<SendFileView>) {
if (json == null) {
return null;
}
return Object.assign(new SendFileView(), json);
}
}

View File

@@ -0,0 +1,28 @@
import { View } from "../../../../models/view/view";
import { DeepJsonify } from "../../../../types/deep-jsonify";
import { SendText } from "../domain/send-text";
export class SendTextView implements View {
text: string = null;
hidden: boolean;
constructor(t?: SendText) {
if (!t) {
return;
}
this.hidden = t.hidden;
}
get maskedText(): string {
return this.text != null ? "••••••••" : null;
}
static fromJSON(json: DeepJsonify<SendTextView>) {
if (json == null) {
return null;
}
return Object.assign(new SendTextView(), json);
}
}

View File

@@ -0,0 +1,94 @@
import { Utils } from "../../../../misc/utils";
import { SymmetricCryptoKey } from "../../../../models/domain/symmetric-crypto-key";
import { View } from "../../../../models/view/view";
import { DeepJsonify } from "../../../../types/deep-jsonify";
import { SendType } from "../../enums/send-type";
import { Send } from "../domain/send";
import { SendFileView } from "./send-file.view";
import { SendTextView } from "./send-text.view";
export class SendView implements View {
id: string = null;
accessId: string = null;
name: string = null;
notes: string = null;
key: ArrayBuffer;
cryptoKey: SymmetricCryptoKey;
type: SendType = null;
text = new SendTextView();
file = new SendFileView();
maxAccessCount?: number = null;
accessCount = 0;
revisionDate: Date = null;
deletionDate: Date = null;
expirationDate: Date = null;
password: string = null;
disabled = false;
hideEmail = false;
constructor(s?: Send) {
if (!s) {
return;
}
this.id = s.id;
this.accessId = s.accessId;
this.type = s.type;
this.maxAccessCount = s.maxAccessCount;
this.accessCount = s.accessCount;
this.revisionDate = s.revisionDate;
this.deletionDate = s.deletionDate;
this.expirationDate = s.expirationDate;
this.disabled = s.disabled;
this.password = s.password;
this.hideEmail = s.hideEmail;
}
get urlB64Key(): string {
return Utils.fromBufferToUrlB64(this.key);
}
get maxAccessCountReached(): boolean {
if (this.maxAccessCount == null) {
return false;
}
return this.accessCount >= this.maxAccessCount;
}
get expired(): boolean {
if (this.expirationDate == null) {
return false;
}
return this.expirationDate <= new Date();
}
get pendingDelete(): boolean {
return this.deletionDate <= new Date();
}
toJSON() {
return Utils.merge(
{ ...this },
{
key: Utils.fromBufferToB64(this.key),
}
);
}
static fromJSON(json: DeepJsonify<SendView>) {
if (json == null) {
return null;
}
return Object.assign(new SendView(), json, {
key: Utils.fromB64ToArray(json.key)?.buffer,
cryptoKey: SymmetricCryptoKey.fromJSON(json.cryptoKey),
text: SendTextView.fromJSON(json.text),
file: SendFileView.fromJSON(json.file),
revisionDate: json.revisionDate == null ? null : new Date(json.revisionDate),
deletionDate: json.deletionDate == null ? null : new Date(json.deletionDate),
expirationDate: json.expirationDate == null ? null : new Date(json.expirationDate),
});
}
}