🔐 Initial change on the public links using anonymous users (#69)
* Initial change on the public links using anonymous users Co-authored-by: Anton Shepilov <anton.shepilov@gmail.com>
This commit is contained in:
@@ -32,7 +32,7 @@ export default (props: { driveItem: DriveItem & { user?: UserType } }) => {
|
||||
const input = useRecoilValue(SearchInputState);
|
||||
const currentWorkspaceId = useRouterWorkspace();
|
||||
const companyApplications = useCompanyApplications();
|
||||
const [_, setParentId] = useRecoilState(DriveCurrentFolderAtom('root'));
|
||||
const [_, setParentId] = useRecoilState(DriveCurrentFolderAtom({ initialFolderId: 'root' }));
|
||||
const tdriveDriveApplicationId =
|
||||
companyApplications.applications.find(application => {
|
||||
return application.identity.code === 'tdrive_drive';
|
||||
|
||||
@@ -2,6 +2,7 @@ import Api from '../../global/framework/api-service';
|
||||
import { DriveItem, DriveItemDetails, DriveItemVersion } from '../types';
|
||||
import Workspace from '@deprecated/workspaces/workspaces';
|
||||
import Logger from 'features/global/framework/logger-service';
|
||||
import { JWTDataType } from 'app/features/auth/jwt-storage-service';
|
||||
export interface BaseSearchOptions {
|
||||
company_id?: string;
|
||||
workspace_id?: string;
|
||||
@@ -32,10 +33,7 @@ export const setTdriveTabToken = (token: string | null) => {
|
||||
tdriveTabToken = token;
|
||||
};
|
||||
|
||||
const appendPublicAndTdriveToken = (useAnd?: boolean) => {
|
||||
if (publicLinkToken) {
|
||||
return `${useAnd ? '&' : '?'}public_token=${publicLinkToken}`;
|
||||
}
|
||||
const appendTdriveToken = (useAnd?: boolean) => {
|
||||
if (tdriveTabToken) {
|
||||
return `${useAnd ? '&' : '?'}tdrive_tab_token=${tdriveTabToken}`;
|
||||
}
|
||||
@@ -44,21 +42,39 @@ const appendPublicAndTdriveToken = (useAnd?: boolean) => {
|
||||
|
||||
export class DriveApiClient {
|
||||
private static logger = Logger.getLogger('MessageAPIClientService');
|
||||
|
||||
static async getAnonymousToken(
|
||||
companyId: string,
|
||||
id: string,
|
||||
publicToken: string,
|
||||
password?: string,
|
||||
) {
|
||||
return await Api.post<
|
||||
{ company_id: string; document_id: string; token: string; token_password?: string },
|
||||
{ access_token: JWTDataType }
|
||||
>(`/internal/services/documents/v1/companies/${companyId}/anonymous/token`, {
|
||||
company_id: companyId,
|
||||
document_id: id,
|
||||
token: publicToken,
|
||||
token_password: password,
|
||||
});
|
||||
}
|
||||
|
||||
static async get(companyId: string, id: string | 'trash' | '') {
|
||||
return await Api.get<DriveItemDetails>(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}${appendPublicAndTdriveToken()}`,
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}${appendTdriveToken()}`,
|
||||
);
|
||||
}
|
||||
|
||||
static async remove(companyId: string, id: string | 'trash' | '') {
|
||||
return await Api.delete<void>(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}${appendPublicAndTdriveToken()}`,
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}${appendTdriveToken()}`,
|
||||
);
|
||||
}
|
||||
|
||||
static async update(companyId: string, id: string, update: Partial<DriveItem>) {
|
||||
return await Api.post<Partial<DriveItem>, DriveItem>(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}${appendPublicAndTdriveToken()}`,
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}${appendTdriveToken()}`,
|
||||
update,
|
||||
);
|
||||
}
|
||||
@@ -72,14 +88,14 @@ export class DriveApiClient {
|
||||
{ item: Partial<DriveItem>; version: Partial<DriveItemVersion> },
|
||||
DriveItem
|
||||
>(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item${appendPublicAndTdriveToken()}`,
|
||||
`/internal/services/documents/v1/companies/${companyId}/item${appendTdriveToken()}`,
|
||||
data as { item: Partial<DriveItem>; version: Partial<DriveItemVersion> },
|
||||
);
|
||||
}
|
||||
|
||||
static async createVersion(companyId: string, id: string, version: Partial<DriveItemVersion>) {
|
||||
return await Api.post<Partial<DriveItemVersion>, DriveItemVersion>(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}/version${appendPublicAndTdriveToken()}`,
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}/version${appendTdriveToken()}`,
|
||||
version,
|
||||
);
|
||||
}
|
||||
@@ -88,7 +104,7 @@ export class DriveApiClient {
|
||||
return Api.get<{ token: string }>(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/download/token` +
|
||||
`?items=${ids.join(',')}&version_id=${versionId}` +
|
||||
appendPublicAndTdriveToken(true),
|
||||
appendTdriveToken(true),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,12 +112,12 @@ export class DriveApiClient {
|
||||
const { token } = await DriveApiClient.getDownloadToken(companyId, [id], versionId);
|
||||
if (versionId)
|
||||
return Api.route(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}/download?version_id=${versionId}&token=${token}${appendPublicAndTdriveToken(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}/download?version_id=${versionId}&token=${token}${appendTdriveToken(
|
||||
true,
|
||||
)}`,
|
||||
);
|
||||
return Api.route(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}/download?token=${token}${appendPublicAndTdriveToken(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/${id}/download?token=${token}${appendTdriveToken(
|
||||
true,
|
||||
)}`,
|
||||
);
|
||||
@@ -112,7 +128,7 @@ export class DriveApiClient {
|
||||
return Api.route(
|
||||
`/internal/services/documents/v1/companies/${companyId}/item/download/zip` +
|
||||
`?items=${ids.join(',')}&token=${token}` +
|
||||
appendPublicAndTdriveToken(true),
|
||||
appendTdriveToken(true),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,17 +26,22 @@ import { PropertiesModal } from './modals/properties';
|
||||
import { AccessModal } from './modals/update-access';
|
||||
import { VersionsModal } from './modals/versions';
|
||||
|
||||
export const DriveCurrentFolderAtom = atomFamily<string, string>({
|
||||
export const DriveCurrentFolderAtom = atomFamily<
|
||||
string,
|
||||
{ context?: string; initialFolderId: string }
|
||||
>({
|
||||
key: 'DriveCurrentFolderAtom',
|
||||
default: startingParentId => startingParentId || 'root',
|
||||
default: options => options.initialFolderId || 'root',
|
||||
});
|
||||
|
||||
export default memo(
|
||||
({
|
||||
context,
|
||||
initialParentId,
|
||||
tdriveTabContextToken,
|
||||
inPublicSharing,
|
||||
}: {
|
||||
context?: string;
|
||||
initialParentId?: string;
|
||||
tdriveTabContextToken?: string;
|
||||
inPublicSharing?: boolean;
|
||||
@@ -45,7 +50,7 @@ export default memo(
|
||||
setTdriveTabToken(tdriveTabContextToken || null);
|
||||
|
||||
const [parentId, _setParentId] = useRecoilState(
|
||||
DriveCurrentFolderAtom(initialParentId || 'root'),
|
||||
DriveCurrentFolderAtom({ context: context, initialFolderId: initialParentId || 'root' }),
|
||||
);
|
||||
|
||||
const [loadingParentChange, setLoadingParentChange] = useState(false);
|
||||
@@ -118,7 +123,7 @@ export default memo(
|
||||
return (
|
||||
<UploadZone
|
||||
overClassName={''}
|
||||
className="h-full overflow-hidden"
|
||||
className="h-full overflow-hidden w-full relative"
|
||||
disableClick
|
||||
parent={''}
|
||||
multiple={true}
|
||||
|
||||
@@ -24,7 +24,9 @@ export const useOnBuildContextMenu = (children: DriveItem[], initialParentId?: s
|
||||
const [checkedIds, setChecked] = useRecoilState(DriveItemSelectedList);
|
||||
const checked = children.filter(c => checkedIds[c.id]);
|
||||
|
||||
const [_, setParentId] = useRecoilState(DriveCurrentFolderAtom(initialParentId || 'root'));
|
||||
const [_, setParentId] = useRecoilState(
|
||||
DriveCurrentFolderAtom({ initialFolderId: initialParentId || 'root' }),
|
||||
);
|
||||
|
||||
const { download, downloadZip, update } = useDriveActions();
|
||||
const setCreationModalState = useSetRecoilState(CreateModalAtom);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import MenusBodyLayer from '@components/menus/menus-body-layer';
|
||||
import JWTStorage from '@features/auth/jwt-storage-service';
|
||||
import Api from '@features/global/framework/api-service';
|
||||
import Languages from '@features/global/services/languages-service';
|
||||
import { addApiUrlIfNeeded } from '@features/global/utils/URLUtils';
|
||||
@@ -11,15 +12,18 @@ import { Input } from 'app/atoms/input/input-text';
|
||||
import { Base, Subtitle, Title } from 'app/atoms/text';
|
||||
import UploadsViewer from 'app/components/file-uploads/uploads-viewer';
|
||||
import { useDriveItem } from 'app/features/drive/hooks/use-drive-item';
|
||||
import { useDriveUpload } from 'app/features/drive/hooks/use-drive-upload';
|
||||
import { ToasterService } from 'app/features/global/services/toaster-service';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import shortUUID from 'short-uuid';
|
||||
import Avatar from '../../../../atoms/avatar';
|
||||
import { setPublicLinkToken } from '../../../../features/drive/api-client/api-client';
|
||||
import {
|
||||
DriveApiClient,
|
||||
setPublicLinkToken,
|
||||
} from '../../../../features/drive/api-client/api-client';
|
||||
import useRouterCompany from '../../../../features/router/hooks/use-router-company';
|
||||
import { CreateModalAtom } from './modals/create';
|
||||
import { CreateModalWithUploadZones } from '../../side-bar/actions';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { DriveCurrentFolderAtom } from './browser';
|
||||
|
||||
export default () => {
|
||||
const companyId = useRouterCompany();
|
||||
@@ -44,7 +48,6 @@ export default () => {
|
||||
|
||||
const { token, documentId: _documentId } = useParams() as { token?: string; documentId?: string };
|
||||
const documentId = _documentId ? shortUUID().toUUID(_documentId || '') : '';
|
||||
setPublicLinkToken(token || null);
|
||||
|
||||
if (!companyId) {
|
||||
return <></>;
|
||||
@@ -77,7 +80,7 @@ export default () => {
|
||||
</div>
|
||||
<MenusBodyLayer />
|
||||
<UploadsViewer />
|
||||
<CreateModalWithUploadZones />
|
||||
<CreateModalWithUploadZones initialParentId={documentId} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -92,10 +95,36 @@ const AccessChecker = ({
|
||||
folderId: string;
|
||||
}) => {
|
||||
const { details, loading, refresh } = useDriveItem(folderId);
|
||||
const companyId = useRouterCompany();
|
||||
const [password, setPassword] = useState((token || '').split('+')[1] || '');
|
||||
|
||||
const setPublicToken = async (token: string, password?: string) => {
|
||||
try {
|
||||
setPublicLinkToken(token || null);
|
||||
|
||||
const { access_token } = await DriveApiClient.getAnonymousToken(
|
||||
companyId,
|
||||
folderId,
|
||||
token,
|
||||
password,
|
||||
);
|
||||
|
||||
if (!access_token) {
|
||||
throw new Error('Invalid password or token, or expired link.');
|
||||
}
|
||||
|
||||
JWTStorage.updateJWT(access_token);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ToasterService.error('Unable to access documents: ' + e);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
refresh(folderId);
|
||||
(async () => {
|
||||
await setPublicToken(token || '');
|
||||
refresh(folderId);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
if (!details?.item?.id && loading) {
|
||||
@@ -125,8 +154,8 @@ const AccessChecker = ({
|
||||
<Button
|
||||
className="rounded-l-none"
|
||||
theme="primary"
|
||||
onClick={() => {
|
||||
setPublicLinkToken(token ? encodeURIComponent(token + '+' + password) : null);
|
||||
onClick={async () => {
|
||||
await setPublicToken(token || '', password);
|
||||
refresh(folderId);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -12,13 +12,17 @@ import { ConfirmDeleteModalAtom } from '../body/drive/modals/confirm-delete';
|
||||
import { CreateModal, CreateModalAtom } from '../body/drive/modals/create';
|
||||
import { Button } from '@atoms/button/button';
|
||||
|
||||
export const CreateModalWithUploadZones = () => {
|
||||
export const CreateModalWithUploadZones = ({ initialParentId }: { initialParentId?: string }) => {
|
||||
const companyId = useRouterCompany();
|
||||
const uploadZoneRef = useRef<UploadZone | null>(null);
|
||||
const uploadFolderZoneRef = useRef<UploadZone | null>(null);
|
||||
const setCreationModalState = useSetRecoilState(CreateModalAtom);
|
||||
const { uploadTree, uploadFromUrl } = useDriveUpload();
|
||||
const [parentId, _] = useRecoilState(DriveCurrentFolderAtom('root'));
|
||||
const [parentId, _] = useRecoilState(
|
||||
DriveCurrentFolderAtom({ initialFolderId: initialParentId || 'root' }),
|
||||
);
|
||||
|
||||
console.log(parentId);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -73,7 +77,7 @@ export const CreateModalWithUploadZones = () => {
|
||||
};
|
||||
|
||||
export default () => {
|
||||
const [parentId, _] = useRecoilState(DriveCurrentFolderAtom('root'));
|
||||
const [parentId, _] = useRecoilState(DriveCurrentFolderAtom({ initialFolderId: 'root' }));
|
||||
const { access, item, inTrash } = useDriveItem(parentId);
|
||||
const { children: trashChildren } = useDriveItem('trash');
|
||||
const uploadZoneRef = useRef<UploadZone | null>(null);
|
||||
@@ -89,7 +93,7 @@ export default () => {
|
||||
<div className="-m-4 overflow-hidden">
|
||||
<AnimatedHeight>
|
||||
<div className="p-4">
|
||||
<CreateModalWithUploadZones />
|
||||
<CreateModalWithUploadZones initialParentId={parentId} />
|
||||
|
||||
{inTrash && access === 'manage' && (
|
||||
<>
|
||||
|
||||
@@ -19,7 +19,9 @@ import DiskUsage from '../common/disk-usage';
|
||||
import Actions from './actions';
|
||||
|
||||
export default () => {
|
||||
const [parentId, setParentId] = useRecoilState(DriveCurrentFolderAtom('root'));
|
||||
const [parentId, setParentId] = useRecoilState(
|
||||
DriveCurrentFolderAtom({ initialFolderId: 'root' }),
|
||||
);
|
||||
const { user } = useCurrentUser();
|
||||
const active = false;
|
||||
const { access: rootAccess } = useDriveItem('root');
|
||||
|
||||
Reference in New Issue
Block a user