Compare commits
2 commits
0962c2cc1f
...
52ace91580
| Author | SHA1 | Date | |
|---|---|---|---|
| 52ace91580 | |||
| 9758fe75f9 |
5 changed files with 23 additions and 6 deletions
|
|
@ -15,7 +15,8 @@
|
|||
"label": "Vidéos",
|
||||
"dir": "./uploads/videos",
|
||||
"allowDirectories": true,
|
||||
"allowedMimeTypes": ["video/*"]
|
||||
"allowedMimeTypes": ["video/*"],
|
||||
"permissions": "0666"
|
||||
},
|
||||
{ "name": "divers", "label": "Divers", "dir": "./uploads/divers" }
|
||||
],
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"permissions":{
|
||||
"type":"string",
|
||||
"default":"0666",
|
||||
"description": "Mode d'écriture sur le disque"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ export interface DropTarget {
|
|||
* valeur globale `allowedMimeTypes`. Toujours résolu après parsing.
|
||||
*/
|
||||
allowedMimeTypes: MimePolicy;
|
||||
|
||||
/**
|
||||
* Mode de permission d'écriture
|
||||
* Par défaut 0o666
|
||||
*/
|
||||
permission: number;
|
||||
}
|
||||
|
||||
/** Liste non vide de cibles de dépôt ; la première est la cible par défaut. */
|
||||
|
|
@ -204,7 +210,7 @@ function parseMimePolicy(value: unknown, label = 'allowedMimeTypes'): MimePolicy
|
|||
if (!valid) {
|
||||
throw new ConfigError(
|
||||
`${label} : entrée invalide « ${entry} » ` +
|
||||
'(formes acceptées : "type/sous-type", "type/*", "*/*", "*")',
|
||||
'(formes acceptées : "type/sous-type", "type/*", "*/*", "*")',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -231,7 +237,7 @@ function parseSessionKey(value: unknown): Buffer {
|
|||
if (key.length !== SESSION_KEY_BYTES) {
|
||||
throw new ConfigError(
|
||||
`session.key doit être ${String(SESSION_KEY_BYTES)} octets encodés en base64 ` +
|
||||
`(décodé : ${String(key.length)} octets). Générer avec : openssl rand -base64 32`,
|
||||
`(décodé : ${String(key.length)} octets). Générer avec : openssl rand -base64 32`,
|
||||
);
|
||||
}
|
||||
return key;
|
||||
|
|
@ -257,7 +263,7 @@ function parseSession(value: unknown): SessionConfig {
|
|||
key: parseSessionKey(raw.key),
|
||||
maxAgeSeconds: Math.round(
|
||||
optionalPositiveNumber(raw.maxAgeHours, DEFAULTS.sessionMaxAgeHours, 'session.maxAgeHours') *
|
||||
3600,
|
||||
3600,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
|
@ -386,6 +392,7 @@ function parseTargets(value: unknown, defaultMimePolicy: MimePolicy): DropTarget
|
|||
raw.allowedMimeTypes === undefined || raw.allowedMimeTypes === null
|
||||
? defaultMimePolicy
|
||||
: parseMimePolicy(raw.allowedMimeTypes, `targets[${String(index)}].allowedMimeTypes`),
|
||||
permission: parseInt(optionalString(raw.label, `targets[${String(index)}].permission`) ?? "0666",8)
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,15 @@ export interface SaveFileParams {
|
|||
/** Dossier de destination (résolu depuis la cible de dépôt choisie). */
|
||||
targetDir: string;
|
||||
maxFileSizeBytes: number;
|
||||
/** Permission d'écriture */
|
||||
permission:number;
|
||||
/**
|
||||
* Mode dossier : recrée `segments` sous `targetDir` et conserve `fileName` ;
|
||||
* un fichier existant au même chemin est écrasé. Absent -> nom dérivé unique
|
||||
* à la racine de `targetDir`.
|
||||
*/
|
||||
placement?: FilePlacement;
|
||||
|
||||
}
|
||||
|
||||
const MAX_BASE_LENGTH = 60;
|
||||
|
|
@ -143,7 +146,7 @@ export async function resolveDestination(input: DestinationInput): Promise<Resol
|
|||
* le fichier partiel est supprimé et `PayloadTooLargeError` est levée.
|
||||
*/
|
||||
export async function saveFile(params: SaveFileParams): Promise<StoredFile> {
|
||||
const { source, originalName, mimeType, maxFileSizeBytes } = params;
|
||||
const { source, originalName, mimeType, maxFileSizeBytes,permission } = params;
|
||||
const { storedName, destination } = await resolveDestination(params);
|
||||
|
||||
let bytesWritten = 0;
|
||||
|
|
@ -162,7 +165,7 @@ export async function saveFile(params: SaveFileParams): Promise<StoredFile> {
|
|||
await pipeline(
|
||||
source,
|
||||
limiter,
|
||||
createWriteStream(destination, { highWaterMark: WRITE_HIGH_WATER_MARK }),
|
||||
createWriteStream(destination, { highWaterMark: WRITE_HIGH_WATER_MARK ,mode:permission}),
|
||||
);
|
||||
} catch (error) {
|
||||
await rm(destination, { force: true });
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ export const uploadRoutes: FastifyPluginCallback = (app, _options, done) => {
|
|||
targetDir: target.dir,
|
||||
maxFileSizeBytes: app.appConfig.maxFileSizeBytes,
|
||||
...(placement !== undefined ? { placement } : {}),
|
||||
permission:target.permission
|
||||
});
|
||||
|
||||
app.notifier.uploadCompleted({
|
||||
|
|
|
|||
Loading…
Reference in a new issue