fix: improve error message for folders

This commit is contained in:
tdurieux
2023-05-08 15:16:56 +02:00
parent 4f6c1d25fc
commit 027f14ffbc
6 changed files with 56 additions and 26 deletions
+9 -3
View File
@@ -2,7 +2,7 @@ import { join, basename } from "path";
import { Response } from "express"; import { Response } from "express";
import { Readable } from "stream"; import { Readable } from "stream";
import Repository from "./Repository"; import Repository from "./Repository";
import { Tree, TreeElement, TreeFile } from "./types"; import { FILE_TYPE, Tree, TreeElement, TreeFile } from "./types";
import storage from "./storage"; import storage from "./storage";
import config from "../config"; import config from "../config";
import { import {
@@ -175,8 +175,14 @@ export default class AnonymizedFile {
httpStatus: 403, httpStatus: 403,
}); });
} }
if (await storage.exists(this.originalCachePath)) { const exist = await storage.exists(this.originalCachePath);
if (exist == FILE_TYPE.FILE) {
return storage.read(this.originalCachePath); return storage.read(this.originalCachePath);
} else if (exist == FILE_TYPE.FOLDER) {
throw new AnonymousError("folder_not_supported", {
object: this,
httpStatus: 400,
});
} }
return await this.repository.source?.getFileContent(this); return await this.repository.source?.getFileContent(this);
} }
@@ -223,7 +229,7 @@ export default class AnonymizedFile {
// unable to get file size // unable to get file size
console.error(error); console.error(error);
} }
const anonymizer = new AnonymizeTransformer(this); const anonymizer = new AnonymizeTransformer(this);
anonymizer.once("transform", (data) => { anonymizer.once("transform", (data) => {
+11 -2
View File
@@ -1,6 +1,13 @@
import { join } from "path"; import { join } from "path";
import storage from "./storage"; import storage from "./storage";
import { RepositoryStatus, Source, Tree, TreeElement, TreeFile } from "./types"; import {
FILE_TYPE,
RepositoryStatus,
Source,
Tree,
TreeElement,
TreeFile,
} from "./types";
import { Readable } from "stream"; import { Readable } from "stream";
import User from "./User"; import User from "./User";
import GitHubStream from "./source/GitHubStream"; import GitHubStream from "./source/GitHubStream";
@@ -333,7 +340,9 @@ export default class Repository {
async removeCache() { async removeCache() {
this.model.isReseted = true; this.model.isReseted = true;
await this.model.save(); await this.model.save();
if (await storage.exists(this._model.repoId + "/")) { if (
(await storage.exists(this._model.repoId + "/")) !== FILE_TYPE.NOT_FOUND
) {
return storage.rm(this._model.repoId + "/"); return storage.rm(this._model.repoId + "/");
} }
} }
+9 -3
View File
@@ -8,7 +8,7 @@ import storage from "../storage";
import Repository from "../Repository"; import Repository from "../Repository";
import GitHubBase from "./GitHubBase"; import GitHubBase from "./GitHubBase";
import AnonymizedFile from "../AnonymizedFile"; import AnonymizedFile from "../AnonymizedFile";
import { RepositoryStatus, SourceBase } from "../types"; import { FILE_TYPE, RepositoryStatus, SourceBase } from "../types";
import AnonymousError from "../AnonymousError"; import AnonymousError from "../AnonymousError";
import { tryCatch } from "bullmq"; import { tryCatch } from "bullmq";
@@ -132,8 +132,14 @@ export default class GitHubDownload extends GitHubBase implements SourceBase {
} }
async getFileContent(file: AnonymizedFile): Promise<Readable> { async getFileContent(file: AnonymizedFile): Promise<Readable> {
if (await storage.exists(file.originalCachePath)) { const exists = await storage.exists(file.originalCachePath);
if (exists === FILE_TYPE.FILE) {
return storage.read(file.originalCachePath); return storage.read(file.originalCachePath);
} else if (exists === FILE_TYPE.FOLDER) {
throw new AnonymousError("folder_not_supported", {
httpStatus: 400,
object: file,
});
} }
// will throw an error if the file is not in the repository // will throw an error if the file is not in the repository
await file.originalPath(); await file.originalPath();
@@ -145,7 +151,7 @@ export default class GitHubDownload extends GitHubBase implements SourceBase {
async getFiles() { async getFiles() {
const folder = this.repository.originalCachePath; const folder = this.repository.originalCachePath;
if (!(await storage.exists(folder))) { if ((await storage.exists(folder)) === FILE_TYPE.NOT_FOUND) {
await this.download(); await this.download();
} }
return storage.listFiles(folder); return storage.listFiles(folder);
+12 -9
View File
@@ -1,4 +1,4 @@
import { SourceBase, StorageBase, Tree } from "../types"; import { FILE_TYPE, SourceBase, StorageBase, Tree } from "../types";
import config from "../../config"; import config from "../../config";
import * as fs from "fs"; import * as fs from "fs";
@@ -17,8 +17,15 @@ export default class FileSystem implements StorageBase {
constructor() {} constructor() {}
/** @override */ /** @override */
async exists(p: string): Promise<boolean> { async exists(p: string): Promise<FILE_TYPE> {
return fs.existsSync(join(config.FOLDER, p)); try {
const stat = await fs.promises.stat(join(config.FOLDER, p));
if (stat.isDirectory()) return FILE_TYPE.FOLDER;
if (stat.isFile()) return FILE_TYPE.FILE;
} catch (_) {
// ignore file not found or not downloaded
}
return FILE_TYPE.NOT_FOUND;
} }
/** @override */ /** @override */
@@ -49,11 +56,7 @@ export default class FileSystem implements StorageBase {
file?: AnonymizedFile, file?: AnonymizedFile,
source?: SourceBase source?: SourceBase
): Promise<void> { ): Promise<void> {
if (!(await this.exists(dirname(p)))) { await this.mk(dirname(p));
await fs.promises.mkdir(dirname(join(config.FOLDER, p)), {
recursive: true,
});
}
return fs.promises.writeFile(join(config.FOLDER, p), data); return fs.promises.writeFile(join(config.FOLDER, p), data);
} }
@@ -67,7 +70,7 @@ export default class FileSystem implements StorageBase {
/** @override */ /** @override */
async mk(dir: string): Promise<void> { async mk(dir: string): Promise<void> {
if (!(await this.exists(dir))) if ((await this.exists(dir)) === FILE_TYPE.NOT_FOUND)
fs.promises.mkdir(join(config.FOLDER, dir), { recursive: true }); fs.promises.mkdir(join(config.FOLDER, dir), { recursive: true });
} }
+8 -8
View File
@@ -1,4 +1,4 @@
import { SourceBase, StorageBase, Tree, TreeFile } from "../types"; import { FILE_TYPE, SourceBase, StorageBase, Tree, TreeFile } from "../types";
import { import {
GetObjectCommand, GetObjectCommand,
ListObjectsV2CommandOutput, ListObjectsV2CommandOutput,
@@ -44,14 +44,12 @@ export default class S3Storage implements StorageBase {
} }
/** @override */ /** @override */
async exists(path: string): Promise<boolean> { async exists(path: string): Promise<FILE_TYPE> {
if (!config.S3_BUCKET) throw new Error("S3_BUCKET not set"); if (!config.S3_BUCKET) throw new Error("S3_BUCKET not set");
try { try {
await this.client().headObject({ // if we can get the file info, it is a file
Bucket: config.S3_BUCKET, await this.fileInfo(path);
Key: path, return FILE_TYPE.FILE;
});
return true;
} catch (err) { } catch (err) {
// check if it is a directory // check if it is a directory
const data = await this.client().listObjectsV2({ const data = await this.client().listObjectsV2({
@@ -59,7 +57,9 @@ export default class S3Storage implements StorageBase {
Prefix: path, Prefix: path,
MaxKeys: 1, MaxKeys: 1,
}); });
return (data.Contents?.length || 0) > 0; return (data.Contents?.length || 0) > 0
? FILE_TYPE.FOLDER
: FILE_TYPE.NOT_FOUND;
} }
} }
+7 -1
View File
@@ -32,6 +32,12 @@ export interface SourceBase {
export type Source = GitHubDownload | GitHubStream | Zip; export type Source = GitHubDownload | GitHubStream | Zip;
export enum FILE_TYPE {
FILE = "file",
FOLDER = "folder",
NOT_FOUND = "not_found",
}
export interface StorageBase { export interface StorageBase {
/** /**
* The type of storage * The type of storage
@@ -42,7 +48,7 @@ export interface StorageBase {
* check if the path exists * check if the path exists
* @param path the path to check * @param path the path to check
*/ */
exists(path: string): Promise<boolean>; exists(path: string): Promise<FILE_TYPE>;
send(p: string, res: Response): Promise<void>; send(p: string, res: Response): Promise<void>;