Added support for FTP uploads
This commit is contained in:
parent
b7dca38786
commit
609bbe5866
|
@ -12,3 +12,11 @@ STRAPI_TOKEN=strapisecreta5e6ea45ef4e66eaa151612bdcb599df
|
||||||
SEEDING_ADMIN_USERNAME=admin_name
|
SEEDING_ADMIN_USERNAME=admin_name
|
||||||
SEEDING_ADMIN_EMAIL=email@domain.com
|
SEEDING_ADMIN_EMAIL=email@domain.com
|
||||||
SEEDING_ADMIN_PASSWORD=somepassword
|
SEEDING_ADMIN_PASSWORD=somepassword
|
||||||
|
|
||||||
|
WEB_HOOK_TOKEN=webhooktoken5e6ea45ef4e66eaa151612bdcb599df
|
||||||
|
WEB_HOOK_URI=https://accords-library.com/some/path
|
||||||
|
|
||||||
|
FTP_USER=someuser
|
||||||
|
FTP_PASSWORD=somepassword
|
||||||
|
FTP_HOST=ftp.host.com
|
||||||
|
FTP_BASE_URL=https://ftp-base-url.com
|
|
@ -12,7 +12,9 @@
|
||||||
"@fontsource/vollkorn": "5.0.19",
|
"@fontsource/vollkorn": "5.0.19",
|
||||||
"@payloadcms/bundler-webpack": "1.0.6",
|
"@payloadcms/bundler-webpack": "1.0.6",
|
||||||
"@payloadcms/db-mongodb": "1.4.4",
|
"@payloadcms/db-mongodb": "1.4.4",
|
||||||
|
"@payloadcms/plugin-cloud-storage": "^1.1.2",
|
||||||
"@payloadcms/richtext-lexical": "0.8.0",
|
"@payloadcms/richtext-lexical": "0.8.0",
|
||||||
|
"basic-ftp": "^5.0.5",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"language-tags": "1.0.9",
|
"language-tags": "1.0.9",
|
||||||
"luxon": "3.4.4",
|
"luxon": "3.4.4",
|
||||||
|
@ -3109,6 +3111,40 @@
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@payloadcms/plugin-cloud-storage": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@payloadcms/plugin-cloud-storage/-/plugin-cloud-storage-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-wBpEWv4VdfltBqEi5ECSrKQ/TtNvmBWT4DLCrTCOhpNuD8dYD2rp+0Eoj7cF8f6wU7DpS5rvdQ/8gxlqh0Armw==",
|
||||||
|
"dependencies": {
|
||||||
|
"find-node-modules": "^2.1.3",
|
||||||
|
"range-parser": "^1.2.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@aws-sdk/client-s3": "^3.142.0",
|
||||||
|
"@aws-sdk/lib-storage": "^3.267.0",
|
||||||
|
"@azure/abort-controller": "^1.0.0",
|
||||||
|
"@azure/storage-blob": "^12.11.0",
|
||||||
|
"@google-cloud/storage": "^6.4.1",
|
||||||
|
"payload": "^1.7.2 || ^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@aws-sdk/client-s3": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@aws-sdk/lib-storage": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@azure/abort-controller": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@azure/storage-blob": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@google-cloud/storage": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@payloadcms/richtext-lexical": {
|
"node_modules/@payloadcms/richtext-lexical": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@payloadcms/richtext-lexical/-/richtext-lexical-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@payloadcms/richtext-lexical/-/richtext-lexical-0.8.0.tgz",
|
||||||
|
@ -5116,6 +5152,14 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/basic-ftp": {
|
||||||
|
"version": "5.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
|
||||||
|
"integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/big.js": {
|
"node_modules/big.js": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||||
|
|
|
@ -25,7 +25,9 @@
|
||||||
"@fontsource/vollkorn": "5.0.19",
|
"@fontsource/vollkorn": "5.0.19",
|
||||||
"@payloadcms/bundler-webpack": "1.0.6",
|
"@payloadcms/bundler-webpack": "1.0.6",
|
||||||
"@payloadcms/db-mongodb": "1.4.4",
|
"@payloadcms/db-mongodb": "1.4.4",
|
||||||
|
"@payloadcms/plugin-cloud-storage": "^1.1.2",
|
||||||
"@payloadcms/richtext-lexical": "0.8.0",
|
"@payloadcms/richtext-lexical": "0.8.0",
|
||||||
|
"basic-ftp": "^5.0.5",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"language-tags": "1.0.9",
|
"language-tags": "1.0.9",
|
||||||
"luxon": "3.4.4",
|
"luxon": "3.4.4",
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { CollectionGroups, Collections } from "../../constants";
|
||||||
|
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||||
|
|
||||||
|
export const Videos = buildCollectionConfig({
|
||||||
|
slug: Collections.Videos,
|
||||||
|
labels: { singular: "Video", plural: "Videos" },
|
||||||
|
admin: { group: CollectionGroups.Media },
|
||||||
|
upload: {
|
||||||
|
mimeTypes: ["video/*"],
|
||||||
|
disableLocalStorage: true,
|
||||||
|
},
|
||||||
|
fields: [],
|
||||||
|
});
|
|
@ -19,6 +19,7 @@ export enum Collections {
|
||||||
Collectibles = "collectibles",
|
Collectibles = "collectibles",
|
||||||
GenericContents = "generic-contents",
|
GenericContents = "generic-contents",
|
||||||
HomeFolders = "home-folders",
|
HomeFolders = "home-folders",
|
||||||
|
Videos = "videos",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CollectionGroups {
|
export enum CollectionGroups {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { webpackBundler } from "@payloadcms/bundler-webpack";
|
import { webpackBundler } from "@payloadcms/bundler-webpack";
|
||||||
import { mongooseAdapter } from "@payloadcms/db-mongodb";
|
import { mongooseAdapter } from "@payloadcms/db-mongodb";
|
||||||
|
import { cloudStorage } from "@payloadcms/plugin-cloud-storage";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { buildConfig } from "payload/config";
|
import { buildConfig } from "payload/config";
|
||||||
import { ChronologyEvents } from "./collections/ChronologyEvents/ChronologyEvents";
|
import { ChronologyEvents } from "./collections/ChronologyEvents/ChronologyEvents";
|
||||||
|
@ -15,12 +16,21 @@ import { Pages } from "./collections/Pages/Pages";
|
||||||
import { Recorders } from "./collections/Recorders/Recorders";
|
import { Recorders } from "./collections/Recorders/Recorders";
|
||||||
import { Tags } from "./collections/Tags/Tags";
|
import { Tags } from "./collections/Tags/Tags";
|
||||||
import { TagsGroups } from "./collections/TagsGroups/TagsGroups";
|
import { TagsGroups } from "./collections/TagsGroups/TagsGroups";
|
||||||
|
import { Videos } from "./collections/Videos/Videos";
|
||||||
import { Wordings } from "./collections/Wordings/Wordings";
|
import { Wordings } from "./collections/Wordings/Wordings";
|
||||||
import { Icon } from "./components/Icon";
|
import { Icon } from "./components/Icon";
|
||||||
import { Logo } from "./components/Logo";
|
import { Logo } from "./components/Logo";
|
||||||
import { Collections } from "./constants";
|
import { Collections } from "./constants";
|
||||||
|
import { ftpAdapter } from "./plugins/ftpAdapter";
|
||||||
import { createEditor } from "./utils/editor";
|
import { createEditor } from "./utils/editor";
|
||||||
|
|
||||||
|
if (!process.env.PAYLOAD_URI) throw new Error("Missing PAYLOAD_URI in .env");
|
||||||
|
if (!process.env.MONGODB_URI) throw new Error("Missing MONGODB_URI in .env");
|
||||||
|
if (!process.env.FTP_HOST) throw new Error("Missing FTP_HOST in .env");
|
||||||
|
if (!process.env.FTP_USER) throw new Error("Missing FTP_USER in .env");
|
||||||
|
if (!process.env.FTP_PASSWORD) throw new Error("Missing FTP_PASSWORD in .env");
|
||||||
|
if (!process.env.FTP_BASE_URL) throw new Error("Missing FTP_BASE_URL in .env");
|
||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
serverURL: process.env.PAYLOAD_URI,
|
serverURL: process.env.PAYLOAD_URI,
|
||||||
admin: {
|
admin: {
|
||||||
|
@ -43,6 +53,7 @@ export default buildConfig({
|
||||||
Notes,
|
Notes,
|
||||||
|
|
||||||
Images,
|
Images,
|
||||||
|
Videos,
|
||||||
|
|
||||||
Tags,
|
Tags,
|
||||||
TagsGroups,
|
TagsGroups,
|
||||||
|
@ -53,7 +64,7 @@ export default buildConfig({
|
||||||
GenericContents,
|
GenericContents,
|
||||||
],
|
],
|
||||||
db: mongooseAdapter({
|
db: mongooseAdapter({
|
||||||
url: process.env.MONGODB_URI ?? "mongodb://mongo:27017/payload",
|
url: process.env.MONGODB_URI,
|
||||||
}),
|
}),
|
||||||
globals: [HomeFolders],
|
globals: [HomeFolders],
|
||||||
telemetry: false,
|
telemetry: false,
|
||||||
|
@ -63,4 +74,21 @@ export default buildConfig({
|
||||||
graphQL: {
|
graphQL: {
|
||||||
disable: true,
|
disable: true,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
cloudStorage({
|
||||||
|
collections: {
|
||||||
|
[Collections.Videos]: {
|
||||||
|
adapter: ftpAdapter({
|
||||||
|
host: process.env.FTP_HOST,
|
||||||
|
user: process.env.FTP_USER,
|
||||||
|
password: process.env.FTP_PASSWORD,
|
||||||
|
secure: false,
|
||||||
|
endpoint: process.env.FTP_BASE_URL,
|
||||||
|
}),
|
||||||
|
disableLocalStorage: true,
|
||||||
|
disablePayloadAccessControl: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
import {
|
||||||
|
Adapter,
|
||||||
|
GenerateURL,
|
||||||
|
HandleDelete,
|
||||||
|
HandleUpload,
|
||||||
|
} from "@payloadcms/plugin-cloud-storage/dist/types";
|
||||||
|
import { Client } from "basic-ftp";
|
||||||
|
import path from "path";
|
||||||
|
import { Readable } from "stream";
|
||||||
|
import type { Configuration as WebpackConfig } from "webpack";
|
||||||
|
|
||||||
|
interface FTPAdapterConfig {
|
||||||
|
host: string;
|
||||||
|
user: string;
|
||||||
|
password: string;
|
||||||
|
secure: boolean;
|
||||||
|
endpoint: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ftpAdapter =
|
||||||
|
({ endpoint, host, password, secure, user }: FTPAdapterConfig): Adapter =>
|
||||||
|
({ collection }) => {
|
||||||
|
const generateURL: GenerateURL = ({ filename }) => `${endpoint}/${collection.slug}/${filename}`;
|
||||||
|
const handleDelete: HandleDelete = async ({ filename }) => {
|
||||||
|
const client = new Client();
|
||||||
|
client.ftp.verbose = true;
|
||||||
|
await client.access({
|
||||||
|
host,
|
||||||
|
user,
|
||||||
|
password,
|
||||||
|
secure,
|
||||||
|
});
|
||||||
|
await client.ensureDir(collection.slug);
|
||||||
|
await client.remove(filename);
|
||||||
|
client.close();
|
||||||
|
};
|
||||||
|
const handleUpload: HandleUpload = async ({ file }) => {
|
||||||
|
const client = new Client();
|
||||||
|
client.ftp.verbose = true;
|
||||||
|
await client.access({
|
||||||
|
host: process.env.FTP_HOST,
|
||||||
|
user: process.env.FTP_USER,
|
||||||
|
password: process.env.FTP_PASSWORD,
|
||||||
|
secure: false,
|
||||||
|
});
|
||||||
|
await client.ensureDir(collection.slug);
|
||||||
|
await client.uploadFrom(Readable.from(file.buffer), file.filename);
|
||||||
|
client.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const webpack = (existingWebpackConfig: WebpackConfig): WebpackConfig => {
|
||||||
|
const newConfig: WebpackConfig = {
|
||||||
|
...existingWebpackConfig,
|
||||||
|
resolve: {
|
||||||
|
...(existingWebpackConfig.resolve || {}),
|
||||||
|
alias: {
|
||||||
|
...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
|
||||||
|
"./plugins/ftpAdapter": path.resolve(__dirname, "./mock.js"),
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
...(existingWebpackConfig.resolve?.fallback
|
||||||
|
? existingWebpackConfig.resolve.fallback
|
||||||
|
: {}),
|
||||||
|
stream: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return newConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
generateURL,
|
||||||
|
handleDelete,
|
||||||
|
handleUpload,
|
||||||
|
staticHandler: () => {},
|
||||||
|
webpack,
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
export const ftpAdapter = () => {};
|
|
@ -49,6 +49,7 @@ export interface Config {
|
||||||
"chronology-events": ChronologyEvent;
|
"chronology-events": ChronologyEvent;
|
||||||
notes: Note;
|
notes: Note;
|
||||||
images: Image;
|
images: Image;
|
||||||
|
videos: Video;
|
||||||
tags: Tag;
|
tags: Tag;
|
||||||
"tags-groups": TagsGroup;
|
"tags-groups": TagsGroup;
|
||||||
recorders: Recorder;
|
recorders: Recorder;
|
||||||
|
@ -622,6 +623,21 @@ export interface Note {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "videos".
|
||||||
|
*/
|
||||||
|
export interface Video {
|
||||||
|
id: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
url?: string | null;
|
||||||
|
filename?: string | null;
|
||||||
|
mimeType?: string | null;
|
||||||
|
filesize?: number | null;
|
||||||
|
width?: number | null;
|
||||||
|
height?: number | null;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "wordings".
|
* via the `definition` "wordings".
|
||||||
|
|
Loading…
Reference in New Issue