mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 11:54:10 +00:00 
			
		
		
		
	Merge branch 'master' into master
This commit is contained in:
		
						commit
						f65644ba64
					
				@ -178,7 +178,7 @@ Load a middleware at the very first place
 | 
			
		||||
{
 | 
			
		||||
  "timeout": 100,
 | 
			
		||||
  "load": {
 | 
			
		||||
    "before": ["time", "responseTime", "logger", "cors", "responses", "gzip"],
 | 
			
		||||
    "before": ["timer", "responseTime", "logger", "cors", "responses", "gzip"],
 | 
			
		||||
    "order": [
 | 
			
		||||
      "Define the middlewares' load order by putting their name in this array is the right order"
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
@ -328,9 +328,27 @@ To enable the provider, create or edit the file at `./extensions/upload/config/s
 | 
			
		||||
 | 
			
		||||
Make sure to read the provider's `README` to know what are the possible parameters.
 | 
			
		||||
 | 
			
		||||
::: tip
 | 
			
		||||
Some providers may have additional settings such as the AWS S3 needs an API endpoint URL. You can find a list of these for AWS [here](https://docs.aws.amazon.com/general/latest/gr/ses.html)
 | 
			
		||||
:::
 | 
			
		||||
### Configuration per envrionment
 | 
			
		||||
 | 
			
		||||
When configuring your upload provider you might want to change the configuration based on the `NODE_ENV` environment variable or use environment specific credentials.
 | 
			
		||||
 | 
			
		||||
You can do so using a `settings.js` file:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
if (process.env.NODE_ENV === 'production') {
 | 
			
		||||
  module.exports = {
 | 
			
		||||
    provider: 'providerName',
 | 
			
		||||
    providerOptions: {
 | 
			
		||||
      cloud_name: process.env.PROVIDER_CLOUD_NAME,
 | 
			
		||||
      api_key: process.env.PROVIDER_API_KEY,
 | 
			
		||||
      api_secret: process.env.PROVIDER_API_SECRET,
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
} else {
 | 
			
		||||
  // to use the default local provider you can return an empty configuration
 | 
			
		||||
  module.exports = {};
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Create providers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@
 | 
			
		||||
  "containers.Edit.clickToJump": "Klicke, um zu einem Eintrag zu springen",
 | 
			
		||||
  "containers.Edit.delete": "Löschen",
 | 
			
		||||
  "containers.Edit.editing": "Bearbeite...",
 | 
			
		||||
  "containers.Edit.reset": "Abbrechen",
 | 
			
		||||
  "containers.Edit.reset": "Zurücksetzen",
 | 
			
		||||
  "containers.Edit.returnList": "Zu Liste zurückkehren",
 | 
			
		||||
  "containers.Edit.seeDetails": "Details",
 | 
			
		||||
  "containers.Edit.submit": "Speichern",
 | 
			
		||||
 | 
			
		||||
@ -172,7 +172,7 @@ const EditForm = forwardRef(
 | 
			
		||||
      try {
 | 
			
		||||
        const file = await getCroppedResult();
 | 
			
		||||
 | 
			
		||||
        onSubmitEdit(e, shouldDuplicate, file);
 | 
			
		||||
        onSubmitEdit(e, shouldDuplicate, file, true);
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        // Silent
 | 
			
		||||
      } finally {
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ import stepper from './stepper';
 | 
			
		||||
import useModalContext from '../../hooks/useModalContext';
 | 
			
		||||
 | 
			
		||||
const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange }) => {
 | 
			
		||||
  const { formatMessage } = useGlobalContext();
 | 
			
		||||
  const { emitEvent, formatMessage } = useGlobalContext();
 | 
			
		||||
  const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
 | 
			
		||||
  const [displayNextButton, setDisplayNextButton] = useState(false);
 | 
			
		||||
  const {
 | 
			
		||||
@ -62,6 +62,8 @@ const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange
 | 
			
		||||
  const editModalRef = useRef();
 | 
			
		||||
 | 
			
		||||
  const handleReplaceMedia = () => {
 | 
			
		||||
    emitEvent('didReplaceMedia', { location: 'upload' });
 | 
			
		||||
 | 
			
		||||
    editModalRef.current.click();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -199,12 +201,20 @@ const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange
 | 
			
		||||
  const handleSubmitEditExistingFile = async (
 | 
			
		||||
    e,
 | 
			
		||||
    shouldDuplicateMedia = false,
 | 
			
		||||
    file = fileToEdit.file
 | 
			
		||||
    file = fileToEdit.file,
 | 
			
		||||
    isSubmittingAfterCrop = false
 | 
			
		||||
  ) => {
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
 | 
			
		||||
    submitEditExistingFile();
 | 
			
		||||
 | 
			
		||||
    if (isSubmittingAfterCrop) {
 | 
			
		||||
      emitEvent('didCropFile', {
 | 
			
		||||
        duplicatedFile: shouldDuplicateMedia,
 | 
			
		||||
        location: 'content-manager',
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const headers = {};
 | 
			
		||||
    const formData = new FormData();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ const InputModalStepperProvider = ({
 | 
			
		||||
  step,
 | 
			
		||||
}) => {
 | 
			
		||||
  const [formErrors, setFormErrors] = useState(null);
 | 
			
		||||
  const { plugins } = useGlobalContext();
 | 
			
		||||
  const { emitEvent, plugins } = useGlobalContext();
 | 
			
		||||
  const [, updated_at] = getFileModelTimestamps(plugins);
 | 
			
		||||
  const [reducerState, dispatch] = useReducer(reducer, initialState, state =>
 | 
			
		||||
    init({
 | 
			
		||||
@ -69,6 +69,11 @@ const InputModalStepperProvider = ({
 | 
			
		||||
  const downloadFiles = async () => {
 | 
			
		||||
    const files = getFilesToDownload(filesToUpload);
 | 
			
		||||
 | 
			
		||||
    // Emit event when the users download files from url
 | 
			
		||||
    if (files.length > 0) {
 | 
			
		||||
      emitEvent('didSelectFile', { source: 'url', location: 'content-manager' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await Promise.all(
 | 
			
		||||
        files.map(file => {
 | 
			
		||||
@ -263,6 +268,9 @@ const InputModalStepperProvider = ({
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleSetCropResult = blob => {
 | 
			
		||||
    // Emit event : the user cropped a file that is not uploaded
 | 
			
		||||
    emitEvent('didCropFile', { duplicatedFile: null, location: 'content-manager' });
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'SET_CROP_RESULT',
 | 
			
		||||
      blob,
 | 
			
		||||
@ -352,6 +360,8 @@ const InputModalStepperProvider = ({
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const addFilesToUpload = ({ target: { value } }) => {
 | 
			
		||||
    emitEvent('didSelectFile', { source: 'computer', location: 'content-manager' });
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'ADD_FILES_TO_UPLOAD',
 | 
			
		||||
      filesToUpload: value,
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ const ModalStepper = ({
 | 
			
		||||
  onDeleteMedia,
 | 
			
		||||
  onToggle,
 | 
			
		||||
}) => {
 | 
			
		||||
  const { formatMessage } = useGlobalContext();
 | 
			
		||||
  const { emitEvent, formatMessage } = useGlobalContext();
 | 
			
		||||
  const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false);
 | 
			
		||||
  const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
 | 
			
		||||
  const [isFormDisabled, setIsFormDisabled] = useState(false);
 | 
			
		||||
@ -74,6 +74,8 @@ const ModalStepper = ({
 | 
			
		||||
  }, [isOpen]);
 | 
			
		||||
 | 
			
		||||
  const addFilesToUpload = ({ target: { value } }) => {
 | 
			
		||||
    emitEvent('didSelectFile', { source: 'computer', location: 'upload' });
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'ADD_FILES_TO_UPLOAD',
 | 
			
		||||
      filesToUpload: value,
 | 
			
		||||
@ -85,6 +87,11 @@ const ModalStepper = ({
 | 
			
		||||
  downloadFilesRef.current = async () => {
 | 
			
		||||
    const files = getFilesToDownload(filesToUpload);
 | 
			
		||||
 | 
			
		||||
    // Emit event when the users download files from url
 | 
			
		||||
    if (files.length > 0) {
 | 
			
		||||
      emitEvent('didSelectFile', { source: 'url', location: 'upload' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await Promise.all(
 | 
			
		||||
        files.map(file => {
 | 
			
		||||
@ -255,6 +262,9 @@ const ModalStepper = ({
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleSetCropResult = blob => {
 | 
			
		||||
    // Emit event : the user cropped a file that is not uploaded
 | 
			
		||||
    emitEvent('didCropFile', { duplicatedFile: null, location: 'upload' });
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'SET_CROP_RESULT',
 | 
			
		||||
      blob,
 | 
			
		||||
@ -274,10 +284,15 @@ const ModalStepper = ({
 | 
			
		||||
  const handleSubmitEditExistingFile = async (
 | 
			
		||||
    e,
 | 
			
		||||
    shouldDuplicateMedia = false,
 | 
			
		||||
    file = fileToEdit.file
 | 
			
		||||
    file = fileToEdit.file,
 | 
			
		||||
    isSubmittingAfterCrop = false
 | 
			
		||||
  ) => {
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
 | 
			
		||||
    if (isSubmittingAfterCrop) {
 | 
			
		||||
      emitEvent('didCropFile', { duplicatedFile: shouldDuplicateMedia, location: 'upload' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'ON_SUBMIT_EDIT_EXISTING_FILE',
 | 
			
		||||
    });
 | 
			
		||||
@ -331,6 +346,7 @@ const ModalStepper = ({
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleReplaceMedia = () => {
 | 
			
		||||
    emitEvent('didReplaceMedia', { location: 'upload' });
 | 
			
		||||
    editModalRef.current.click();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,40 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const body = require('koa-body');
 | 
			
		||||
const qs = require('koa-qs');
 | 
			
		||||
const qs = require('qs');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Body parser hook
 | 
			
		||||
 */
 | 
			
		||||
const addQsParser = app => {
 | 
			
		||||
  Object.defineProperty(app.request, 'query', {
 | 
			
		||||
    configurable: false,
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    /*
 | 
			
		||||
     * Get parsed query-string.
 | 
			
		||||
     */
 | 
			
		||||
    get() {
 | 
			
		||||
      const qstr = this.querystring;
 | 
			
		||||
      const cache = (this._querycache = this._querycache || {});
 | 
			
		||||
      return cache[qstr] || (cache[qstr] = qs.parse(qstr));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Set query-string as an object.
 | 
			
		||||
     */
 | 
			
		||||
    set(obj) {
 | 
			
		||||
      this.querystring = qs.stringify(obj);
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return app;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = strapi => {
 | 
			
		||||
  return {
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize the hook
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    initialize() {
 | 
			
		||||
      strapi.app.use((ctx, next) => {
 | 
			
		||||
        // disable for graphql
 | 
			
		||||
@ -24,7 +47,7 @@ module.exports = strapi => {
 | 
			
		||||
        })(ctx, next);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      qs(strapi.app);
 | 
			
		||||
      addQsParser(strapi.app);
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,6 @@
 | 
			
		||||
    "koa-ip": "^2.0.0",
 | 
			
		||||
    "koa-locale": "~1.3.0",
 | 
			
		||||
    "koa-lusca": "~2.2.0",
 | 
			
		||||
    "koa-qs": "^2.0.0",
 | 
			
		||||
    "koa-router": "^7.4.0",
 | 
			
		||||
    "koa-session": "^5.12.0",
 | 
			
		||||
    "koa-static": "^5.0.0",
 | 
			
		||||
@ -49,6 +48,7 @@
 | 
			
		||||
    "node-schedule": "1.3.2",
 | 
			
		||||
    "opn": "^5.3.0",
 | 
			
		||||
    "ora": "^3.0.0",
 | 
			
		||||
    "qs": "^6.9.3",
 | 
			
		||||
    "resolve-cwd": "^3.0.0",
 | 
			
		||||
    "rimraf": "^2.6.2",
 | 
			
		||||
    "shelljs": "^0.8.3",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								yarn.lock
									
									
									
									
									
								
							@ -10821,14 +10821,6 @@ koa-lusca@~2.2.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    koa-compose "~2.3.0"
 | 
			
		||||
 | 
			
		||||
koa-qs@^2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/koa-qs/-/koa-qs-2.0.0.tgz#18d16b43508a541f092e514351dc09563a48819f"
 | 
			
		||||
  integrity sha1-GNFrQ1CKVB8JLlFDUdwJVjpIgZ8=
 | 
			
		||||
  dependencies:
 | 
			
		||||
    merge-descriptors "~0.0.2"
 | 
			
		||||
    qs "~2.3.3"
 | 
			
		||||
 | 
			
		||||
koa-range@0.3.0:
 | 
			
		||||
  version "0.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/koa-range/-/koa-range-0.3.0.tgz#3588e3496473a839a1bd264d2a42b1d85bd7feac"
 | 
			
		||||
@ -11778,16 +11770,11 @@ meow@^5.0.0:
 | 
			
		||||
    trim-newlines "^2.0.0"
 | 
			
		||||
    yargs-parser "^10.0.0"
 | 
			
		||||
 | 
			
		||||
merge-descriptors@1.0.1:
 | 
			
		||||
merge-descriptors@1.0.1, merge-descriptors@^1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
 | 
			
		||||
  integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
 | 
			
		||||
 | 
			
		||||
merge-descriptors@~0.0.2:
 | 
			
		||||
  version "0.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-0.0.2.tgz#c36a52a781437513c57275f39dd9d317514ac8c7"
 | 
			
		||||
  integrity sha1-w2pSp4FDdRPFcnXzndnTF1FKyMc=
 | 
			
		||||
 | 
			
		||||
merge-stream@^2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
 | 
			
		||||
@ -14330,10 +14317,10 @@ qs@^6.4.0, qs@^6.5.1, qs@^6.5.2, qs@^6.9.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
 | 
			
		||||
  integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==
 | 
			
		||||
 | 
			
		||||
qs@~2.3.3:
 | 
			
		||||
  version "2.3.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404"
 | 
			
		||||
  integrity sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=
 | 
			
		||||
qs@^6.9.3:
 | 
			
		||||
  version "6.9.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e"
 | 
			
		||||
  integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==
 | 
			
		||||
 | 
			
		||||
qs@~6.5.1, qs@~6.5.2:
 | 
			
		||||
  version "6.5.2"
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user