@cloudimage-strapi/content-plugin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 scaleflex
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Cloudimage plugin from Scaleflex for Strapi v4
2
+
3
+ ## Install
4
+
5
+ `npm install @cloudimage-strapi/content-plugin`
6
+
7
+ ## Config
8
+
9
+
10
+ `config/middlewares.js`
11
+
12
+ Replace `'strapi::security',` with:
13
+
14
+ ```
15
+ {
16
+ name: 'strapi::security',
17
+ config: {
18
+ contentSecurityPolicy: {
19
+ useDefaults: true,
20
+ directives: {
21
+ 'connect-src': ["'self'", 'https:'],
22
+ 'img-src': ["'self'", 'data:', 'blob:', 'scaleflex.cloudimg.io', 'assets.scaleflex.com', '*.cloudimg.io'],
23
+ 'media-src': ["'self'", 'data:', 'blob:', 'scaleflex.cloudimg.io', 'assets.scaleflex.com', '*.cloudimg.io'],
24
+ upgradeInsecureRequests: null,
25
+ },
26
+ },
27
+ },
28
+ },
29
+ ```
30
+
31
+ `config/server.js`
32
+
33
+ Append `url: 'domain (including the http/https:// part)'`
34
+
35
+ Eg: if you website is called `mywebsite.com`, then write like this:
36
+
37
+ ```
38
+ module.exports = ({ env }) => ({
39
+ host: env('HOST', '0.0.0.0'),
40
+ port: env.int('PORT', 1337),
41
+ app: {
42
+ keys: env.array('APP_KEYS'),
43
+ },
44
+ url: 'https://www.mywebsite.com',
45
+ });
46
+ ```
47
+
48
+ **It’s very important that you don’t forget to do this**
49
+
50
+ ## Configure
51
+
52
+ ![](https://user-images.githubusercontent.com/20809372/210363042-d254b19b-2cb6-493c-b3fe-676131d15cf3.png)
53
+
54
+ - You can enter either token or domain.
55
+ - Whether your Cloudimage token is v7 or not, it will be auto-detected and set.
56
+
57
+ If you enter nothing or an invalid token, you will get this error.
58
+
59
+ ![](https://user-images.githubusercontent.com/20809372/210363124-a3c548f5-8bf3-4303-bad7-22906f5e1585.png)
60
+
61
+ In the rare case that we can’t auto-detect whether token is v7 or not, you will get the option to manually set it.
62
+
63
+ ![](https://user-images.githubusercontent.com/20809372/210363178-0bb4c4b7-6fe6-4bee-8226-61fe0128c92f.png)
64
+
65
+ ## What the plugin brings
66
+
67
+ 1. This plugin simple gives client an interface to save the configuration settings.
68
+ 2. It also allows clients to Cloudimage-ize all previous images:
69
+
70
+ ![](https://user-images.githubusercontent.com/20809372/210363230-37094499-ecea-4f14-92e3-0a7217bb9a18.png)
71
+
72
+ - It will NOT Cloudimage-ize images that are already hosted on Filerobot.
73
+ - It will only sync images, no videos nor audios.
@@ -0,0 +1,26 @@
1
+ /**
2
+ *
3
+ * Initializer
4
+ *
5
+ */
6
+
7
+ import { useEffect, useRef } from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import pluginId from '../../pluginId';
10
+
11
+ const Initializer = ({ setPlugin }) => {
12
+ const ref = useRef();
13
+ ref.current = setPlugin;
14
+
15
+ useEffect(() => {
16
+ ref.current(pluginId);
17
+ }, []);
18
+
19
+ return null;
20
+ };
21
+
22
+ Initializer.propTypes = {
23
+ setPlugin: PropTypes.func.isRequired,
24
+ };
25
+
26
+ export default Initializer;
@@ -0,0 +1,12 @@
1
+ /**
2
+ *
3
+ * PluginIcon
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ import Puzzle from '@strapi/icons/Puzzle';
9
+
10
+ const PluginIcon = () => <img src="https://assets.scaleflex.com/Marketing/Logos/Cloudimage+Logos/Favicon/CLOUDIMAGE+favicon.ico" width="16" height="16" />;
11
+
12
+ export default PluginIcon;
@@ -0,0 +1,63 @@
1
+ import { prefixPluginTranslations } from '@strapi/helper-plugin';
2
+ import pluginPkg from '../../package.json';
3
+ import pluginId from './pluginId';
4
+ import Initializer from './components/Initializer';
5
+ import PluginIcon from './components/PluginIcon';
6
+
7
+ const name = "scaleflex-cloudimage";
8
+
9
+ export default {
10
+ register(app) {
11
+ app.addMenuLink({
12
+ to: `/plugins/${pluginId}`,
13
+ icon: PluginIcon,
14
+ intlLabel: {
15
+ id: `${pluginId}.plugin.name`,
16
+ defaultMessage: 'Cloudimage by Scaleflex',
17
+ },
18
+ Component: async () => {
19
+ const component = await import(/* webpackChunkName: "[request]" */ './pages/App');
20
+
21
+ return component;
22
+ },
23
+ permissions: [
24
+ // Uncomment to set the permissions of the plugin here
25
+ // {
26
+ // action: '', // the action name should be plugin::plugin-name.actionType
27
+ // subject: null,
28
+ // },
29
+ ],
30
+ });
31
+ app.registerPlugin({
32
+ id: pluginId,
33
+ initializer: Initializer,
34
+ isReady: false,
35
+ name,
36
+ });
37
+ },
38
+
39
+ bootstrap(app) {},
40
+ async registerTrads({ locales }) {
41
+ const importedTrads = await Promise.all(
42
+ locales.map(locale => {
43
+ return import(
44
+ /* webpackChunkName: "translation-[request]" */ `./translations/${locale}.json`
45
+ )
46
+ .then(({ default: data }) => {
47
+ return {
48
+ data: prefixPluginTranslations(data, pluginId),
49
+ locale,
50
+ };
51
+ })
52
+ .catch(() => {
53
+ return {
54
+ data: {},
55
+ locale,
56
+ };
57
+ });
58
+ })
59
+ );
60
+
61
+ return Promise.resolve(importedTrads);
62
+ },
63
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ *
3
+ * This component is the skeleton around the actual pages, and should only
4
+ * contain code that should be seen on all pages. (e.g. navigation bar)
5
+ *
6
+ */
7
+
8
+ import React from 'react';
9
+ import { Switch, Route } from 'react-router-dom';
10
+ import { NotFound } from '@strapi/helper-plugin';
11
+ import pluginId from '../../pluginId';
12
+ import HomePage from '../HomePage';
13
+
14
+ const App = () => {
15
+ return (
16
+ <div>
17
+ <Switch>
18
+ <Route path={`/plugins/${pluginId}`} component={HomePage} exact />
19
+ <Route component={NotFound} />
20
+ </Switch>
21
+ </div>
22
+ );
23
+ };
24
+
25
+ export default App;
@@ -0,0 +1,199 @@
1
+ /*
2
+ *
3
+ * HomePage
4
+ *
5
+ */
6
+
7
+ import React, {memo, useState, useEffect} from 'react';
8
+ import { Stack, Box, Typography, Field, FieldLabel, FieldInput, Button, Alert, Radio, RadioGroup } from '@strapi/design-system';
9
+ import {request} from "@strapi/helper-plugin";
10
+ import pluginId from '../../pluginId';
11
+
12
+ const HomePage = () => {
13
+ const [config, setConfig] = useState(null);
14
+ const [loading, setLoading] = useState(true);
15
+ const [domain, setDomain] = useState('');
16
+ const [isV7, setIsV7] = useState(false);
17
+ const [isV7CheckSuccessful, setIsV7CheckSuccessful] = useState(true);
18
+ const [manualV7, setManualV7] = useState(false);
19
+ const [disabledAllButtons, setDisabledAllButtons] = useState(false);
20
+ const [success, setSuccess] = useState(false);
21
+ const [error, setError] = useState(false);
22
+ const [disableUpdateButtons, setDisableUpdateButtons] = useState(false);
23
+ const [updateCount, setUpdateCount] = useState(-1);
24
+ const [displayUpdateResult, setDisplayUpdateResult] = useState(false);
25
+ const [updateMessage, setUpdateMessage] = useState('');
26
+
27
+ useEffect(() => {
28
+ request(`/${pluginId}/config`, {method: 'GET'}).then(config => {
29
+ setConfig(config);
30
+ setDomain(config.domain);
31
+ setLoading(false);
32
+
33
+ if (!config.domain || !config.hasOwnProperty('isV7'))
34
+ {
35
+ setDisableUpdateButtons(true);
36
+ }
37
+ else
38
+ {
39
+ setDisableUpdateButtons(false);
40
+ }
41
+ });
42
+ }, []);
43
+
44
+ if (loading)
45
+ {
46
+ return (
47
+ <Typography>fetching configuration...</Typography>
48
+ );
49
+ }
50
+
51
+ const saveConfiguration = async () => {
52
+ if (!domain)
53
+ {
54
+ setError(true);
55
+ setSuccess(false);
56
+ setDisabledAllButtons(false);
57
+
58
+ return;
59
+ }
60
+ else
61
+ {
62
+ setError(false);
63
+ }
64
+
65
+ setDisabledAllButtons(true);
66
+
67
+ // Check whether input is token or domain
68
+ let tokenOrDomain = '';
69
+
70
+ if (domain && domain.indexOf('.') === -1)
71
+ {
72
+ tokenOrDomain = `${domain}.cloudimg.io`.trim();
73
+ }
74
+ else
75
+ {
76
+ tokenOrDomain = domain.trim();
77
+ }
78
+
79
+ // Check whether v7 or not
80
+ let v7Check = await request(`/${pluginId}/is-v7?domain=${tokenOrDomain}`, {method: 'GET'});
81
+
82
+ if (!v7Check.domainExists)
83
+ {
84
+ setError(true);
85
+ setSuccess(false);
86
+ setDisabledAllButtons(false);
87
+
88
+ return;
89
+ }
90
+ else
91
+ {
92
+ setError(false);
93
+ }
94
+
95
+ setIsV7CheckSuccessful(v7Check.isSuccess);
96
+
97
+ let isV7Overall = v7Check.isSuccess ? v7Check.isV7 : manualV7;
98
+ setIsV7(isV7Overall);
99
+
100
+ // POST to backend to set config
101
+ let config = {
102
+ domain: tokenOrDomain,
103
+ isV7: isV7Overall
104
+ }
105
+
106
+ let updatedConfigs = await request(`/${pluginId}/update-config`, {method: 'PUT', body: config});
107
+
108
+ setDomain(updatedConfigs.domain);
109
+ setSuccess(true);
110
+ setDisabledAllButtons(false);
111
+ }
112
+
113
+ const countUpdate = async () => {
114
+ setUpdateCount(-1);
115
+ setDisabledAllButtons(true);
116
+ let count = await request(`/${pluginId}/count-update`, {method: 'GET'});
117
+ setUpdateCount(count);
118
+ setDisabledAllButtons(false);
119
+ }
120
+ const updateMedia = async () => {
121
+ setDisplayUpdateResult(false);
122
+ setDisabledAllButtons(true);
123
+
124
+ let result = await request(`/${pluginId}/update-media`, {method: 'PUT'});
125
+
126
+ if (result.response === false)
127
+ {
128
+ setUpdateMessage('Update was not successful. Please try again later.');
129
+ }
130
+ else
131
+ {
132
+ setUpdateMessage(`${result.response} updates was successful.`);
133
+ }
134
+
135
+ setDisplayUpdateResult(true);
136
+ setDisabledAllButtons(false);
137
+ }
138
+
139
+ return (
140
+ <>
141
+ <Stack spacing={4} padding={3}>
142
+ {success && isV7CheckSuccessful && (
143
+ <Alert title="Successful" onClose={() => setSuccess(false)} closeLabel="Close alert" variant={'success'}>
144
+ Configuration updated. Your domain is {isV7 ? '' : 'not'} of Cloudimage version 7.
145
+ </Alert>
146
+ )}
147
+ {success && !isV7CheckSuccessful && (
148
+ <Alert title="Failed" onClose={() => setError(false)} closeLabel="Close alert" variant={'danger'}>
149
+ Cannot auto-determine whether it's Cloudimage version 7 or not. Please mannually set Cloudimage version.
150
+ </Alert>
151
+ )}
152
+ {error && (
153
+ <Alert title="Failed" onClose={() => setError(false)} closeLabel="Close alert" variant={'danger'}>
154
+ Please check your configuration inputs. Ensure you entered valid inputs for all required fields.
155
+ </Alert>
156
+ )}
157
+ {updateCount > -1 && (
158
+ <Alert onClose={() => setUpdateCount(-1)} closeLabel="Close alert" variant={'success'}>
159
+ There are {updateCount} image URLs to be updated.
160
+ </Alert>
161
+ )}
162
+ {displayUpdateResult && (
163
+ <Alert onClose={() => setDisplayUpdateResult(false)} closeLabel="Close alert" variant={'success'}>
164
+ {(updateCount <= 0) ? 'None are to be updated.' : updateMessage}
165
+ </Alert>
166
+ )}
167
+ <Box paddingLeft={8} paddingTop={5} paddingRight={8}>
168
+ <Typography variant={'alpha'}>Cloudimage by Scaleflex</Typography>
169
+ </Box>
170
+ <Field name="domain">
171
+ <Stack spacing={1}>
172
+ <FieldLabel>Token or Domain *</FieldLabel>
173
+ <FieldInput type="text" placeholder="Token/Domain" value={domain} onChange={(e) => {
174
+ setDomain(e.target.value)
175
+ }}/>
176
+ </Stack>
177
+ </Field>
178
+ {!isV7CheckSuccessful && (
179
+ <Stack spacing={1}>
180
+ <FieldLabel>Is Cloudimage version 7 ?</FieldLabel>
181
+ <RadioGroup onChange={e => setManualV7(e.target.value)} value={manualV7} name="manualV7">
182
+ <Radio value="true">Version 7</Radio>
183
+ <Radio value="false">Not version 7</Radio>
184
+ </RadioGroup>
185
+ </Stack>
186
+ )}
187
+ <Box width={200}>
188
+ <Button disabled={disabledAllButtons} onClick={() => saveConfiguration()}>Save configuration</Button>
189
+ </Box>
190
+ <Stack horizontal spacing={4}>
191
+ <Button disabled={disabledAllButtons || disableUpdateButtons} onClick={() => countUpdate()}>Count updatable images</Button>
192
+ <Button disabled={disabledAllButtons || disableUpdateButtons} onClick={() => updateMedia()}>Update old images</Button>
193
+ </Stack>
194
+ </Stack>
195
+ </>
196
+ )
197
+ };
198
+
199
+ export default memo(HomePage);
@@ -0,0 +1,5 @@
1
+ import pluginPkg from '../../package.json';
2
+
3
+ const pluginId = "scaleflex-cloudimage".replace(/^(@[^-,.][\w,-]+\/|strapi-)plugin-/i, '');
4
+
5
+ export default pluginId;
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * axios with a custom config.
3
+ */
4
+
5
+ import axios from 'axios';
6
+ import { auth } from '@strapi/helper-plugin';
7
+
8
+ const instance = axios.create({
9
+ baseURL: process.env.STRAPI_ADMIN_BACKEND_URL,
10
+ });
11
+
12
+ instance.interceptors.request.use(
13
+ async config => {
14
+ config.headers = {
15
+ Authorization: `Bearer ${auth.getToken()}`,
16
+ Accept: 'application/json',
17
+ 'Content-Type': 'application/json',
18
+ };
19
+
20
+ return config;
21
+ },
22
+ error => {
23
+ Promise.reject(error);
24
+ }
25
+ );
26
+
27
+ instance.interceptors.response.use(
28
+ response => response,
29
+ error => {
30
+ // whatever you want to do with the error
31
+ if (error.response?.status === 401) {
32
+ auth.clearAppStorage();
33
+ window.location.reload();
34
+ }
35
+
36
+ throw error;
37
+ }
38
+ );
39
+
40
+ export default instance;
@@ -0,0 +1,5 @@
1
+ import pluginId from '../pluginId';
2
+
3
+ const getTrad = id => `${pluginId}.${id}`;
4
+
5
+ export default getTrad;
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@cloudimage-strapi/content-plugin",
3
+ "version": "1.0.0",
4
+ "description": "Strapi v4 plugin for Filerobot by Scaleflex",
5
+ "strapi": {
6
+ "name": "scaleflex-cloudimage",
7
+ "description": "Scaleflex Cloudimage",
8
+ "kind": "plugin",
9
+ "displayName": "Scaleflex Cloudimage"
10
+ },
11
+ "dependencies": {
12
+ "@strapi/design-system": "^1.4.1"
13
+ },
14
+ "peerDependencies": {
15
+ "@strapi/strapi": "^4.3.0"
16
+ },
17
+ "author": {
18
+ "name": "Scaleflex"
19
+ },
20
+ "maintainers": [
21
+ {
22
+ "name": "Ruslan Aliyev"
23
+ }
24
+ ],
25
+ "engines": {
26
+ "node": ">=12.x. <=16.x.x",
27
+ "npm": ">=6.0.0"
28
+ },
29
+ "license": "MIT",
30
+ "keywords": [
31
+ "scaleflex",
32
+ "filerobot",
33
+ "strapi"
34
+ ]
35
+ }
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ module.exports = ({ strapi }) => {
4
+ // bootstrap phase
5
+ };
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ default: {},
5
+ validator() {},
6
+ };
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = {};
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ const scaleflexCloudimage = require('./scaleflex-cloudimage');
4
+
5
+ module.exports = {
6
+ scaleflexCloudimage,
7
+ };
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ module.exports = ({ strapi }) => ({
4
+ async index(ctx) {
5
+ ctx.body = await strapi
6
+ .plugin('scaleflex-cloudimage')
7
+ .service('scaleflexCloudimage')
8
+ .getWelcomeMessage();
9
+ },
10
+ async getConfig(ctx) {
11
+ ctx.body = await strapi
12
+ .plugin('scaleflex-cloudimage')
13
+ .service('scaleflexCloudimage')
14
+ .getConfig();
15
+ },
16
+ async updateConfig(ctx) {
17
+ ctx.body = await strapi
18
+ .plugin('scaleflex-cloudimage')
19
+ .service('scaleflexCloudimage')
20
+ .updateConfig(ctx);
21
+ },
22
+ async checkV7(ctx) {
23
+ ctx.body = await strapi
24
+ .plugin('scaleflex-cloudimage')
25
+ .service('scaleflexCloudimage')
26
+ .checkV7(ctx);
27
+ },
28
+ async countUpdate(ctx) {
29
+ ctx.body = await strapi
30
+ .plugin('scaleflex-cloudimage')
31
+ .service('scaleflexCloudimage')
32
+ .countUpdate(ctx);
33
+ },
34
+ async updateMedia(ctx) {
35
+ ctx.body = await strapi
36
+ .plugin('scaleflex-cloudimage')
37
+ .service('scaleflexCloudimage')
38
+ .updateMedia(ctx);
39
+ },
40
+ });
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ module.exports = ({ strapi }) => {
4
+ // destroy phase
5
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ const register = require('./register');
4
+ const bootstrap = require('./bootstrap');
5
+ const destroy = require('./destroy');
6
+ const config = require('./config');
7
+ const contentTypes = require('./content-types');
8
+ const controllers = require('./controllers');
9
+ const routes = require('./routes');
10
+ const middlewares = require('./middlewares');
11
+ const policies = require('./policies');
12
+ const services = require('./services');
13
+
14
+ module.exports = {
15
+ register,
16
+ bootstrap,
17
+ destroy,
18
+ config,
19
+ controllers,
20
+ routes,
21
+ services,
22
+ contentTypes,
23
+ policies,
24
+ middlewares,
25
+ };
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = {};
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = {};
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+ //@Todo: Think about how this can be done in a cluster of may servers. Maybe persist the plugin's middleware settings in DB, then load it into that memory object upon start
3
+ module.exports = ({ strapi }) => {
4
+ // const pluginMiddleware = {
5
+ // name: 'strapi::security',
6
+ // config: {
7
+ // contentSecurityPolicy: {
8
+ // useDefaults: true,
9
+ // directives: {
10
+ // 'connect-src': ["'self'", 'https:'],
11
+ // 'img-src': ["'self'", 'data:', 'blob:', 'scaleflex.cloudimg.io', 'assets.scaleflex.com', '*.cloudimg.io'],
12
+ // 'media-src': ["'self'", 'data:', 'blob:', 'scaleflex.cloudimg.io', 'assets.scaleflex.com', '*.cloudimg.io'],
13
+ // upgradeInsecureRequests: null,
14
+ // },
15
+ // },
16
+ // },
17
+ // };
18
+
19
+ // // Merge a `source` object to a `target` recursively
20
+ // const merge = (target, source) => {
21
+ // // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
22
+ // for (const key of Object.keys(source))
23
+ // {
24
+ // if (Array.isArray(source[key]))
25
+ // {
26
+ // Object.assign(source[key], [...new Set(target[key].concat(source[key]))]);
27
+ // }
28
+
29
+ // if (source[key] instanceof Object && !Array.isArray(source[key]))
30
+ // {
31
+ // Object.assign(source[key], merge(target[key], source[key]));
32
+ // }
33
+ // }
34
+
35
+ // // Join `target` and modified `source`
36
+ // Object.assign(target || {}, source);
37
+
38
+ // return target;
39
+ // };
40
+
41
+ // for (let index = 1; index < strapi.config.middlewares.length; index++)
42
+ // {
43
+ // let item = strapi.config.middlewares[index];
44
+
45
+ // if (typeof item === 'object' && item.name === 'strapi::security')
46
+ // {
47
+ // let mergedSettings = merge(item.config, pluginMiddleware.config);
48
+ // strapi.config.middlewares.splice(index, 1, {name: 'strapi::security', config: mergedSettings});
49
+
50
+ // break;
51
+ // }
52
+ // else if (typeof item === 'string' && item === 'strapi::security')
53
+ // {
54
+ // strapi.config.middlewares.splice(index, 1, pluginMiddleware);
55
+
56
+ // break;
57
+ // }
58
+ // else
59
+ // {
60
+ // strapi.config.middlewares.push(pluginMiddleware);
61
+
62
+ // break;
63
+ // }
64
+ // }
65
+ };
@@ -0,0 +1,56 @@
1
+ module.exports = [
2
+ {
3
+ method: 'GET',
4
+ path: '/',
5
+ handler: 'scaleflexCloudimage.index',
6
+ config: {
7
+ policies: [],
8
+ auth: false,
9
+ },
10
+ },
11
+ {
12
+ method: 'GET',
13
+ path: '/config',
14
+ handler: 'scaleflexCloudimage.getConfig',
15
+ config: {
16
+ policies: [],
17
+ auth: false,
18
+ },
19
+ },
20
+ {
21
+ method: 'PUT',
22
+ path: '/update-config',
23
+ handler: 'scaleflexCloudimage.updateConfig',
24
+ config: {
25
+ policies: [],
26
+ auth: false,
27
+ },
28
+ },
29
+ {
30
+ method: 'GET',
31
+ path: '/is-v7',
32
+ handler: 'scaleflexCloudimage.checkV7',
33
+ config: {
34
+ policies: [],
35
+ auth: false,
36
+ },
37
+ },
38
+ {
39
+ method: 'GET',
40
+ path: '/count-update',
41
+ handler: 'scaleflexCloudimage.countUpdate',
42
+ config: {
43
+ policies: [],
44
+ auth: false,
45
+ },
46
+ },
47
+ {
48
+ method: 'PUT',
49
+ path: '/update-media',
50
+ handler: 'scaleflexCloudimage.updateMedia',
51
+ config: {
52
+ policies: [],
53
+ auth: false,
54
+ },
55
+ },
56
+ ];
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ const scaleflexCloudimage = require('./scaleflex-cloudimage');
4
+
5
+ module.exports = {
6
+ scaleflexCloudimage,
7
+ };
@@ -0,0 +1,187 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const fetch = require("node-fetch");
6
+
7
+ module.exports = ({ strapi }) => ({
8
+ getWelcomeMessage() {
9
+ return 'Thank you for using Scaleflex Filerobot';
10
+ },
11
+ getPluginStore() {
12
+ return strapi.store({
13
+ environment: strapi.config.environment,
14
+ type: 'plugin',
15
+ name: 'cloudimage',
16
+ });
17
+ },
18
+ async getConfig() {
19
+ const pluginStore = this.getPluginStore();
20
+
21
+ let config = {
22
+ domain: '',
23
+ isV7: ''
24
+ }
25
+
26
+ const storedConfig = await pluginStore.get({key: 'options'})
27
+ if (storedConfig) {
28
+ config = storedConfig;
29
+ }
30
+
31
+ return config
32
+ },
33
+ async updateConfig(ctx) {
34
+ const pluginStore = this.getPluginStore();
35
+
36
+ await pluginStore.set({
37
+ key: 'options',
38
+ value: ctx.request.body
39
+ });
40
+
41
+ const config = await pluginStore.get({key: 'options'});
42
+
43
+ // if (config.domain)
44
+ // {
45
+ // for (let index = 1; index < strapi.config.middlewares.length; index++)
46
+ // {
47
+ // let item = strapi.config.middlewares[index];
48
+
49
+ // if (typeof item === 'object' && item.name === 'strapi::security'
50
+ // && !item.config.contentSecurityPolicy.directives['img-src'].includes(config.domain))
51
+ // {
52
+ // strapi.config.middlewares[index].config.contentSecurityPolicy.directives['img-src'].push(config.domain);
53
+ // strapi.config.middlewares[index].config.contentSecurityPolicy.directives['media-src'].push(config.domain);
54
+ // }
55
+ // }
56
+ // }
57
+
58
+ return config;
59
+ },
60
+ async checkV7(ctx) {
61
+ let domain = ctx.request.query.domain;
62
+
63
+ let response = {};
64
+ let responseV7 = {};
65
+
66
+ try
67
+ {
68
+ response = await fetch(`https://${domain}/http://sample.li/blank.png`);
69
+ responseV7 = await fetch(`https://${domain}/v7/http://sample.li/blank.png`);
70
+ }
71
+ catch (error)
72
+ {
73
+ console.error(error);
74
+
75
+ return {domainExists: false};
76
+ }
77
+
78
+ let isValid = response.status === 200 && !response.headers.get('x-hexa-missingbehavior');
79
+ let isV7Valid = responseV7.status === 200 && !responseV7.headers.get('x-hexa-missingbehavior');
80
+
81
+ if (isValid && !isV7Valid)
82
+ {
83
+ return {isSuccess: true, domainExists: true, isV7: false};
84
+ }
85
+ else if (!isValid && isV7Valid)
86
+ {
87
+ return {isSuccess: true, domainExists: true, isV7: true};
88
+ }
89
+ else
90
+ {
91
+ return {isSuccess: false, domainExists: true};
92
+ }
93
+ },
94
+ async countUpdate(ctx) {
95
+ let pluginStore = this.getPluginStore();
96
+ let pluginConfig = await pluginStore.get({key: 'options'});
97
+ let domain = pluginConfig.domain;
98
+
99
+ let media = await strapi.entityService.findMany('plugin::upload.file', {
100
+ populate: {category: true},
101
+ filters: { // https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/entity-service/filter.html#and
102
+ $and: [
103
+ {
104
+ url: { $notContains: domain, },
105
+ },
106
+ {
107
+ mime: { $contains: 'image', },
108
+ },
109
+ {
110
+ provider: { $notContains: 'filerobot', },
111
+ },
112
+ ],
113
+ },
114
+ });
115
+
116
+ return media.length;
117
+ },
118
+ async updateMedia(ctx) {
119
+ let baseUrl = strapi.config.get('server.url');
120
+ let pluginStore = this.getPluginStore();
121
+ let pluginConfig = await pluginStore.get({key: 'options'});
122
+ let domain = pluginConfig.domain;
123
+ let isV7 = pluginConfig.isV7;
124
+
125
+ let media = await strapi.entityService.findMany('plugin::upload.file', {
126
+ populate: {category: true},
127
+ filters: {
128
+ $and: [
129
+ {
130
+ url: { $notContains: domain, },
131
+ },
132
+ {
133
+ mime: { $contains: 'image', },
134
+ },
135
+ {
136
+ provider: { $notContains: 'filerobot', },
137
+ },
138
+ ],
139
+ },
140
+ });
141
+
142
+ return Promise.all(media.map((item, index) => {
143
+ let prepUrl = '';
144
+
145
+ if (/^https?:\/\//.test(item.url))
146
+ {
147
+ prepUrl = item.url.replace(/^https?:\/\//, '');
148
+ }
149
+ else
150
+ {
151
+ prepUrl = `${baseUrl}${item.url}`.replace(/^https?:\/\//, '');
152
+ }
153
+
154
+ let ciUrl = `https://${pluginConfig.domain}${pluginConfig.isV7 ? '/v7' : ''}/${prepUrl}`;
155
+
156
+ return strapi.entityService.update('plugin::upload.file', item.id, {
157
+ data: {
158
+ url: ciUrl,
159
+ formats: null
160
+ },
161
+ })
162
+ .then(function(result) {
163
+ return {success: true, result: result};
164
+ })
165
+ .catch(function(error) {
166
+ return {success: false, error: error.message};
167
+ });
168
+ }))
169
+ .then(function(results) {
170
+ let successCount = 0;
171
+
172
+ results.forEach((result, index) => {
173
+ if (result.success)
174
+ {
175
+ successCount++;
176
+ }
177
+ });
178
+
179
+ return {response: `${successCount} / ${results.length}`};
180
+ })
181
+ .catch(function(error) {
182
+ console.dir(error.message);
183
+
184
+ return {response: false};
185
+ });
186
+ },
187
+ });
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('./admin/src').default;
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('./server');