Merge pull request #388 from ente-io/showErrForPopularAlbums
Show err for popular albums
This commit is contained in:
commit
3400d13058
|
@ -28,6 +28,8 @@ module.exports = {
|
|||
'base-uri ': "'self'",
|
||||
'frame-ancestors': " 'none'",
|
||||
'form-action': "'none'",
|
||||
'report-uri': ' https://csp-reporter.ente.io',
|
||||
'report-to': ' https://csp-reporter.ente.io',
|
||||
},
|
||||
|
||||
WORKBOX_CONFIG: {
|
||||
|
@ -38,10 +40,9 @@ module.exports = {
|
|||
ALL_ROUTES: '/(.*)',
|
||||
|
||||
buildCSPHeader: (directives) => ({
|
||||
'Content-Security-Policy': Object.entries(directives).reduce(
|
||||
(acc, [key, value]) => acc + `${key} ${value};`,
|
||||
''
|
||||
),
|
||||
'Content-Security-Policy-Report-Only': Object.entries(
|
||||
directives
|
||||
).reduce((acc, [key, value]) => acc + `${key} ${value};`, ''),
|
||||
}),
|
||||
|
||||
convertToNextHeaderFormat: (headers) =>
|
||||
|
|
|
@ -8,5 +8,5 @@
|
|||
X-Frame-Options: deny
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Referrer-Policy: same-origin
|
||||
Content-Security-Policy-Report-Only: default-src 'none'; img-src 'self' blob:; media-src 'self' blob:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self' 'unsafe-eval' blob:; manifest-src': 'self'; connect-src 'self' https://*.ente.io data: blob: https://ente-prod-eu.s3.eu-central-003.backblazeb2.com ; base-uri 'self'; frame-ancestors 'none'; form-action 'none'; report-uri https://csp-reporter.ente.io; report-to https://csp-reporter.ente.io;
|
||||
Content-Security-Policy-Report-Only: default-src 'none'; img-src 'self' blob:; media-src 'self' blob:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self' 'unsafe-eval' blob:; manifest-src 'self'; connect-src 'self' https://*.ente.io data: blob: https://ente-prod-eu.s3.eu-central-003.backblazeb2.com ; base-uri 'self'; frame-ancestors 'none'; form-action 'none'; report-uri https://csp-reporter.ente.io; report-to https://csp-reporter.ente.io;
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@ Sentry.init({
|
|||
event.request.url = currentURL;
|
||||
return event;
|
||||
},
|
||||
integrations: function (i) {
|
||||
return i.filter(function (i) {
|
||||
return i.name !== 'Breadcrumbs';
|
||||
});
|
||||
},
|
||||
// ...
|
||||
// Note: if you want to override the automatic release value, do not set a
|
||||
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
|
||||
|
|
|
@ -410,7 +410,8 @@ const PhotoFrame = ({
|
|||
url =
|
||||
await PublicCollectionDownloadManager.getThumbnail(
|
||||
item,
|
||||
publicCollectionGalleryContext.token
|
||||
publicCollectionGalleryContext.token,
|
||||
publicCollectionGalleryContext.passwordToken
|
||||
);
|
||||
} else {
|
||||
url = await DownloadManager.getThumbnail(item);
|
||||
|
@ -447,6 +448,7 @@ const PhotoFrame = ({
|
|||
url = await PublicCollectionDownloadManager.getFile(
|
||||
item,
|
||||
publicCollectionGalleryContext.token,
|
||||
publicCollectionGalleryContext.passwordToken,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -705,7 +705,8 @@ function PhotoSwipe(props: Iprops) {
|
|||
await downloadFile(
|
||||
file,
|
||||
publicCollectionGalleryContext.accessedThroughSharedURL,
|
||||
publicCollectionGalleryContext.token
|
||||
publicCollectionGalleryContext.token,
|
||||
publicCollectionGalleryContext.passwordToken
|
||||
);
|
||||
|
||||
galleryContext.finishLoading();
|
||||
|
|
|
@ -194,7 +194,8 @@ export default function PreviewCard(props: IProps) {
|
|||
url =
|
||||
await PublicCollectionDownloadManager.getThumbnail(
|
||||
file,
|
||||
publicCollectionGalleryContext.token
|
||||
publicCollectionGalleryContext.token,
|
||||
publicCollectionGalleryContext.passwordToken
|
||||
);
|
||||
} else {
|
||||
url = await DownloadManager.getThumbnail(file);
|
||||
|
|
|
@ -67,6 +67,7 @@ export default function Credentials() {
|
|||
keyAttributes.keyDecryptionNonce,
|
||||
kek
|
||||
);
|
||||
|
||||
if (isFirstLogin()) {
|
||||
await generateAndSaveIntermediateKeyAttributes(
|
||||
passphrase,
|
||||
|
|
|
@ -3,11 +3,14 @@ import PhotoFrame from 'components/PhotoFrame';
|
|||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
getLocalPublicCollection,
|
||||
getLocalPublicCollectionPassword,
|
||||
getLocalPublicFiles,
|
||||
getPublicCollection,
|
||||
getPublicCollectionUID,
|
||||
removePublicCollectionWithFiles,
|
||||
savePublicCollectionPassword,
|
||||
syncPublicFiles,
|
||||
verifyPublicCollectionPassword,
|
||||
} from 'services/publicCollectionService';
|
||||
import { Collection } from 'types/collection';
|
||||
import { EnteFile } from 'types/file';
|
||||
|
@ -28,6 +31,10 @@ import LoadingBar from 'react-top-loading-bar';
|
|||
import CryptoWorker from 'utils/crypto';
|
||||
import { PAGES } from 'constants/pages';
|
||||
import { useRouter } from 'next/router';
|
||||
import LogoImg from 'components/LogoImg';
|
||||
import SingleInputForm from 'components/SingleInputForm';
|
||||
import { Card } from 'react-bootstrap';
|
||||
import { logError } from 'utils/sentry';
|
||||
|
||||
const Loader = () => (
|
||||
<Container>
|
||||
|
@ -39,6 +46,8 @@ const Loader = () => (
|
|||
const bs58 = require('bs58');
|
||||
export default function PublicCollectionGallery() {
|
||||
const token = useRef<string>(null);
|
||||
// passwordJWTToken refers to the jwt token which is used for album protected by password.
|
||||
const [passwordJWTToken, setPasswordJWTToken] = useState<string>(null);
|
||||
const collectionKey = useRef<string>(null);
|
||||
const url = useRef<string>(null);
|
||||
const [publicFiles, setPublicFiles] = useState<EnteFile[]>(null);
|
||||
|
@ -54,6 +63,8 @@ export default function PublicCollectionGallery() {
|
|||
const loadingBar = useRef(null);
|
||||
const isLoadingBarRunning = useRef(false);
|
||||
const router = useRouter();
|
||||
const [isPasswordProtected, setIsPasswordProtected] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const openMessageDialog = () => setMessageDialogView(true);
|
||||
const closeMessageDialog = () => setMessageDialogView(false);
|
||||
|
@ -114,7 +125,11 @@ export default function PublicCollectionGallery() {
|
|||
const localPublicFiles = sortFiles(
|
||||
mergeMetadata(localFiles)
|
||||
);
|
||||
const localPasswordJWTToken =
|
||||
await getLocalPublicCollectionPassword(collectionUID);
|
||||
|
||||
setPublicFiles(localPublicFiles);
|
||||
setPasswordJWTToken(localPasswordJWTToken);
|
||||
}
|
||||
await syncWithRemote();
|
||||
} finally {
|
||||
|
@ -134,13 +149,31 @@ export default function PublicCollectionGallery() {
|
|||
collectionKey.current
|
||||
);
|
||||
setPublicCollection(collection);
|
||||
|
||||
await syncPublicFiles(token.current, collection, setPublicFiles);
|
||||
setErrorMessage(null);
|
||||
// check if we need to prompt user for the password
|
||||
if (
|
||||
(collection?.publicURLs?.[0]?.passwordEnabled ?? false) &&
|
||||
!passwordJWTToken
|
||||
) {
|
||||
setIsPasswordProtected(true);
|
||||
} else {
|
||||
await syncPublicFiles(
|
||||
token.current,
|
||||
collection,
|
||||
setPublicFiles
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
const parsedError = parseSharingErrorCodes(e);
|
||||
if (parsedError.message === CustomError.TOKEN_EXPIRED) {
|
||||
setErrorMessage(constants.LINK_EXPIRED);
|
||||
if (
|
||||
parsedError.message === CustomError.TOKEN_EXPIRED ||
|
||||
parsedError.message === CustomError.TOO_MANY_REQUESTS
|
||||
) {
|
||||
setErrorMessage(
|
||||
parsedError.message === CustomError.TOO_MANY_REQUESTS
|
||||
? constants.LINK_TOO_MANY_REQUESTS
|
||||
: constants.LINK_EXPIRED
|
||||
);
|
||||
// share has been disabled
|
||||
// local cache should be cleared
|
||||
removePublicCollectionWithFiles(
|
||||
|
@ -155,6 +188,54 @@ export default function PublicCollectionGallery() {
|
|||
}
|
||||
};
|
||||
|
||||
const verifyLinkPassword = async (password, setFieldError) => {
|
||||
try {
|
||||
const cryptoWorker = await new CryptoWorker();
|
||||
let hashedPassword: string = null;
|
||||
try {
|
||||
const publicUrl = publicCollection.publicURLs[0];
|
||||
hashedPassword = await cryptoWorker.deriveKey(
|
||||
password,
|
||||
publicUrl.nonce,
|
||||
publicUrl.opsLimit,
|
||||
publicUrl.memLimit
|
||||
);
|
||||
} catch (e) {
|
||||
logError(e, 'failed to derive key for verifyLinkPassword');
|
||||
setFieldError(
|
||||
'passphrase',
|
||||
`${constants.UNKNOWN_ERROR} ${e.message}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
const collectionUID = getPublicCollectionUID(token.current);
|
||||
try {
|
||||
const jwtToken = await verifyPublicCollectionPassword(
|
||||
token.current,
|
||||
hashedPassword
|
||||
);
|
||||
setPasswordJWTToken(jwtToken);
|
||||
savePublicCollectionPassword(collectionUID, jwtToken);
|
||||
} catch (e) {
|
||||
// reset local password token
|
||||
logError(e, 'failed to validate password for album');
|
||||
const parsedError = parseSharingErrorCodes(e);
|
||||
if (parsedError.message === CustomError.TOKEN_EXPIRED) {
|
||||
setFieldError('passphrase', constants.INCORRECT_PASSPHRASE);
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
await syncWithRemote();
|
||||
finishLoadingBar();
|
||||
} catch (e) {
|
||||
setFieldError(
|
||||
'passphrase',
|
||||
`${constants.UNKNOWN_ERROR} ${e.message}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if (!publicFiles && loading) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
@ -162,6 +243,30 @@ export default function PublicCollectionGallery() {
|
|||
if (errorMessage && !loading) {
|
||||
return <Container>{errorMessage}</Container>;
|
||||
}
|
||||
if (isPasswordProtected && !passwordJWTToken && !loading) {
|
||||
return (
|
||||
<Container>
|
||||
<Card style={{ width: '332px' }} className="text-center">
|
||||
<Card.Body style={{ padding: '40px 30px' }}>
|
||||
<Card.Title style={{ marginBottom: '24px' }}>
|
||||
<LogoImg src="/icon.svg" />
|
||||
{constants.PASSWORD}
|
||||
</Card.Title>
|
||||
<Card.Subtitle style={{ marginBottom: '2rem' }}>
|
||||
{/* <LogoImg src="/icon.svg" /> */}
|
||||
{constants.LINK_PASSWORD}
|
||||
</Card.Subtitle>
|
||||
<SingleInputForm
|
||||
callback={verifyLinkPassword}
|
||||
placeholder={constants.RETURN_PASSPHRASE_HINT}
|
||||
buttonText={'unlock'}
|
||||
fieldType="password"
|
||||
/>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
if (!publicFiles && !loading) {
|
||||
return <Container>{constants.NOT_FOUND}</Container>;
|
||||
|
@ -172,6 +277,7 @@ export default function PublicCollectionGallery() {
|
|||
value={{
|
||||
...defaultPublicCollectionGalleryContext,
|
||||
token: token.current,
|
||||
passwordToken: passwordJWTToken,
|
||||
accessedThroughSharedURL: true,
|
||||
setDialogMessage,
|
||||
openReportForm,
|
||||
|
|
|
@ -19,7 +19,11 @@ class PublicCollectionDownloadManager {
|
|||
private fileObjectURLPromise = new Map<string, Promise<string>>();
|
||||
private thumbnailObjectURLPromise = new Map<number, Promise<string>>();
|
||||
|
||||
public async getThumbnail(file: EnteFile, token: string) {
|
||||
public async getThumbnail(
|
||||
file: EnteFile,
|
||||
token: string,
|
||||
passwordToken: string
|
||||
) {
|
||||
try {
|
||||
if (!token) {
|
||||
return null;
|
||||
|
@ -42,7 +46,11 @@ class PublicCollectionDownloadManager {
|
|||
if (cacheResp) {
|
||||
return URL.createObjectURL(await cacheResp.blob());
|
||||
}
|
||||
const thumb = await this.downloadThumb(token, file);
|
||||
const thumb = await this.downloadThumb(
|
||||
token,
|
||||
passwordToken,
|
||||
file
|
||||
);
|
||||
const thumbBlob = new Blob([thumb]);
|
||||
try {
|
||||
await thumbnailCache?.put(
|
||||
|
@ -65,11 +73,18 @@ class PublicCollectionDownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
private downloadThumb = async (token: string, file: EnteFile) => {
|
||||
private downloadThumb = async (
|
||||
token: string,
|
||||
passwordToken: string,
|
||||
file: EnteFile
|
||||
) => {
|
||||
const resp = await HTTPService.get(
|
||||
getPublicCollectionThumbnailURL(file.id),
|
||||
null,
|
||||
{ 'X-Auth-Access-Token': token },
|
||||
{
|
||||
'X-Auth-Access-Token': token,
|
||||
'X-Auth-Access-Token-JWT': passwordToken,
|
||||
},
|
||||
{ responseType: 'arraybuffer' }
|
||||
);
|
||||
if (typeof resp.data === 'undefined') {
|
||||
|
@ -84,14 +99,23 @@ class PublicCollectionDownloadManager {
|
|||
return decrypted;
|
||||
};
|
||||
|
||||
getFile = async (file: EnteFile, token: string, forPreview = false) => {
|
||||
getFile = async (
|
||||
file: EnteFile,
|
||||
token: string,
|
||||
passwordToken: string,
|
||||
forPreview = false
|
||||
) => {
|
||||
const shouldBeConverted = forPreview && needsConversionForPreview(file);
|
||||
const fileKey = shouldBeConverted
|
||||
? `${file.id}_converted`
|
||||
: `${file.id}`;
|
||||
try {
|
||||
const getFilePromise = async (convert: boolean) => {
|
||||
const fileStream = await this.downloadFile(token, file);
|
||||
const fileStream = await this.downloadFile(
|
||||
token,
|
||||
passwordToken,
|
||||
file
|
||||
);
|
||||
let fileBlob = await new Response(fileStream).blob();
|
||||
if (convert) {
|
||||
fileBlob = await convertForPreview(file, fileBlob);
|
||||
|
@ -117,7 +141,7 @@ class PublicCollectionDownloadManager {
|
|||
return await this.fileObjectURLPromise.get(file.id.toString());
|
||||
}
|
||||
|
||||
async downloadFile(token: string, file: EnteFile) {
|
||||
async downloadFile(token: string, passwordToken: string, file: EnteFile) {
|
||||
const worker = await new CryptoWorker();
|
||||
if (!token) {
|
||||
return null;
|
||||
|
@ -129,7 +153,10 @@ class PublicCollectionDownloadManager {
|
|||
const resp = await HTTPService.get(
|
||||
getPublicCollectionFileURL(file.id),
|
||||
null,
|
||||
{ 'X-Auth-Access-Token': token },
|
||||
{
|
||||
'X-Auth-Access-Token': token,
|
||||
'X-Auth-Access-Token-JWT': passwordToken,
|
||||
},
|
||||
{ responseType: 'arraybuffer' }
|
||||
);
|
||||
if (typeof resp.data === 'undefined') {
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from 'types/publicCollection';
|
||||
import CryptoWorker from 'utils/crypto';
|
||||
import { REPORT_REASON } from 'constants/publicCollection';
|
||||
import { CustomError, parseSharingErrorCodes } from 'utils/error';
|
||||
|
||||
const ENDPOINT = getEndpoint();
|
||||
const PUBLIC_COLLECTION_FILES_TABLE = 'public-collection-files';
|
||||
|
@ -22,6 +23,9 @@ export const getPublicCollectionUID = (token: string) => `${token}`;
|
|||
const getPublicCollectionSyncTimeUID = (collectionUID: string) =>
|
||||
`public-${collectionUID}-time`;
|
||||
|
||||
const getPublicCollectionPasswordKey = (collectionUID: string) =>
|
||||
`public-${collectionUID}-passkey`;
|
||||
|
||||
export const getLocalPublicFiles = async (collectionUID: string) => {
|
||||
const localSavedPublicCollectionFiles =
|
||||
(
|
||||
|
@ -55,6 +59,26 @@ export const savePublicCollectionFiles = async (
|
|||
);
|
||||
};
|
||||
|
||||
export const getLocalPublicCollectionPassword = async (
|
||||
collectionKey: string
|
||||
): Promise<string> => {
|
||||
return (
|
||||
(await localForage.getItem<string>(
|
||||
getPublicCollectionPasswordKey(collectionKey)
|
||||
)) || ''
|
||||
);
|
||||
};
|
||||
|
||||
export const savePublicCollectionPassword = async (
|
||||
collectionKey: string,
|
||||
passToken: string
|
||||
): Promise<string> => {
|
||||
return await localForage.setItem<string>(
|
||||
getPublicCollectionPasswordKey(collectionKey),
|
||||
passToken
|
||||
);
|
||||
};
|
||||
|
||||
export const getLocalPublicCollection = async (collectionKey: string) => {
|
||||
const localCollections =
|
||||
(await localForage.getItem<Collection[]>(PUBLIC_COLLECTIONS_TABLE)) ||
|
||||
|
@ -134,11 +158,15 @@ export const syncPublicFiles = async (
|
|||
const lastSyncTime = await getPublicCollectionLastSyncTime(
|
||||
collectionUID
|
||||
);
|
||||
if (collection.updationTime === lastSyncTime) {
|
||||
return files;
|
||||
}
|
||||
const passwordToken = await getLocalPublicCollectionPassword(
|
||||
collectionUID
|
||||
);
|
||||
// if (collection.updationTime === lastSyncTime) {
|
||||
// return files;
|
||||
// }
|
||||
const fetchedFiles = await getPublicFiles(
|
||||
token,
|
||||
passwordToken,
|
||||
collection,
|
||||
lastSyncTime,
|
||||
files,
|
||||
|
@ -171,7 +199,12 @@ export const syncPublicFiles = async (
|
|||
);
|
||||
setPublicFiles([...sortFiles(mergeMetadata(files))]);
|
||||
} catch (e) {
|
||||
const parsedError = parseSharingErrorCodes(e);
|
||||
logError(e, 'failed to sync shared collection files');
|
||||
if (parsedError.message === CustomError.TOKEN_EXPIRED) {
|
||||
console.log('invalid token or password');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return [...sortFiles(mergeMetadata(files))];
|
||||
} catch (e) {
|
||||
|
@ -182,6 +215,7 @@ export const syncPublicFiles = async (
|
|||
|
||||
const getPublicFiles = async (
|
||||
token: string,
|
||||
passwordToken: string,
|
||||
collection: Collection,
|
||||
sinceTime: number,
|
||||
files: EnteFile[],
|
||||
|
@ -203,6 +237,7 @@ const getPublicFiles = async (
|
|||
{
|
||||
'Cache-Control': 'no-cache',
|
||||
'X-Auth-Access-Token': token,
|
||||
'X-Auth-Access-Token-JWT': passwordToken,
|
||||
}
|
||||
);
|
||||
decryptedFiles.push(
|
||||
|
@ -249,7 +284,7 @@ export const getPublicCollection = async (
|
|||
null,
|
||||
{ 'Cache-Control': 'no-cache', 'X-Auth-Access-Token': token }
|
||||
);
|
||||
const fetchedCollection = resp.data?.collection;
|
||||
const fetchedCollection = resp.data.collection;
|
||||
const collectionName = await decryptCollectionName(
|
||||
fetchedCollection,
|
||||
collectionKey
|
||||
|
@ -267,6 +302,25 @@ export const getPublicCollection = async (
|
|||
}
|
||||
};
|
||||
|
||||
export const verifyPublicCollectionPassword = async (
|
||||
token: string,
|
||||
passwordHash: string
|
||||
): Promise<string> => {
|
||||
try {
|
||||
const resp = await HTTPService.post(
|
||||
`${ENDPOINT}/public-collection/verify-password`,
|
||||
{ passHash: passwordHash },
|
||||
null,
|
||||
{ 'Cache-Control': 'no-cache', 'X-Auth-Access-Token': token }
|
||||
);
|
||||
const jwtToken = resp.data.jwtToken;
|
||||
return jwtToken;
|
||||
} catch (e) {
|
||||
logError(e, 'failed to get public collection');
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
const decryptCollectionName = async (
|
||||
collection: Collection,
|
||||
collectionKey: string
|
||||
|
@ -311,6 +365,7 @@ export const removePublicCollectionWithFiles = async (
|
|||
collectionKey: string
|
||||
) => {
|
||||
const collectionUID = getPublicCollectionUID(token);
|
||||
console.log('remove information about public collection ' + collectionUID);
|
||||
const publicCollections =
|
||||
(await localForage.getItem<Collection[]>(PUBLIC_COLLECTIONS_TABLE)) ||
|
||||
[];
|
||||
|
@ -320,7 +375,7 @@ export const removePublicCollectionWithFiles = async (
|
|||
(collection) => collection.key !== collectionKey
|
||||
)
|
||||
);
|
||||
|
||||
await localForage.removeItem(getPublicCollectionPasswordKey(collectionUID));
|
||||
await localForage.removeItem(getPublicCollectionSyncTimeUID(collectionUID));
|
||||
|
||||
const publicCollectionFiles =
|
||||
|
|
|
@ -27,6 +27,8 @@ export interface PublicURL {
|
|||
enableDownload: boolean;
|
||||
passwordEnabled: boolean;
|
||||
nonce: string;
|
||||
opsLimit: number;
|
||||
memLimit: number;
|
||||
}
|
||||
|
||||
export interface CreatePublicAccessTokenRequest {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { EnteFile } from 'types/file';
|
|||
|
||||
export interface PublicCollectionGalleryContextType {
|
||||
token: string;
|
||||
passwordToken: string;
|
||||
accessedThroughSharedURL: boolean;
|
||||
setDialogMessage: SetDialogMessage;
|
||||
openReportForm: () => void;
|
||||
|
|
|
@ -35,6 +35,7 @@ export enum CustomError {
|
|||
REQUEST_CANCELLED = 'request canceled',
|
||||
REQUEST_FAILED = 'request failed',
|
||||
TOKEN_EXPIRED = 'token expired',
|
||||
TOO_MANY_REQUESTS = 'too many requests',
|
||||
BAD_REQUEST = 'bad request',
|
||||
SUBSCRIPTION_NEEDED = 'subscription not present',
|
||||
NOT_FOUND = 'not found ',
|
||||
|
@ -121,9 +122,11 @@ export const parseSharingErrorCodes = (error) => {
|
|||
break;
|
||||
case ServerErrorCodes.SESSION_EXPIRED:
|
||||
case ServerErrorCodes.TOKEN_EXPIRED:
|
||||
case ServerErrorCodes.TOO_MANY_REQUEST:
|
||||
parsedMessage = CustomError.TOKEN_EXPIRED;
|
||||
break;
|
||||
case ServerErrorCodes.TOO_MANY_REQUEST:
|
||||
parsedMessage = CustomError.TOO_MANY_REQUESTS;
|
||||
break;
|
||||
default:
|
||||
parsedMessage = `${constants.UNKNOWN_ERROR} statusCode:${errorCode}`;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ export function downloadAsFile(filename: string, content: string) {
|
|||
export async function downloadFile(
|
||||
file: EnteFile,
|
||||
accessedThroughSharedURL: boolean,
|
||||
token?: string
|
||||
token?: string,
|
||||
passwordToken?: string
|
||||
) {
|
||||
let fileURL: string;
|
||||
let tempURL: string;
|
||||
|
@ -58,6 +59,7 @@ export async function downloadFile(
|
|||
await new Response(
|
||||
await PublicCollectionDownloadManager.downloadFile(
|
||||
token,
|
||||
passwordToken,
|
||||
file
|
||||
)
|
||||
).blob()
|
||||
|
|
|
@ -4,6 +4,7 @@ import { PublicCollectionGalleryContextType } from 'types/publicCollection';
|
|||
export const defaultPublicCollectionGalleryContext: PublicCollectionGalleryContextType =
|
||||
{
|
||||
token: null,
|
||||
passwordToken: null,
|
||||
accessedThroughSharedURL: false,
|
||||
setDialogMessage: () => null,
|
||||
openReportForm: () => null,
|
||||
|
|
|
@ -74,6 +74,7 @@ const englishConstants = {
|
|||
SENDING: 'sending...',
|
||||
SENT: 'sent!',
|
||||
PASSWORD: 'password',
|
||||
LINK_PASSWORD: 'enter password to unlock the album',
|
||||
ENTER_PASSPHRASE: 'enter your password',
|
||||
RETURN_PASSPHRASE_HINT: 'password',
|
||||
SET_PASSPHRASE: 'set password',
|
||||
|
@ -627,7 +628,8 @@ const englishConstants = {
|
|||
ALBUM_URL: 'album url',
|
||||
PUBLIC_SHARING: 'link sharing',
|
||||
NOT_FOUND: '404 - not found',
|
||||
LINK_EXPIRED: 'the link has expired!',
|
||||
LINK_EXPIRED: 'the link is either disabled or expired!',
|
||||
LINK_TOO_MANY_REQUESTS: 'this album is too popular for us to handle!',
|
||||
DISABLE_PUBLIC_SHARING: "'disable public sharing",
|
||||
DISABLE_PUBLIC_SHARING_MESSAGE:
|
||||
'are you sure you want to disable public sharing?',
|
||||
|
|
Loading…
Reference in a new issue