Skip to content

Commit

Permalink
added PUT webdav handler
Browse files Browse the repository at this point in the history
  • Loading branch information
larryrider committed Mar 20, 2024
1 parent cd9c25a commit c3abc02
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/webdav/handlers/PUT.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Request, Response } from 'express';
import path from 'path';
import { DriveFileService } from '../../services/drive/drive-file.service';
import { DriveRealmManager } from '../../services/realms/drive-realm-manager.service';
import { NetworkFacade } from '../../services/network/network-facade.service';
import { UploadService } from '../../services/network/upload.service';
import { DownloadService } from '../../services/network/download.service';
import { CryptoService } from '../../services/crypto.service';
import { AuthService } from '../../services/auth.service';
import { DriveFolderRealmSchema } from '../../services/realms/drive-folders.realm';
import { WebDavMethodHandler, WebDavRequestedResource } from '../../types/webdav.types';
import { NotFoundError, UnsupportedMediaTypeError } from '../../utils/errors.utils';
import { StreamUtils } from '../../utils/stream.utils';
import { WebDavUtils } from '../../utils/webdav.utils';

export class PUTRequestHandler implements WebDavMethodHandler {
constructor(
private dependencies: {
driveFileService: DriveFileService;
driveRealmManager: DriveRealmManager;
uploadService: UploadService;
downloadService: DownloadService;
cryptoService: CryptoService;
authService: AuthService;
networkFacade: NetworkFacade;
},
) {}

handle = async (req: Request, res: Response) => {
const contentLength = req.header('content-length') ? Number(req.header('content-length')) : undefined;
if (!contentLength || isNaN(contentLength) || contentLength <= 0) {
throw new UnsupportedMediaTypeError('Empty files are not supported');
}

const resource = WebDavUtils.getRequestedResource(req, this.dependencies.driveRealmManager);
const driveFolder = await this.getDriveFolderRealmObject(resource);

if (resource.type === 'file' || !driveFolder) {
//TODO maybe we should call/make the 'propfind' logic here if destination folder has not been found on realm database
throw new NotFoundError('Drive destination folder not found');
}

const { user, mnemonic } = await this.dependencies.authService.getAuthDetails();

const [uploadPromise] = await this.dependencies.networkFacade.uploadFromStream(
user.bucket,
mnemonic,
contentLength,
StreamUtils.requestToReadableStream(req),
);

const uploadResult = await uploadPromise;

const fileInfo = path.parse(decodeURI(req.url));

await DriveFileService.instance.createFile({
name: fileInfo.name,
type: fileInfo.ext.replaceAll('.', ''),
size: contentLength,
folderId: driveFolder.id,
fileId: uploadResult.fileId,
bucket: user.bucket,
});

res.status(200);
res.send();
};

private async getDriveFolderRealmObject(resource: WebDavRequestedResource) {
const { driveRealmManager } = this.dependencies;
const result = driveRealmManager.findByRelativePath(resource.path.dir);
return result as DriveFolderRealmSchema | null;
}
}
15 changes: 15 additions & 0 deletions src/webdav/webdav-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import asyncHandler from 'express-async-handler';
import { SdkManager } from '../services/sdk-manager.service';
import { NetworkFacade } from '../services/network/network-facade.service';
import { NetworkUtils } from '../utils/network.utils';
import { PUTRequestHandler } from './handlers/PUT.handler';

export class WebDavServer {
constructor(
Expand Down Expand Up @@ -85,6 +86,20 @@ export class WebDavServer {
).handle,
),
);
this.app.put(
'*',
asyncHandler(
new PUTRequestHandler({
driveFileService: this.driveFileService,
driveRealmManager: this.driveRealmManager,
uploadService: this.uploadService,
downloadService: this.downloadService,
cryptoService: this.cryptoService,
authService: this.authService,
networkFacade: await this.getNetwork(),
}).handle,
),
);
};

async start() {
Expand Down

0 comments on commit c3abc02

Please sign in to comment.