2021-01-13 05:31:02 +00:00
|
|
|
import { getEndpoint } from "utils/common/apiUtil";
|
|
|
|
import { getData, LS_KEYS } from "utils/storage/localStorage";
|
2021-01-14 11:31:20 +00:00
|
|
|
import { file, user, getFiles } from "./fileService";
|
|
|
|
import localForage from 'localforage';
|
|
|
|
|
2021-01-13 05:31:02 +00:00
|
|
|
import HTTPService from "./HTTPService";
|
|
|
|
import * as Comlink from 'comlink';
|
2021-01-13 12:43:46 +00:00
|
|
|
import { keyEncryptionResult } from "./uploadService";
|
2021-01-15 11:11:06 +00:00
|
|
|
import { getActualKey, getToken } from "utils/common/key";
|
2021-01-13 05:31:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
const CryptoWorker: any =
|
|
|
|
typeof window !== 'undefined' &&
|
|
|
|
Comlink.wrap(new Worker('worker/crypto.worker.js', { type: 'module' }));
|
|
|
|
const ENDPOINT = getEndpoint();
|
|
|
|
|
|
|
|
|
2021-01-13 12:43:46 +00:00
|
|
|
enum CollectionType {
|
2021-01-14 09:41:09 +00:00
|
|
|
folder = "folder",
|
|
|
|
favorites = "favorites",
|
|
|
|
album = "album",
|
2021-01-13 12:43:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface collection {
|
|
|
|
id: string;
|
|
|
|
owner: user;
|
2021-01-18 02:27:00 +00:00
|
|
|
key?: string;
|
2021-01-21 02:24:17 +00:00
|
|
|
name?: string;
|
|
|
|
encryptedName?: string;
|
|
|
|
nameDecryptionNonce?: string;
|
2021-01-14 09:41:09 +00:00
|
|
|
type: string;
|
2021-01-13 12:43:46 +00:00
|
|
|
attributes: collectionAttributes
|
|
|
|
sharees: user[];
|
|
|
|
updationTime: number;
|
|
|
|
encryptedKey: string;
|
|
|
|
keyDecryptionNonce: string;
|
|
|
|
isDeleted: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface collectionAttributes {
|
|
|
|
encryptedPath?: string;
|
|
|
|
pathDecryptionNonce?: string
|
|
|
|
};
|
|
|
|
|
2021-01-14 11:31:20 +00:00
|
|
|
export interface collectionLatestFile {
|
|
|
|
collection: collection
|
|
|
|
file: file;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-21 02:24:17 +00:00
|
|
|
const getCollectionSecrets = async (collection: collection, masterKey: string) => {
|
2021-01-13 05:31:02 +00:00
|
|
|
const worker = await new CryptoWorker();
|
|
|
|
const userID = getData(LS_KEYS.USER).id;
|
2021-01-18 02:27:00 +00:00
|
|
|
let decryptedKey: string;
|
2021-01-21 02:24:17 +00:00
|
|
|
let decryptedName: string;
|
2021-01-13 05:31:02 +00:00
|
|
|
if (collection.owner.id == userID) {
|
2021-01-18 02:27:00 +00:00
|
|
|
decryptedKey = await worker.decryptB64(
|
|
|
|
collection.encryptedKey,
|
|
|
|
collection.keyDecryptionNonce,
|
|
|
|
masterKey
|
2021-01-13 05:31:02 +00:00
|
|
|
);
|
2021-01-21 02:24:17 +00:00
|
|
|
decryptedName = collection.name || await worker.decryptString(
|
|
|
|
collection.encryptedName,
|
|
|
|
collection.nameDecryptionNonce,
|
|
|
|
masterKey);
|
2021-01-13 05:31:02 +00:00
|
|
|
} else {
|
|
|
|
const keyAttributes = getData(LS_KEYS.KEY_ATTRIBUTES);
|
2021-01-18 02:27:00 +00:00
|
|
|
const secretKey = await worker.decryptB64(
|
|
|
|
keyAttributes.encryptedSecretKey,
|
|
|
|
keyAttributes.secretKeyDecryptionNonce,
|
|
|
|
masterKey
|
2021-01-13 05:31:02 +00:00
|
|
|
);
|
|
|
|
decryptedKey = await worker.boxSealOpen(
|
2021-01-21 02:24:17 +00:00
|
|
|
collection.encryptedKey,
|
|
|
|
keyAttributes.publicKey,
|
|
|
|
secretKey
|
2021-01-13 05:31:02 +00:00
|
|
|
);
|
2021-01-21 02:24:17 +00:00
|
|
|
decryptedName = collection.name || await worker.decryptString(
|
|
|
|
collection.encryptedName,
|
|
|
|
collection.nameDecryptionNonce,
|
|
|
|
secretKey);
|
2021-01-13 05:31:02 +00:00
|
|
|
}
|
|
|
|
return {
|
|
|
|
...collection,
|
|
|
|
key: decryptedKey,
|
2021-01-21 02:24:17 +00:00
|
|
|
name: decryptedName
|
2021-01-13 05:31:02 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const getCollections = async (
|
|
|
|
token: string,
|
|
|
|
sinceTime: string,
|
2021-01-18 02:27:00 +00:00
|
|
|
key: string
|
2021-01-13 05:31:02 +00:00
|
|
|
): Promise<collection[]> => {
|
|
|
|
const resp = await HTTPService.get(`${ENDPOINT}/collections`, {
|
|
|
|
token: token,
|
|
|
|
sinceTime: sinceTime,
|
|
|
|
});
|
2021-01-18 02:27:00 +00:00
|
|
|
const ignore: Set<number> = new Set([206, 208]);
|
|
|
|
const promises: Promise<collection>[] = resp.data.collections.filter(collection => !ignore.has(collection.id)).map(
|
2021-01-21 02:24:17 +00:00
|
|
|
(collection: collection) => getCollectionSecrets(collection, key)
|
2021-01-13 05:31:02 +00:00
|
|
|
);
|
|
|
|
return await Promise.all(promises);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const fetchCollections = async (token: string, key: string) => {
|
2021-01-15 11:11:06 +00:00
|
|
|
const collections = await getCollections(token, '0', key);
|
|
|
|
const favCollection = collections.filter(collection => collection.type === CollectionType.favorites);
|
|
|
|
await localForage.setItem('fav-collection', favCollection);
|
|
|
|
return collections;
|
2021-01-13 05:31:02 +00:00
|
|
|
};
|
2021-01-13 12:43:46 +00:00
|
|
|
|
2021-01-14 11:31:20 +00:00
|
|
|
export const getCollectionLatestFile = async (
|
|
|
|
collections: collection[],
|
|
|
|
token
|
|
|
|
): Promise<collectionLatestFile[]> => {
|
|
|
|
return Promise.all(
|
|
|
|
collections.map(async collection => {
|
|
|
|
const sinceTime: string = (Number(await localForage.getItem<string>(`${collection.id}-time`)) - 1).toString();
|
|
|
|
const file: file[] = await getFiles([collection], sinceTime, "100", token);
|
|
|
|
return {
|
|
|
|
file: file[0],
|
|
|
|
collection,
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
};
|
|
|
|
|
2021-01-20 12:05:04 +00:00
|
|
|
export const getFavItemIds = async (files: file[]): Promise<Set<number>> => {
|
|
|
|
|
|
|
|
let favCollection: collection = (await localForage.getItem<collection>('fav-collection'))[0];
|
|
|
|
if (!favCollection)
|
|
|
|
return new Set();
|
2021-01-20 13:04:27 +00:00
|
|
|
|
2021-01-20 12:05:04 +00:00
|
|
|
return new Set(files.filter(file => file.collectionID === Number(favCollection.id)).map((file): number => file.id));
|
|
|
|
}
|
|
|
|
|
2021-01-15 17:04:33 +00:00
|
|
|
export const createAlbum = async (albumName: string) => {
|
2021-01-15 11:11:06 +00:00
|
|
|
return AddCollection(albumName, CollectionType.album);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-21 02:24:17 +00:00
|
|
|
export const AddCollection = async (collectionName: string, type: CollectionType) => {
|
2021-01-13 12:43:46 +00:00
|
|
|
const worker = await new CryptoWorker();
|
2021-01-15 11:11:06 +00:00
|
|
|
const encryptionKey = await getActualKey();
|
|
|
|
const token = getToken();
|
2021-01-19 04:32:12 +00:00
|
|
|
const collectionKey: string = await worker.generateMasterKey();
|
2021-01-15 11:11:06 +00:00
|
|
|
const { encryptedData: encryptedKey, nonce: keyDecryptionNonce }: keyEncryptionResult = await worker.encryptToB64(collectionKey, encryptionKey);
|
2021-01-21 02:24:17 +00:00
|
|
|
const { encryptedData: encryptedName, nonce: nameDecryptionNonce }: keyEncryptionResult = await worker.encryptToB64(collectionName, encryptionKey);
|
2021-01-13 12:43:46 +00:00
|
|
|
const newCollection: collection = {
|
|
|
|
id: null,
|
|
|
|
owner: null,
|
|
|
|
encryptedKey,
|
|
|
|
keyDecryptionNonce,
|
2021-01-21 02:24:17 +00:00
|
|
|
encryptedName,
|
|
|
|
nameDecryptionNonce,
|
2021-01-15 11:11:06 +00:00
|
|
|
type,
|
2021-01-13 12:43:46 +00:00
|
|
|
attributes: {},
|
|
|
|
sharees: null,
|
|
|
|
updationTime: null,
|
|
|
|
isDeleted: false
|
|
|
|
};
|
|
|
|
let createdCollection: collection = await createCollection(newCollection, token);
|
2021-01-21 02:24:17 +00:00
|
|
|
createdCollection = await getCollectionSecrets(createdCollection, encryptionKey);
|
2021-01-13 12:43:46 +00:00
|
|
|
return createdCollection;
|
|
|
|
}
|
|
|
|
|
|
|
|
const createCollection = async (collectionData: collection, token: string): Promise<collection> => {
|
|
|
|
const response = await HTTPService.post(`${ENDPOINT}/collections`, collectionData, { token });
|
2021-01-14 09:41:09 +00:00
|
|
|
return response.data.collection;
|
2021-01-13 12:43:46 +00:00
|
|
|
}
|
2021-01-15 11:11:06 +00:00
|
|
|
|
|
|
|
export const addToFavorites = async (file: file) => {
|
|
|
|
let favCollection: collection = (await localForage.getItem<collection>('fav-collection'))[0];
|
|
|
|
if (!favCollection) {
|
|
|
|
favCollection = await AddCollection("Favorites", CollectionType.favorites);
|
|
|
|
await localForage.setItem('fav-collection', favCollection);
|
|
|
|
}
|
|
|
|
await addtoCollection(favCollection, [file])
|
|
|
|
}
|
|
|
|
|
2021-01-20 13:04:27 +00:00
|
|
|
export const removeFromFavorites = async (file: file) => {
|
|
|
|
let favCollection: collection = (await localForage.getItem<collection>('fav-collection'))[0];
|
|
|
|
await removeFromCollection(favCollection, [file])
|
|
|
|
}
|
|
|
|
|
2021-01-15 11:11:06 +00:00
|
|
|
const addtoCollection = async (collection: collection, files: file[]) => {
|
|
|
|
const params = new Object();
|
|
|
|
const worker = await new CryptoWorker();
|
|
|
|
const token = getToken();
|
|
|
|
params["collectionID"] = collection.id;
|
2021-01-20 13:04:27 +00:00
|
|
|
await Promise.all(files.map(async file => {
|
2021-01-15 11:11:06 +00:00
|
|
|
file.collectionID = Number(collection.id);
|
2021-01-19 04:32:12 +00:00
|
|
|
const newEncryptedKey: keyEncryptionResult = await worker.encryptToB64(file.key, collection.key);
|
2021-01-15 11:11:06 +00:00
|
|
|
file.encryptedKey = newEncryptedKey.encryptedData;
|
|
|
|
file.keyDecryptionNonce = newEncryptedKey.nonce;
|
|
|
|
if (params["files"] == undefined) {
|
|
|
|
params["files"] = [];
|
|
|
|
}
|
|
|
|
params["files"].push({
|
|
|
|
id: file.id,
|
|
|
|
encryptedKey: file.encryptedKey,
|
|
|
|
keyDecryptionNonce: file.keyDecryptionNonce
|
|
|
|
})
|
|
|
|
return file;
|
|
|
|
}));
|
|
|
|
await HTTPService.post(`${ENDPOINT}/collections/add-files`, params, { token });
|
2021-01-20 12:05:04 +00:00
|
|
|
}
|
2021-01-20 13:04:27 +00:00
|
|
|
const removeFromCollection = async (collection: collection, files: file[]) => {
|
|
|
|
const params = new Object();
|
|
|
|
const token = getToken();
|
|
|
|
params["collectionID"] = collection.id;
|
|
|
|
await Promise.all(files.map(async file => {
|
|
|
|
if (params["fileIDs"] == undefined) {
|
|
|
|
params["fileIDs"] = [];
|
|
|
|
}
|
|
|
|
params["fileIDs"].push(file.id);
|
|
|
|
}));
|
|
|
|
await HTTPService.post(`${ENDPOINT}/collections/remove-files`, params, { token });
|
|
|
|
}
|
|
|
|
|