mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
Stalwart 1.0 checks names more strictly than its capability says: a reserved name may not be the stem either (`con.txt`, `Aux.tar.gz`), and control characters are refused (macOS `Icon\r`). Names over 255 bytes of UTF-8 were never accepted. Uploaded names are now made acceptable before they are sent: control characters become "_", a reserved stem gets "_" after it (`con.txt` becomes `con_.txt`), and a long name is shortened, keeping its extension. The rename and new-folder dialogs refuse such names with their own messages. The rules apply wherever the server publishes naming rules, so 0.16.6 to 0.16.23 get `con_.txt` too. One refused file used to abort a whole upload. Uploads now go on and report the files that failed at the end, and a folder upload skips the contents of a folder it could not create instead of dropping them into the folder the upload started in. What would sit deeper than 1.0's `maxFileNodeDepth` (64) is left out before it is uploaded, and a folder copy that would go past it fails before the first create. File errors keep their JMAP type, and the Files toasts now say why an action failed: too many files or folders (`overQuota`), folders nested too deeply, a refused name, missing rights, or a file too large. New and copied files get a bare lowercase media type, which 1.0 requires.
43 lines
2.6 KiB
TypeScript
43 lines
2.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { fileErrorKind, folderDepthError } from '../file-errors';
|
|
import { jmapError } from '../jmap/jmap-error';
|
|
|
|
// SetErrors as Stalwart words them (1.0: jmap/src/file/*.rs; 0.16.23:
|
|
// jmap/src/file/set.rs), thrown by the JMAP client through jmapError.
|
|
const setError = (type: string, description: string, properties?: string[]) =>
|
|
jmapError(description, { type, description, properties });
|
|
|
|
describe('fileErrorKind', () => {
|
|
it('explains Stalwart 1.0\'s limits on files and folders', () => {
|
|
expect(fileErrorKind(setError('overQuota', 'There are too many files, please delete some before adding a new one.'))).toBe('overQuota');
|
|
expect(fileErrorKind(setError('overQuota', 'There are too many folders, please delete some before adding a new one.'))).toBe('overQuota');
|
|
expect(fileErrorKind(setError('invalidProperties', 'Maximum folder depth exceeded.', ['parentId']))).toBe('tooDeep');
|
|
expect(fileErrorKind(setError('tooLarge', 'File is too large.'))).toBe('tooLarge');
|
|
});
|
|
|
|
it('treats Bulwark\'s own depth check like the server\'s', () => {
|
|
expect(fileErrorKind(folderDepthError())).toBe('tooDeep');
|
|
});
|
|
|
|
it('explains refused names on 0.16 and 1.0', () => {
|
|
expect(fileErrorKind(setError('invalidProperties', 'Name is reserved and cannot be used.', ['name']))).toBe('invalidName');
|
|
expect(fileErrorKind(setError('invalidProperties', 'Name contains a forbidden character.', ['name']))).toBe('invalidName');
|
|
expect(fileErrorKind(setError('invalidProperties', 'Name must be between 1 and 255 octets.', ['name']))).toBe('invalidName');
|
|
});
|
|
|
|
it('explains missing rights on 0.16 and 1.0', () => {
|
|
expect(fileErrorKind(setError('forbidden', 'You are not allowed to create file nodes in this folder.'))).toBe('forbidden');
|
|
expect(fileErrorKind(setError('forbidden', 'You do not have access to blobId b2.'))).toBe('forbidden');
|
|
expect(fileErrorKind(setError('forbidden', 'You are not allowed to modify this file node.'))).toBe('forbidden');
|
|
});
|
|
|
|
it('has nothing to add for other errors', () => {
|
|
// The folder is gone, or a folder was moved into itself.
|
|
expect(fileErrorKind(setError('invalidProperties', 'Parent ID does not exist or is not a folder.', ['parentId']))).toBeNull();
|
|
expect(fileErrorKind(setError('invalidProperties', 'Circular reference in parent ids.', ['parentId']))).toBeNull();
|
|
expect(fileErrorKind(setError('notFound', 'Not found'))).toBeNull();
|
|
expect(fileErrorKind(new Error('Failed to upload file: 500'))).toBeNull();
|
|
expect(fileErrorKind(undefined)).toBeNull();
|
|
});
|
|
});
|