mirror of
https://github.com/strapi/strapi.git
synced 2025-07-24 17:40:18 +00:00
Add tests and comments and PR co-author credit
Co-Authored-By: Anton Mikaskin <garrakombo@gmail.com> Co-Authored-By: vnguyen42
This commit is contained in:
parent
d6965e562c
commit
d11699c79b
@ -2,9 +2,10 @@ import { Readable } from 'stream';
|
||||
import type { ILocalFileSourceProviderOptions } from '..';
|
||||
|
||||
import { createLocalFileSourceProvider } from '..';
|
||||
import { isFilePathInDirname, isPathEquivalent, unknownPathToPosix } from '../utils';
|
||||
|
||||
describe('Stream assets', () => {
|
||||
test('returns a stream', () => {
|
||||
describe('File source provider', () => {
|
||||
test('returns assets stream', () => {
|
||||
const options: ILocalFileSourceProviderOptions = {
|
||||
file: {
|
||||
path: './test-file',
|
||||
@ -21,4 +22,108 @@ describe('Stream assets', () => {
|
||||
|
||||
expect(stream instanceof Readable).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('utils', () => {
|
||||
const unknownConversionCases = [
|
||||
['some/path/on/posix', 'some/path/on/posix'],
|
||||
['some/path/on/posix/', 'some/path/on/posix/'],
|
||||
['some/path/on/posix.jpg', 'some/path/on/posix.jpg'],
|
||||
['file.jpg', 'file.jpg'],
|
||||
['noextension', 'noextension'],
|
||||
['some\\windows\\filename.jpg', 'some/windows/filename.jpg'],
|
||||
['some\\windows\\noendingslash', 'some/windows/noendingslash'],
|
||||
['some\\windows\\endingslash\\', 'some/windows/endingslash/'],
|
||||
];
|
||||
test.each(unknownConversionCases)('unknownPathToPosix: %p -> %p', (input, expected) => {
|
||||
expect(unknownPathToPosix(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
const isFilePathInDirnameCases: [string, string, boolean][] = [
|
||||
// posix paths
|
||||
['some/path/on/posix', 'some/path/on/posix/file.jpg', true],
|
||||
['some/path/on/posix/', 'some/path/on/posix/file.jpg', true],
|
||||
['./some/path/on/posix', 'some/path/on/posix/file.jpg', true],
|
||||
['some/path/on/posix/', './some/path/on/posix/file.jpg', true],
|
||||
['some/path/on/posix/', 'some/path/on/posix/', false], // invalid; second method should include a filename
|
||||
['some/path/on/posix', 'some/path/on/posix', false], // 'posix' in second case should be interpreted as a filename
|
||||
['', 'file.jpg', true],
|
||||
['', './file.jpg', true],
|
||||
['./', './file.jpg', true],
|
||||
['noextension', 'noextension', false], // second case is a file
|
||||
['noextension', './noextension/file.jpg', true],
|
||||
['./noextension', './noextension/file.jpg', true],
|
||||
['./noextension', 'noextension/file.jpg', true],
|
||||
['noextension', 'noextension/noextension', true],
|
||||
// win32 paths
|
||||
['some/path/on/win32', 'some\\path\\on\\win32\\file.jpg', true],
|
||||
['some/path/on/win32/', 'some\\path\\on\\win32\\file.jpg', true],
|
||||
['some/path/on/win32/', 'some\\path\\on\\win32\\', false], // invalid; second method should include a filename
|
||||
['some/path/on/win32', 'some\\path\\on\\win32', false], // 'win32' in second case should be interpreted as a filename
|
||||
['', 'file.jpg', true],
|
||||
['', '.\\file.jpg', true],
|
||||
['./', '.\\file.jpg', true],
|
||||
['noextension', 'noextension', false], // second case is a file
|
||||
['noextension', '.\\noextension\\file.jpg', true],
|
||||
['./noextension', '.\\noextension\\file.jpg', true],
|
||||
['./noextension', 'noextension\\file.jpg', true],
|
||||
['noextension', 'noextension\\noextension', true],
|
||||
];
|
||||
test.each(isFilePathInDirnameCases)(
|
||||
'isFilePathInDirname: %p : %p -> %p',
|
||||
(inputA, inputB, expected) => {
|
||||
expect(isFilePathInDirname(inputA, inputB)).toEqual(expected);
|
||||
}
|
||||
);
|
||||
|
||||
const isPathEquivalentCases: [string, string, boolean][] = [
|
||||
// POSITIVES
|
||||
// root level
|
||||
['file.jpg', 'file.jpg', true],
|
||||
['file.jpg', '.\\file.jpg', true],
|
||||
['file.jpg', './file.jpg', true],
|
||||
// cwd root level (posix)
|
||||
['./file.jpg', 'file.jpg', true],
|
||||
['./file.jpg', './file.jpg', true],
|
||||
['./file.jpg', '.\\file.jpg', true],
|
||||
// cwd root level (win32)
|
||||
['.\\file.jpg', 'file.jpg', true],
|
||||
['.\\file.jpg', './file.jpg', true],
|
||||
['.\\file.jpg', '.\\file.jpg', true],
|
||||
// directory with file (posix)
|
||||
['one/two/file.jpg', 'one/two/file.jpg', true],
|
||||
['one/two/file.jpg', './one/two/file.jpg', true],
|
||||
['one/two/file.jpg', 'one\\two\\file.jpg', true],
|
||||
['one/two/file.jpg', '.\\one\\two\\file.jpg', true],
|
||||
// cwd with file (posix)
|
||||
['./one/two/file.jpg', 'one/two/file.jpg', true],
|
||||
['./one/two/file.jpg', './one/two/file.jpg', true],
|
||||
['./one/two/file.jpg', 'one\\two\\file.jpg', true],
|
||||
['./one/two/file.jpg', '.\\one\\two\\file.jpg', true],
|
||||
// directory with file (win32)
|
||||
['one\\two\\file.jpg', 'one/two/file.jpg', true],
|
||||
['one\\two\\file.jpg', './one/two/file.jpg', true],
|
||||
['one\\two\\file.jpg', '.\\one\\two\\file.jpg', true],
|
||||
['one\\two\\file.jpg', 'one\\two\\file.jpg', true],
|
||||
// cwd with file (win32)
|
||||
['.\\one\\two\\file.jpg', 'one/two/file.jpg', true],
|
||||
['.\\one\\two\\file.jpg', './one/two/file.jpg', true],
|
||||
['.\\one\\two\\file.jpg', '.\\one\\two\\file.jpg', true],
|
||||
['.\\one\\two\\file.jpg', 'one\\two\\file.jpg', true],
|
||||
|
||||
// NEGATIVES
|
||||
['file.jpg', 'one/file.jpg', false],
|
||||
['file.jpg', 'one\\file.jpg', false],
|
||||
['file.jpg', '/file.jpg', false],
|
||||
['file.jpg', '\\file.jpg', false],
|
||||
['one/file.jpg', '\\one\\file.jpg', false],
|
||||
['one/file.jpg', '/one/file.jpg', false],
|
||||
['one/file.jpg', 'file.jpg', false],
|
||||
];
|
||||
test.each(isPathEquivalentCases)(
|
||||
'isPathEquivalent: %p : %p -> %p',
|
||||
(inputA, inputB, expected) => {
|
||||
expect(isPathEquivalent(inputA, inputB)).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ import type { IAsset, IMetadata, ISourceProvider, ProviderType } from '../../../
|
||||
import { createDecryptionCipher } from '../../../utils/encryption';
|
||||
import { collect } from '../../../utils/stream';
|
||||
import { ProviderInitializationError, ProviderTransferError } from '../../../errors/providers';
|
||||
import { isDirPathEquivalent, isPathEquivalent, unknownPathToPosix } from './utils';
|
||||
import { isFilePathInDirname, isPathEquivalent, unknownPathToPosix } from './utils';
|
||||
|
||||
type StreamItemArray = Parameters<typeof chain>[0];
|
||||
|
||||
@ -143,7 +143,7 @@ class LocalFileSourceProvider implements ISourceProvider {
|
||||
if (entry.type !== 'File') {
|
||||
return false;
|
||||
}
|
||||
return isDirPathEquivalent('assets/uploads', filePath);
|
||||
return isFilePathInDirname('assets/uploads', filePath);
|
||||
},
|
||||
onentry(entry) {
|
||||
// TODO: Check if we need to handle win32 paths here for the assets
|
||||
@ -203,7 +203,7 @@ class LocalFileSourceProvider implements ISourceProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isDirPathEquivalent(directory, filePath);
|
||||
return isFilePathInDirname(directory, filePath);
|
||||
},
|
||||
|
||||
async onentry(entry) {
|
||||
|
@ -12,23 +12,37 @@ import path from 'path';
|
||||
*
|
||||
* */
|
||||
|
||||
// Check if the directory of a given filePath (which can be either posix or win32) resolves to the same as the given posix-format path posixDirName
|
||||
// We must be able to assume the first argument is a path, otherwise path.dirname will interpret a path without any slashes as the filename
|
||||
export const isDirPathEquivalent = (posixDirName: string, filePath: string) => {
|
||||
/**
|
||||
* Check if the directory of a given filePath (which can be either posix or win32) resolves to the same as the given posix-format path posixDirName
|
||||
* We must be able to assume the first argument is a path to a directory and the second is a path to a file, otherwise path.dirname will interpret a path without any slashes as the filename
|
||||
*
|
||||
* @param {string} posixDirName A posix path pointing to a directory
|
||||
* @param {string} filePath an unknown filesystem path pointing to a file
|
||||
* @returns {boolean} is the file located in the given directory
|
||||
*/
|
||||
export const isFilePathInDirname = (posixDirName: string, filePath: string) => {
|
||||
const normalizedDir = path.posix.dirname(unknownPathToPosix(filePath));
|
||||
return isPathEquivalent(posixDirName, normalizedDir);
|
||||
};
|
||||
|
||||
// Check if two paths that can be either in posix or win32 format resolves to the same file
|
||||
export const isPathEquivalent = (fileA: string, fileB: string) => {
|
||||
/**
|
||||
* Check if two paths that can be either in posix or win32 format resolves to the same file
|
||||
*
|
||||
* @param {string} pathA a path that may be either win32 or posix
|
||||
* @param {string} pathB a path that may be either win32 or posix
|
||||
*
|
||||
* @returns {boolean} do paths point to the same place
|
||||
*/
|
||||
export const isPathEquivalent = (pathA: string, pathB: string) => {
|
||||
// Check if paths appear to be win32 or posix, and if win32 convert to posix
|
||||
const normalizedPathA = unknownPathToPosix(fileA);
|
||||
const normalizedPathB = unknownPathToPosix(fileB);
|
||||
const normalizedPathA = path.posix.normalize(unknownPathToPosix(pathA));
|
||||
const normalizedPathB = path.posix.normalize(unknownPathToPosix(pathB));
|
||||
|
||||
return !path.posix.relative(normalizedPathB, normalizedPathA).length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert an unknown format path (win32 or posix) to a posix path
|
||||
*
|
||||
* @param {string} filePath a path that may be either win32 or posix
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user