mirror of
https://github.com/strapi/strapi.git
synced 2025-12-13 16:08:11 +00:00
Fix/#4513/ability to use a sub path behind a proxy (#5833)
* add possibility to use strapi on a non-root base url path * fix documentation password form * use server.url and admin.url in config Signed-off-by: Pierre Noël <pierre.noel@strapi.io> * update doc proxy Signed-off-by: Pierre Noël <pierre.noel@strapi.io> * move server.url location in config Signed-off-by: Pierre Noël <pierre.noel@strapi.io> * refacto Signed-off-by: Pierre Noël <pierre.noel@strapi.io> * add possibility to put relative urls Signed-off-by: Pierre Noël <pierre.noel@strapi.io> * allow '/' as an admin url + refacto Signed-off-by: Pierre Noël <pierre.noel@strapi.io> * update yarn.lock Signed-off-by: Pierre Noël <petersg83@gmail.com> * refacto Signed-off-by: Pierre Noël <petersg83@gmail.com> * Remove default proxy option Signed-off-by: Alexandre Bodin <bodin.alex@gmail.com> * fix github provider Signed-off-by: Pierre Noël <petersg83@gmail.com> * fix github login Signed-off-by: Pierre Noël <petersg83@gmail.com> * Remove files that should be here Signed-off-by: Alexandre Bodin <bodin.alex@gmail.com> Co-authored-by: Pierre Noël <pierre.noel@strapi.io> Co-authored-by: Alexandre Bodin <bodin.alex@gmail.com>
This commit is contained in:
parent
2b3d94d747
commit
57d7d876b7
@ -139,8 +139,7 @@ import axios from 'axios';
|
||||
axios
|
||||
.post('http://localhost:1337/auth/forgot-password', {
|
||||
email: 'user@strapi.io',
|
||||
url:
|
||||
'http:/localhost:1337/admin/plugins/users-permissions/auth/reset-password',
|
||||
url: 'http:/localhost:1337/admin/plugins/users-permissions/auth/reset-password',
|
||||
})
|
||||
.then(response => {
|
||||
// Handle success.
|
||||
|
||||
@ -173,16 +173,12 @@ module.exports = ({ env }) => ({
|
||||
| `host` | Host name | string | `localhost` |
|
||||
| `port` | Port on which the server should be running. | integer | `1337` |
|
||||
| `emitErrors` | Enable errors to be emitted to `koa` when they happen in order to attach custom logic or use error reporting services. | boolean | |
|
||||
| `proxy` | Proxy configuration | Object | |
|
||||
| `proxy.enabled` | Enable proxy support such as Apache or Nginx. | boolean | `false` |
|
||||
| `proxy.ssl` | Enable proxy SSL support. | boolean | |
|
||||
| `proxy.host` | Host name your proxy service uses for Strapi. | string | |
|
||||
| `proxy.port` | Port that your proxy service accepts connections on. | integer | |
|
||||
| `url` | Url of the server. Enable proxy support such as Apache or Nginx, example: `https://mywebsite.com/api`. Default value: `http://${host}:${port}`. | string | |
|
||||
| `cron` | Cron configuration (powered by [`node-schedule`](https://github.com/node-schedule/node-schedule)) | Object | |
|
||||
| `cron.enabled` | Enable or disable CRON tasks to schedule jobs at specific dates. | boolean | `false` |
|
||||
| `admin` | Admin panel configuration | Object | |
|
||||
| `admin.url` | Url of your admin panel. Default value: `/admin`. Note: If the url is relative, it will be concatenated with `url`. | string | `/admin` |
|
||||
| `admin.autoOpen` | Enable or disabled administration opening on start. | boolean | `true` |
|
||||
| `admin.path` | Allow to change the URL to access the admin panel. | string | `/admin` |
|
||||
| `admin.watchIgnoreFiles` | Add custom files that should not be watched during development. See more [here](https://github.com/paulmillr/chokidar#path-filtering) (property `ignored`). | Array(string) | `[]`. |
|
||||
| `admin.build` | Admin panel build configuration | Object | |
|
||||
| `admin.build.backend` | URL that the admin panel and plugins will request | string | |
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
Upgrading your Strapi application to `v3.0.0-beta.18`.
|
||||
|
||||
**Make sure your server is not running until then end of the migration**
|
||||
**Make sure your server is not running until the end of the migration**
|
||||
|
||||
## Upgrading your dependencies
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
Upgrading your Strapi application to `v3.0.0-beta.19`.
|
||||
|
||||
**Make sure your server is not running until then end of the migration**
|
||||
**Make sure your server is not running until the end of the migration**
|
||||
|
||||
## Upgrading your dependencies
|
||||
|
||||
|
||||
@ -76,13 +76,9 @@ module.exports = strapi => {
|
||||
try {
|
||||
client = require(connection.settings.client);
|
||||
} catch (err) {
|
||||
strapi.log.error('The client `' + connection.settings.client + '` is not installed.');
|
||||
strapi.log.error(
|
||||
'The client `' + connection.settings.client + '` is not installed.'
|
||||
);
|
||||
strapi.log.error(
|
||||
'You can install it with `$ npm install ' +
|
||||
connection.settings.client +
|
||||
' --save`.'
|
||||
'You can install it with `$ npm install ' + connection.settings.client + ' --save`.'
|
||||
);
|
||||
strapi.stop();
|
||||
}
|
||||
@ -92,9 +88,7 @@ module.exports = strapi => {
|
||||
client: connection.settings.client,
|
||||
connection: {
|
||||
host: _.get(connection.settings, 'host'),
|
||||
user:
|
||||
_.get(connection.settings, 'username') ||
|
||||
_.get(connection.settings, 'user'),
|
||||
user: _.get(connection.settings, 'username') || _.get(connection.settings, 'user'),
|
||||
password: _.get(connection.settings, 'password'),
|
||||
database: _.get(connection.settings, 'database'),
|
||||
charset: _.get(connection.settings, 'charset'),
|
||||
@ -106,10 +100,7 @@ module.exports = strapi => {
|
||||
filename: _.get(connection.settings, 'filename', '.tmp/data.db'),
|
||||
},
|
||||
debug: _.get(connection.options, 'debug', false),
|
||||
acquireConnectionTimeout: _.get(
|
||||
connection.options,
|
||||
'acquireConnectionTimeout'
|
||||
),
|
||||
acquireConnectionTimeout: _.get(connection.options, 'acquireConnectionTimeout'),
|
||||
migrations: _.get(connection.options, 'migrations'),
|
||||
useNullAsDefault: _.get(connection.options, 'useNullAsDefault'),
|
||||
},
|
||||
@ -121,26 +112,10 @@ module.exports = strapi => {
|
||||
options.pool = {
|
||||
min: _.get(connection.options, 'pool.min', 0),
|
||||
max: _.get(connection.options, 'pool.max', 10),
|
||||
acquireTimeoutMillis: _.get(
|
||||
connection.options,
|
||||
'pool.acquireTimeoutMillis',
|
||||
2000
|
||||
),
|
||||
createTimeoutMillis: _.get(
|
||||
connection.options,
|
||||
'pool.createTimeoutMillis',
|
||||
2000
|
||||
),
|
||||
idleTimeoutMillis: _.get(
|
||||
connection.options,
|
||||
'pool.idleTimeoutMillis',
|
||||
30000
|
||||
),
|
||||
reapIntervalMillis: _.get(
|
||||
connection.options,
|
||||
'pool.reapIntervalMillis',
|
||||
1000
|
||||
),
|
||||
acquireTimeoutMillis: _.get(connection.options, 'pool.acquireTimeoutMillis', 2000),
|
||||
createTimeoutMillis: _.get(connection.options, 'pool.createTimeoutMillis', 2000),
|
||||
idleTimeoutMillis: _.get(connection.options, 'pool.idleTimeoutMillis', 30000),
|
||||
reapIntervalMillis: _.get(connection.options, 'pool.reapIntervalMillis', 1000),
|
||||
createRetryIntervalMillis: _.get(
|
||||
connection.options,
|
||||
'pool.createRetryIntervalMillis',
|
||||
@ -151,9 +126,7 @@ module.exports = strapi => {
|
||||
|
||||
// Resolve path to the directory containing the database file.
|
||||
const fileDirectory = options.connection.filename
|
||||
? path.dirname(
|
||||
path.resolve(strapi.config.appPath, options.connection.filename)
|
||||
)
|
||||
? path.dirname(path.resolve(strapi.config.appPath, options.connection.filename))
|
||||
: '';
|
||||
|
||||
switch (options.client) {
|
||||
@ -180,12 +153,9 @@ module.exports = strapi => {
|
||||
options.pool = {
|
||||
...options.pool,
|
||||
afterCreate: (conn, cb) => {
|
||||
conn.query(
|
||||
`SET SESSION SCHEMA '${options.connection.schema}';`,
|
||||
err => {
|
||||
cb(err, conn);
|
||||
}
|
||||
);
|
||||
conn.query(`SET SESSION SCHEMA '${options.connection.schema}';`, err => {
|
||||
cb(err, conn);
|
||||
});
|
||||
},
|
||||
};
|
||||
} else {
|
||||
@ -227,9 +197,7 @@ module.exports = strapi => {
|
||||
} catch (err) {
|
||||
strapi.log.error('Impossible to use the `' + name + '` connection...');
|
||||
strapi.log.warn(
|
||||
'Be sure that your client `' +
|
||||
name +
|
||||
'` are in the same node_modules directory'
|
||||
'Be sure that your client `' + name + '` are in the same node_modules directory'
|
||||
);
|
||||
strapi.log.error(err);
|
||||
strapi.stop();
|
||||
|
||||
@ -13,9 +13,14 @@ module.exports = async (ctx, next) => {
|
||||
if (!ctx.session.documentation) {
|
||||
const querystring = ctx.querystring ? `?${ctx.querystring}` : '';
|
||||
|
||||
return ctx.redirect(`${strapi.plugins.documentation.config['x-strapi-config'].path}/login${querystring}`);
|
||||
return ctx.redirect(
|
||||
`${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}/login${querystring}`
|
||||
);
|
||||
}
|
||||
const isValid = strapi.plugins['users-permissions'].services.user.validatePassword(ctx.session.documentation, config.password);
|
||||
const isValid = strapi.plugins['users-permissions'].services.user.validatePassword(
|
||||
ctx.session.documentation,
|
||||
config.password
|
||||
);
|
||||
|
||||
if (!isValid) {
|
||||
ctx.session.documentation = null;
|
||||
|
||||
@ -18,11 +18,6 @@ const koaStatic = require('koa-static');
|
||||
module.exports = {
|
||||
getInfos: async ctx => {
|
||||
try {
|
||||
const prefix = _.get(
|
||||
strapi.plugins,
|
||||
['documentation', 'config', 'x-strapi-config', 'path'],
|
||||
'/documentation'
|
||||
);
|
||||
const service = strapi.plugins.documentation.services.documentation;
|
||||
const docVersions = service.retrieveDocumentationVersions();
|
||||
const form = await service.retrieveFrontForm();
|
||||
@ -30,7 +25,7 @@ module.exports = {
|
||||
ctx.send({
|
||||
docVersions,
|
||||
currentVersion: service.getDocumentationVersion(),
|
||||
prefix: `/${prefix}`.replace('//', '/'),
|
||||
prefix: strapi.plugins.documentation.config['x-strapi-config'].path,
|
||||
form,
|
||||
});
|
||||
} catch (err) {
|
||||
@ -39,15 +34,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
async index(ctx, next) {
|
||||
// Read layout file.
|
||||
|
||||
try {
|
||||
const layout = fs.readFileSync(
|
||||
path.resolve(__dirname, '..', 'public', 'index.html'),
|
||||
'utf8'
|
||||
);
|
||||
const $ = cheerio.load(layout);
|
||||
|
||||
/**
|
||||
* We don't expose the specs using koa-static or something else due to security reasons.
|
||||
* That's why, we need to read the file localy and send the specs through it when we serve the Swagger UI.
|
||||
@ -68,39 +55,16 @@ module.exports = {
|
||||
|
||||
try {
|
||||
const documentation = fs.readFileSync(openAPISpecsPath, 'utf8');
|
||||
|
||||
// Remove previous Swagger configuration.
|
||||
$('.custom-swagger-ui').remove();
|
||||
// Set new Swagger configuration
|
||||
$('body').append(`
|
||||
<script class="custom-swagger-ui">
|
||||
window.onload = function() {
|
||||
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "https://petstore.swagger.io/v2/swagger.json",
|
||||
spec: ${JSON.stringify(JSON.parse(documentation))},
|
||||
dom_id: '#swagger-ui',
|
||||
docExpansion: "none",
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
`);
|
||||
const layout = fs.readFileSync(
|
||||
path.resolve(__dirname, '..', 'public', 'index.html'),
|
||||
'utf8'
|
||||
);
|
||||
const filledLayout = _.template(layout)({
|
||||
backendUrl: strapi.config.server.url,
|
||||
spec: JSON.stringify(JSON.parse(documentation)),
|
||||
});
|
||||
|
||||
try {
|
||||
// Write the layout with the new Swagger configuration.
|
||||
// fs.writeFileSync(layoutPath, $.html());
|
||||
const layoutPath = path.resolve(
|
||||
strapi.config.appPath,
|
||||
'extensions',
|
||||
@ -109,7 +73,7 @@ module.exports = {
|
||||
'index.html'
|
||||
);
|
||||
await fs.ensureFile(layoutPath);
|
||||
await fs.writeFile(layoutPath, $.html());
|
||||
await fs.writeFile(layoutPath, filledLayout);
|
||||
|
||||
// Serve the file.
|
||||
ctx.url = path.basename(`${ctx.url}/index.html`);
|
||||
@ -140,15 +104,12 @@ module.exports = {
|
||||
const { error } = ctx.query;
|
||||
|
||||
try {
|
||||
const layout = fs.readFileSync(
|
||||
path.join(__dirname, '..', 'public', 'login.html')
|
||||
);
|
||||
const $ = cheerio.load(layout);
|
||||
const layout = fs.readFileSync(path.join(__dirname, '..', 'public', 'login.html'));
|
||||
const filledLayout = _.template(layout)({
|
||||
actionUrl: `${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}/login`,
|
||||
});
|
||||
const $ = cheerio.load(filledLayout);
|
||||
|
||||
$('form').attr(
|
||||
'action',
|
||||
`${strapi.plugins.documentation.config['x-strapi-config'].path}/login`
|
||||
);
|
||||
$('.error').text(_.isEmpty(error) ? '' : 'Wrong password...');
|
||||
|
||||
try {
|
||||
@ -197,9 +158,10 @@ module.exports = {
|
||||
})
|
||||
.get();
|
||||
|
||||
const isValid = strapi.plugins[
|
||||
'users-permissions'
|
||||
].services.user.validatePassword(password, storedPassword);
|
||||
const isValid = strapi.plugins['users-permissions'].services.user.validatePassword(
|
||||
password,
|
||||
storedPassword
|
||||
);
|
||||
let querystring = '?error=password';
|
||||
|
||||
if (isValid) {
|
||||
@ -208,17 +170,13 @@ module.exports = {
|
||||
}
|
||||
|
||||
ctx.redirect(
|
||||
`${
|
||||
strapi.plugins.documentation.config['x-strapi-config'].path
|
||||
}${querystring}`
|
||||
`${strapi.config.server.url}${strapi.plugins.documentation.config['x-strapi-config'].path}${querystring}`
|
||||
);
|
||||
},
|
||||
|
||||
regenerateDoc: async ctx => {
|
||||
const service = strapi.plugins.documentation.services.documentation;
|
||||
const documentationVersions = service
|
||||
.retrieveDocumentationVersions()
|
||||
.map(el => el.version);
|
||||
const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
|
||||
const {
|
||||
request: {
|
||||
body: { version },
|
||||
@ -254,10 +212,7 @@ module.exports = {
|
||||
);
|
||||
ctx.send({ ok: true });
|
||||
} catch (err) {
|
||||
ctx.badRequest(
|
||||
null,
|
||||
admin ? 'documentation.error.regenerateDoc' : 'An error occured'
|
||||
);
|
||||
ctx.badRequest(null, admin ? 'documentation.error.regenerateDoc' : 'An error occured');
|
||||
} finally {
|
||||
strapi.reload.isWatching = true;
|
||||
}
|
||||
@ -266,9 +221,7 @@ module.exports = {
|
||||
deleteDoc: async ctx => {
|
||||
strapi.reload.isWatching = false;
|
||||
const service = strapi.plugins.documentation.services.documentation;
|
||||
const documentationVersions = service
|
||||
.retrieveDocumentationVersions()
|
||||
.map(el => el.version);
|
||||
const documentationVersions = service.retrieveDocumentationVersions().map(el => el.version);
|
||||
const {
|
||||
request: {
|
||||
params: { version },
|
||||
@ -318,14 +271,11 @@ module.exports = {
|
||||
if (restrictedAccess && _.isEmpty(password)) {
|
||||
return ctx.badRequest(
|
||||
null,
|
||||
admin
|
||||
? 'users-permissions.Auth.form.error.password.provide'
|
||||
: 'Please provide a password'
|
||||
admin ? 'users-permissions.Auth.form.error.password.provide' : 'Please provide a password'
|
||||
);
|
||||
}
|
||||
|
||||
const isNewPassword =
|
||||
!_.isEmpty(password) && password !== prevConfig.password;
|
||||
const isNewPassword = !_.isEmpty(password) && password !== prevConfig.password;
|
||||
|
||||
if (isNewPassword && usersPermService.user.isHashed(password)) {
|
||||
// Throw an error if the password selected by the user
|
||||
|
||||
@ -18,9 +18,7 @@ module.exports = strapi => {
|
||||
beforeInitialize() {
|
||||
strapi.config.middleware.load.before.push('documentation');
|
||||
|
||||
initialRoutes.push(
|
||||
..._.cloneDeep(strapi.plugins.documentation.config.routes)
|
||||
);
|
||||
initialRoutes.push(..._.cloneDeep(strapi.plugins.documentation.config.routes));
|
||||
},
|
||||
|
||||
initialize() {
|
||||
@ -31,22 +29,12 @@ module.exports = strapi => {
|
||||
return route;
|
||||
}
|
||||
|
||||
if (
|
||||
route.handler === 'Documentation.index' ||
|
||||
route.path === '/login'
|
||||
) {
|
||||
if (route.handler === 'Documentation.index' || route.path === '/login') {
|
||||
route.config.policies = initialRoutes[index].config.policies;
|
||||
}
|
||||
|
||||
// Set prefix to empty to be able to customise it.
|
||||
if (
|
||||
_.get(strapi.plugins, [
|
||||
'documentation',
|
||||
'config',
|
||||
'x-strapi-config',
|
||||
'path',
|
||||
])
|
||||
) {
|
||||
if (_.get(strapi.plugins, ['documentation', 'config', 'x-strapi-config', 'path'])) {
|
||||
route.config.prefix = '';
|
||||
route.path = `/${strapi.plugins.documentation.config['x-strapi-config'].path}${route.path}`.replace(
|
||||
'//',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -20,18 +20,18 @@
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
|
||||
.login {
|
||||
height: 100%;
|
||||
background-color: #F6F9FC;
|
||||
}
|
||||
|
||||
|
||||
.login .login-form {
|
||||
height: calc(100% - 70px);
|
||||
padding: 68px 0 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.login .login-form form {
|
||||
position: relative;
|
||||
max-width: 460px;
|
||||
@ -42,7 +42,7 @@
|
||||
box-shadow: 0px 2px 4px rgba(91, 107, 174, .15);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.login .login-form form:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
@ -77,7 +77,7 @@
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
||||
.login .login-form form input {
|
||||
outline: none;
|
||||
width: calc(100% - 30px);
|
||||
@ -120,7 +120,7 @@
|
||||
<div class="col-lg-6 col-lg-offset-3 col-md-12">
|
||||
<img alt="Strapi logo" class="logo" src="https://strapi.io/assets/images/logo_login.png">
|
||||
<h2 class="sub-title">Enter the password to access to the documentation.</h2>
|
||||
<form method="post" action="/documentation/login">
|
||||
<form method="post" action="<%=actionUrl%>">
|
||||
<span class="error">Wrong password...</span>
|
||||
<label>Password</label>
|
||||
<input type="password" name="password" placeholder="•••••••••">
|
||||
@ -131,5 +131,5 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
</body></html>
|
||||
|
||||
@ -111,7 +111,7 @@ module.exports = strapi => {
|
||||
strapi.plugins.graphql.config.playgroundAlways
|
||||
) {
|
||||
serverParams.playground = {
|
||||
endpoint: strapi.plugins.graphql.config.endpoint,
|
||||
endpoint: `${strapi.config.server.url}${strapi.plugins.graphql.config.endpoint}`,
|
||||
shareEnabled: strapi.plugins.graphql.config.shareEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
@ -47,10 +47,7 @@ class PopUpForm extends React.Component {
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
const { values } = nextProps;
|
||||
|
||||
if (
|
||||
get(values, 'enabled') &&
|
||||
get(values, 'enabled') !== get(this.props.values, 'enabled')
|
||||
) {
|
||||
if (get(values, 'enabled') && get(values, 'enabled') !== get(this.props.values, 'enabled')) {
|
||||
this.setState({ enabled: get(values, 'enabled') });
|
||||
}
|
||||
}
|
||||
@ -65,7 +62,7 @@ class PopUpForm extends React.Component {
|
||||
case 'google':
|
||||
return `${strapi.backendURL}/connect/google/callback`;
|
||||
case 'github':
|
||||
return get(this.props.values, 'redirect_uri', '');
|
||||
return `${strapi.backendURL}/connect/github/callback`;
|
||||
case 'microsoft':
|
||||
return `${strapi.backendURL}/connect/microsoft/callback`;
|
||||
case 'twitter':
|
||||
@ -77,17 +74,13 @@ class PopUpForm extends React.Component {
|
||||
default: {
|
||||
const value = get(this.props.values, 'callback', '');
|
||||
|
||||
return startsWith(value, 'http')
|
||||
? value
|
||||
: `${strapi.backendURL}${value}`;
|
||||
return startsWith(value, 'http') ? value : `${strapi.backendURL}${value}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
generateRedirectURL = url => {
|
||||
return startsWith(url, 'https://') ||
|
||||
startsWith(url, 'http://') ||
|
||||
this.state.isEditing
|
||||
return startsWith(url, 'https://') || startsWith(url, 'http://') || this.state.isEditing
|
||||
? url
|
||||
: `${strapi.backendURL}${startsWith(url, '/') ? '' : '/'}${url}`;
|
||||
};
|
||||
@ -113,36 +106,26 @@ class PopUpForm extends React.Component {
|
||||
handleFocus = () => this.setState({ isEditing: true });
|
||||
|
||||
renderForm = () => {
|
||||
const {
|
||||
dataToEdit,
|
||||
didCheckErrors,
|
||||
formErrors,
|
||||
settingType,
|
||||
values,
|
||||
} = this.props;
|
||||
const form = Object.keys(values.options || values || {}).reduce(
|
||||
(acc, current) => {
|
||||
const path =
|
||||
settingType === 'email-templates' ? ['options', current] : [current];
|
||||
const name = settingType === 'email-templates' ? 'options.' : '';
|
||||
const { dataToEdit, didCheckErrors, formErrors, settingType, values } = this.props;
|
||||
const form = Object.keys(values.options || values || {}).reduce((acc, current) => {
|
||||
const path = settingType === 'email-templates' ? ['options', current] : [current];
|
||||
const name = settingType === 'email-templates' ? 'options.' : '';
|
||||
|
||||
if (isObject(get(values, path)) && !isArray(get(values, path))) {
|
||||
return Object.keys(get(values, path, {}))
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(`${name}${current}.${curr}`);
|
||||
if (isObject(get(values, path)) && !isArray(get(values, path))) {
|
||||
return Object.keys(get(values, path, {}))
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(`${name}${current}.${curr}`);
|
||||
|
||||
return acc;
|
||||
}, [])
|
||||
.concat(acc);
|
||||
}
|
||||
if (current !== 'icon' && current !== 'scope') {
|
||||
acc.push(`${name}${current}`);
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
.concat(acc);
|
||||
}
|
||||
if (current !== 'icon' && current !== 'scope') {
|
||||
acc.push(`${name}${current}`);
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (settingType === 'providers') {
|
||||
return (
|
||||
@ -166,11 +149,7 @@ class PopUpForm extends React.Component {
|
||||
autoFocus={key === 0}
|
||||
customBootstrapClass="col-md-12"
|
||||
didCheckErrors={didCheckErrors}
|
||||
errors={get(
|
||||
formErrors,
|
||||
[findIndex(formErrors, ['name', value]), 'errors'],
|
||||
[]
|
||||
)}
|
||||
errors={get(formErrors, [findIndex(formErrors, ['name', value]), 'errors'], [])}
|
||||
key={value}
|
||||
label={{
|
||||
id: `users-permissions.PopUpForm.Providers.${
|
||||
@ -248,9 +227,7 @@ class PopUpForm extends React.Component {
|
||||
placeholder={`users-permissions.PopUpForm.Email.${value}.placeholder`}
|
||||
type={includes(value, 'email') ? 'email' : 'text'}
|
||||
value={get(values, value)}
|
||||
validations={
|
||||
value !== 'options.response_email' ? { required: true } : {}
|
||||
}
|
||||
validations={value !== 'options.response_email' ? { required: true } : {}}
|
||||
/>
|
||||
))}
|
||||
<div className="col-md-6" />
|
||||
@ -278,9 +255,7 @@ class PopUpForm extends React.Component {
|
||||
validations={{ required: true }}
|
||||
value={get(values, value)}
|
||||
inputStyle={
|
||||
!includes(value, 'object')
|
||||
? { height: '16rem', marginBottom: '-0.8rem' }
|
||||
: {}
|
||||
!includes(value, 'object') ? { height: '16rem', marginBottom: '-0.8rem' } : {}
|
||||
}
|
||||
/>
|
||||
))}
|
||||
@ -290,13 +265,7 @@ class PopUpForm extends React.Component {
|
||||
|
||||
render() {
|
||||
const { display } = this.props.values;
|
||||
const {
|
||||
actionType,
|
||||
dataToEdit,
|
||||
isOpen,
|
||||
onSubmit,
|
||||
settingType,
|
||||
} = this.props;
|
||||
const { actionType, dataToEdit, isOpen, onSubmit, settingType } = this.props;
|
||||
|
||||
let header = <span>{dataToEdit}</span>;
|
||||
|
||||
@ -338,11 +307,7 @@ class PopUpForm extends React.Component {
|
||||
onClick={this.context.unsetDataToEdit}
|
||||
isSecondary
|
||||
/>
|
||||
<ButtonModal
|
||||
message="form.button.done"
|
||||
onClick={onSubmit}
|
||||
type="submit"
|
||||
/>
|
||||
<ButtonModal message="form.button.done" onClick={onSubmit} type="submit" />
|
||||
</section>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
|
||||
@ -27,7 +27,7 @@ module.exports = async () => {
|
||||
icon: 'discord',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/discord/callback',
|
||||
callback: `${strapi.config.server.url}/auth/discord/callback`,
|
||||
scope: ['identify', 'email'],
|
||||
},
|
||||
facebook: {
|
||||
@ -35,7 +35,7 @@ module.exports = async () => {
|
||||
icon: 'facebook-square',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/facebook/callback',
|
||||
callback: `${strapi.config.server.url}/auth/facebook/callback`,
|
||||
scope: ['email'],
|
||||
},
|
||||
google: {
|
||||
@ -43,7 +43,7 @@ module.exports = async () => {
|
||||
icon: 'google',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/google/callback',
|
||||
callback: `${strapi.config.server.url}/auth/google/callback`,
|
||||
scope: ['email'],
|
||||
},
|
||||
github: {
|
||||
@ -51,7 +51,7 @@ module.exports = async () => {
|
||||
icon: 'github',
|
||||
key: '',
|
||||
secret: '',
|
||||
redirect_uri: '/auth/github/callback',
|
||||
callback: `${strapi.config.server.url}/auth/github/callback`,
|
||||
scope: ['user', 'user:email'],
|
||||
},
|
||||
microsoft: {
|
||||
@ -59,7 +59,7 @@ module.exports = async () => {
|
||||
icon: 'windows',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/microsoft/callback',
|
||||
callback: `${strapi.config.server.url}/auth/microsoft/callback`,
|
||||
scope: ['user.read'],
|
||||
},
|
||||
twitter: {
|
||||
@ -67,21 +67,21 @@ module.exports = async () => {
|
||||
icon: 'twitter',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/twitter/callback',
|
||||
callback: `${strapi.config.server.url}/auth/twitter/callback`,
|
||||
},
|
||||
instagram: {
|
||||
enabled: false,
|
||||
icon: 'instagram',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/instagram/callback',
|
||||
callback: `${strapi.config.server.url}/auth/instagram/callback`,
|
||||
},
|
||||
vk: {
|
||||
enabled: false,
|
||||
icon: 'vk',
|
||||
key: '',
|
||||
secret: '',
|
||||
callback: '/auth/vk/callback',
|
||||
callback: `${strapi.config.server.url}/auth/vk/callback`,
|
||||
scope: ['email'],
|
||||
},
|
||||
};
|
||||
@ -145,17 +145,12 @@ module.exports = async () => {
|
||||
}
|
||||
|
||||
if (!(await pluginStore.get({ key: 'advanced' }))) {
|
||||
const host = strapi.config.get('server.host');
|
||||
const port = strapi.config.get('server.port');
|
||||
|
||||
const uri = `http://${host}:${port}/admin`;
|
||||
|
||||
const value = {
|
||||
unique_email: true,
|
||||
allow_register: true,
|
||||
email_confirmation: false,
|
||||
email_confirmation_redirection: uri,
|
||||
email_reset_password: uri,
|
||||
email_confirmation_redirection: `${strapi.config.admin.url}/admin`,
|
||||
email_reset_password: `${strapi.config.admin.url}/admin`,
|
||||
default_role: 'authenticated',
|
||||
};
|
||||
|
||||
|
||||
@ -55,9 +55,7 @@ module.exports = {
|
||||
);
|
||||
}
|
||||
|
||||
const query = {
|
||||
provider,
|
||||
};
|
||||
const query = { provider };
|
||||
|
||||
// Check if the provided identifier is an email or not.
|
||||
const isEmail = emailRegExp.test(params.identifier);
|
||||
@ -251,20 +249,17 @@ module.exports = {
|
||||
})
|
||||
.get();
|
||||
|
||||
const [protocol, host] = strapi.config.url.split('://');
|
||||
_.defaultsDeep(grantConfig, { server: { protocol, host } });
|
||||
|
||||
const [requestPath] = ctx.request.url.split('?');
|
||||
const provider =
|
||||
process.platform === 'win32' ? requestPath.split('\\')[2] : requestPath.split('/')[2];
|
||||
const config = grantConfig[provider];
|
||||
|
||||
if (!_.get(config, 'enabled')) {
|
||||
if (!_.get(grantConfig[provider], 'enabled')) {
|
||||
return ctx.badRequest(null, 'This provider is disabled.');
|
||||
}
|
||||
// Ability to pass OAuth callback dynamically
|
||||
grantConfig[provider].callback =
|
||||
ctx.query && ctx.query.callback ? ctx.query.callback : grantConfig[provider].callback;
|
||||
grantConfig[provider].callback = _.get(ctx, 'query.callback') || grantConfig[provider].callback;
|
||||
grantConfig[provider].redirect_uri = `${strapi.config.server.url}/connect/${provider}/callback`;
|
||||
|
||||
return grant(grantConfig)(ctx, next);
|
||||
},
|
||||
|
||||
@ -512,7 +507,7 @@ module.exports = {
|
||||
settings.message = await strapi.plugins[
|
||||
'users-permissions'
|
||||
].services.userspermissions.template(settings.message, {
|
||||
URL: new URL('/auth/email-confirmation', strapi.config.url).toString(),
|
||||
URL: `${strapi.config.server.url}/auth/email-confirmation`,
|
||||
USER: _.omit(user.toJSON ? user.toJSON() : user, [
|
||||
'password',
|
||||
'resetPasswordToken',
|
||||
@ -652,7 +647,7 @@ module.exports = {
|
||||
settings.message = await strapi.plugins['users-permissions'].services.userspermissions.template(
|
||||
settings.message,
|
||||
{
|
||||
URL: new URL('/auth/email-confirmation', strapi.config.url).toString(),
|
||||
URL: `${strapi.config.server.url}/auth/email-confirmation`,
|
||||
USER: _.omit(user.toJSON ? user.toJSON() : user, [
|
||||
'password',
|
||||
'resetPasswordToken',
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"dependencies": {
|
||||
"@purest/providers": "^1.0.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"grant-koa": "^4.6.0",
|
||||
"grant-koa": "^5.0.1",
|
||||
"immutable": "^3.8.2",
|
||||
"jsonwebtoken": "^8.1.0",
|
||||
"koa2-ratelimit": "^0.9.0",
|
||||
|
||||
@ -55,10 +55,7 @@ exports.connect = (provider, query) => {
|
||||
})
|
||||
.get();
|
||||
|
||||
if (
|
||||
_.isEmpty(_.find(users, { provider })) &&
|
||||
!advanced.allow_register
|
||||
) {
|
||||
if (_.isEmpty(_.find(users, { provider })) && !advanced.allow_register) {
|
||||
return resolve([
|
||||
null,
|
||||
[{ messages: [{ id: 'Auth.advanced.allow_register' }] }],
|
||||
@ -95,9 +92,7 @@ exports.connect = (provider, query) => {
|
||||
confirmed: true,
|
||||
});
|
||||
|
||||
const createdUser = await strapi
|
||||
.query('user', 'users-permissions')
|
||||
.create(params);
|
||||
const createdUser = await strapi.query('user', 'users-permissions').create(params);
|
||||
|
||||
return resolve([createdUser, null]);
|
||||
} catch (err) {
|
||||
@ -217,53 +212,41 @@ const getProfile = async (provider, query, callback) => {
|
||||
},
|
||||
});
|
||||
|
||||
request.post(
|
||||
{
|
||||
url: 'https://github.com/login/oauth/access_token',
|
||||
form: {
|
||||
client_id: grant.github.key,
|
||||
client_secret: grant.github.secret,
|
||||
code: access_token,
|
||||
},
|
||||
},
|
||||
(err, res, body) => {
|
||||
github
|
||||
.query()
|
||||
.get('user')
|
||||
.auth(access_token)
|
||||
.request((err, res, userbody) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// This is the public email on the github profile
|
||||
if (userbody.email) {
|
||||
return callback(null, {
|
||||
username: userbody.login,
|
||||
email: userbody.email,
|
||||
});
|
||||
}
|
||||
|
||||
// Get the email with Github's user/emails API
|
||||
github
|
||||
.query()
|
||||
.get('user')
|
||||
.auth(body.split('&')[0].split('=')[1])
|
||||
.request((err, res, userbody) => {
|
||||
.get('user/emails')
|
||||
.auth(access_token)
|
||||
.request((err, res, emailsbody) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// This is the public email on the github profile
|
||||
if (userbody.email) {
|
||||
return callback(null, {
|
||||
username: userbody.login,
|
||||
email: userbody.email,
|
||||
});
|
||||
}
|
||||
|
||||
// Get the email with Github's user/emails API
|
||||
github
|
||||
.query()
|
||||
.get('user/emails')
|
||||
.auth(body.split('&')[0].split('=')[1])
|
||||
.request((err, res, emailsbody) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
return callback(null, {
|
||||
username: userbody.login,
|
||||
email: Array.isArray(emailsbody)
|
||||
? emailsbody.find(email => email.primary === true).email
|
||||
: null,
|
||||
});
|
||||
});
|
||||
return callback(null, {
|
||||
username: userbody.login,
|
||||
email: Array.isArray(emailsbody)
|
||||
? emailsbody.find(email => email.primary === true).email
|
||||
: null,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'microsoft': {
|
||||
|
||||
62
packages/strapi-utils/lib/config.js
Normal file
62
packages/strapi-utils/lib/config.js
Normal file
@ -0,0 +1,62 @@
|
||||
const _ = require('lodash');
|
||||
const { getCommonBeginning } = require('./stringFormatting');
|
||||
|
||||
const getConfigUrls = (serverConfig, forAdminBuild = false) => {
|
||||
// Defines serverUrl value
|
||||
let serverUrl = _.get(serverConfig, 'url', '');
|
||||
serverUrl = _.trim(serverUrl, '/ ');
|
||||
if (typeof serverUrl !== 'string') {
|
||||
throw new Error('Invalid server url config. Make sure the url is a string.');
|
||||
}
|
||||
if (serverUrl.startsWith('http')) {
|
||||
try {
|
||||
serverUrl = _.trim(new URL(serverConfig.url).toString(), '/');
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid server url config. Make sure the url defined in server.js is valid.'
|
||||
);
|
||||
}
|
||||
} else if (serverUrl !== '') {
|
||||
serverUrl = `/${serverUrl}`;
|
||||
}
|
||||
|
||||
// Defines adminUrl value
|
||||
let adminUrl = _.get(serverConfig, 'admin.url', '/admin');
|
||||
adminUrl = _.trim(adminUrl, '/ ');
|
||||
if (typeof adminUrl !== 'string') {
|
||||
throw new Error('Invalid admin url config. Make sure the url is a non-empty string.');
|
||||
}
|
||||
if (adminUrl.startsWith('http')) {
|
||||
try {
|
||||
adminUrl = _.trim(new URL(adminUrl).toString(), '/');
|
||||
} catch (e) {
|
||||
throw new Error('Invalid admin url config. Make sure the url defined in server.js is valid.');
|
||||
}
|
||||
} else {
|
||||
adminUrl = `${serverUrl}/${adminUrl}`;
|
||||
}
|
||||
|
||||
// Defines adminPath value
|
||||
let adminPath = adminUrl;
|
||||
if (
|
||||
serverUrl.startsWith('http') &&
|
||||
adminUrl.startsWith('http') &&
|
||||
new URL(adminUrl).origin === new URL(serverUrl).origin &&
|
||||
!forAdminBuild
|
||||
) {
|
||||
adminPath = adminUrl.replace(getCommonBeginning(serverUrl, adminUrl), '');
|
||||
adminPath = `/${_.trim(adminPath, '/')}`;
|
||||
} else if (adminUrl.startsWith('http')) {
|
||||
adminPath = new URL(adminUrl).pathname;
|
||||
}
|
||||
|
||||
return {
|
||||
serverUrl,
|
||||
adminUrl,
|
||||
adminPath,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getConfigUrls,
|
||||
};
|
||||
@ -15,7 +15,13 @@ const models = require('./models');
|
||||
const policy = require('./policy');
|
||||
const templateConfiguration = require('./templateConfiguration');
|
||||
const { yup, formatYupErrors } = require('./validators');
|
||||
const { nameToSlug, nameToCollectionName, escapeQuery } = require('./stringFormatting');
|
||||
const {
|
||||
nameToSlug,
|
||||
nameToCollectionName,
|
||||
getCommonBeginning,
|
||||
escapeQuery,
|
||||
} = require('./stringFormatting');
|
||||
const { getConfigUrls } = require('./config');
|
||||
|
||||
module.exports = {
|
||||
yup,
|
||||
@ -32,5 +38,7 @@ module.exports = {
|
||||
parseType,
|
||||
nameToSlug,
|
||||
nameToCollectionName,
|
||||
getCommonBeginning,
|
||||
getConfigUrls,
|
||||
escapeQuery,
|
||||
};
|
||||
|
||||
@ -6,6 +6,20 @@ const nameToSlug = name => slugify(name, { separator: '-' });
|
||||
|
||||
const nameToCollectionName = name => slugify(name, { separator: '_' });
|
||||
|
||||
const getCommonBeginning = (str1 = '', str2 = '') => {
|
||||
let common = '';
|
||||
let index = 0;
|
||||
while (index < str1.length && index < str2.length) {
|
||||
if (str1[index] === str2[index]) {
|
||||
common += str1[index];
|
||||
index += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return common;
|
||||
};
|
||||
|
||||
const escapeQuery = (query, charsToEscape, escapeChar = '\\') => {
|
||||
return query
|
||||
.split('')
|
||||
@ -21,5 +35,6 @@ const escapeQuery = (query, charsToEscape, escapeChar = '\\') => {
|
||||
module.exports = {
|
||||
nameToSlug,
|
||||
nameToCollectionName,
|
||||
getCommonBeginning,
|
||||
escapeQuery,
|
||||
};
|
||||
|
||||
@ -97,6 +97,14 @@ class Strapi {
|
||||
logFirstStartupMessage() {
|
||||
this.logStats();
|
||||
|
||||
let hostname = strapi.config.host;
|
||||
if (
|
||||
strapi.config.environment === 'development' &&
|
||||
['127.0.0.1', '0.0.0.0'].includes(strapi.config.host)
|
||||
) {
|
||||
hostname = 'localhost';
|
||||
}
|
||||
|
||||
console.log(chalk.bold('One more thing...'));
|
||||
console.log(
|
||||
chalk.grey('Create your first administrator 💻 by going to the administration panel at:')
|
||||
@ -104,7 +112,13 @@ class Strapi {
|
||||
console.log();
|
||||
|
||||
const addressTable = new CLITable();
|
||||
addressTable.push([chalk.bold(this.config.admin.url)]);
|
||||
if (this.config.admin.url.startsWith('http')) {
|
||||
addressTable.push([chalk.bold(this.config.admin.url)]);
|
||||
} else {
|
||||
addressTable.push([
|
||||
chalk.bold(`http://${hostname}:${strapi.config.port}${this.config.admin.url}`),
|
||||
]);
|
||||
}
|
||||
console.log(`${addressTable.toString()}`);
|
||||
console.log();
|
||||
}
|
||||
@ -112,16 +126,32 @@ class Strapi {
|
||||
logStartupMessage() {
|
||||
this.logStats();
|
||||
|
||||
let hostname = strapi.config.host;
|
||||
if (
|
||||
strapi.config.environment === 'development' &&
|
||||
['127.0.0.1', '0.0.0.0'].includes(strapi.config.host)
|
||||
) {
|
||||
hostname = 'localhost';
|
||||
}
|
||||
|
||||
console.log(chalk.bold('Welcome back!'));
|
||||
|
||||
if (this.config.serveAdminPanel === true) {
|
||||
console.log(chalk.grey('To manage your project 🚀, go to the administration panel at:'));
|
||||
console.log(chalk.bold(this.config.admin.url));
|
||||
if (this.config.admin.url.startsWith('http')) {
|
||||
console.log(chalk.bold(this.config.admin.url));
|
||||
} else {
|
||||
console.log(chalk.bold(`http://${hostname}:${strapi.config.port}${this.config.admin.url}`));
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
console.log(chalk.grey('To access the server ⚡️, go to:'));
|
||||
console.log(chalk.bold(this.config.url));
|
||||
if (this.config.admin.url.startsWith('http')) {
|
||||
console.log(chalk.bold(this.config.server.url));
|
||||
} else {
|
||||
console.log(chalk.bold(`http://${hostname}:${strapi.config.port}${this.config.server.url}`));
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
const { green } = require('chalk');
|
||||
// eslint-disable-next-line node/no-extraneous-require
|
||||
const strapiAdmin = require('strapi-admin');
|
||||
const { getConfigUrls } = require('strapi-utils');
|
||||
|
||||
const loadConfiguration = require('../core/app-configuration');
|
||||
const addSlash = require('../utils/addSlash');
|
||||
/**
|
||||
@ -12,8 +14,7 @@ module.exports = async ({ clean, optimization }) => {
|
||||
const dir = process.cwd();
|
||||
const config = loadConfiguration(dir);
|
||||
|
||||
const adminPath = config.get('server.admin.path', '/admin');
|
||||
const adminBackend = config.get('server.admin.build.backend', '/');
|
||||
const { serverUrl, adminPath } = getConfigUrls(config.get('server'), true);
|
||||
|
||||
console.log(`Building your admin UI with ${green(config.environment)} configuration ...`);
|
||||
|
||||
@ -28,7 +29,7 @@ module.exports = async ({ clean, optimization }) => {
|
||||
env: 'production',
|
||||
optimize: optimization,
|
||||
options: {
|
||||
backend: adminBackend,
|
||||
backend: serverUrl,
|
||||
publicPath: addSlash(adminPath),
|
||||
},
|
||||
})
|
||||
|
||||
@ -21,7 +21,7 @@ module.exports = async (plugins, { deleteFiles }) => {
|
||||
const loader = ora();
|
||||
const dir = process.cwd();
|
||||
|
||||
const pluginArgs = plugins.map((name) => `strapi-plugin-${name}`);
|
||||
const pluginArgs = plugins.map(name => `strapi-plugin-${name}`);
|
||||
|
||||
try {
|
||||
// verify should rebuild before removing the pacakge
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// eslint-disable-next-line node/no-extraneous-require
|
||||
const strapiAdmin = require('strapi-admin');
|
||||
const { getConfigUrls } = require('strapi-utils');
|
||||
|
||||
const loadConfiguration = require('../core/app-configuration');
|
||||
const addSlash = require('../utils/addSlash');
|
||||
@ -9,14 +10,10 @@ module.exports = async function() {
|
||||
|
||||
const config = loadConfiguration(dir);
|
||||
|
||||
const port = config.get('server.port', 1337);
|
||||
const host = config.get('server.host', 'localhost');
|
||||
const { serverUrl, adminPath } = getConfigUrls(config.get('server'), true);
|
||||
|
||||
const adminPort = config.get('server.admin.port', 8000);
|
||||
const adminHost = config.get('server.admin.host', 'localhost');
|
||||
|
||||
const adminBackend = config.get('server.admin.build.backend', `http://${host}:${port}`);
|
||||
const adminPath = config.get('server.admin.path', '/admin');
|
||||
const adminWatchIgnoreFiles = config.get('server.admin.watchIgnoreFiles', []);
|
||||
|
||||
strapiAdmin.watchAdmin({
|
||||
@ -24,7 +21,7 @@ module.exports = async function() {
|
||||
port: adminPort,
|
||||
host: adminHost,
|
||||
options: {
|
||||
backend: adminBackend,
|
||||
backend: serverUrl,
|
||||
publicPath: addSlash(adminPath),
|
||||
watchIgnoreFiles: adminWatchIgnoreFiles,
|
||||
},
|
||||
|
||||
@ -37,7 +37,6 @@ const defaultConfig = {
|
||||
server: {
|
||||
host: process.env.HOST || os.hostname() || 'localhost',
|
||||
port: process.env.PORT || 1337,
|
||||
proxy: { enabled: false },
|
||||
cron: { enabled: false },
|
||||
admin: { autoOpen: false },
|
||||
},
|
||||
|
||||
33
packages/strapi/lib/core/bootstrap.js
vendored
33
packages/strapi/lib/core/bootstrap.js
vendored
@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const { getConfigUrls } = require('strapi-utils');
|
||||
|
||||
const { createCoreApi } = require('../core-api');
|
||||
const getURLFromSegments = require('../utils/url-from-segments');
|
||||
|
||||
const getKind = obj => obj.kind || 'collectionType';
|
||||
|
||||
@ -182,30 +182,15 @@ module.exports = function(strapi) {
|
||||
}, {});
|
||||
|
||||
// default settings
|
||||
const port = strapi.config.get('server.port');
|
||||
const host = strapi.config.get('server.host');
|
||||
strapi.config.port = strapi.config.get('server.port') || strapi.config.port;
|
||||
strapi.config.host = strapi.config.get('server.host') || strapi.config.host;
|
||||
|
||||
let hostname = host;
|
||||
if (strapi.config.environment === 'development' && ['127.0.0.1', '0.0.0.0'].includes(host)) {
|
||||
hostname = 'localhost';
|
||||
}
|
||||
const { serverUrl, adminUrl, adminPath } = getConfigUrls(strapi.config.get('server'));
|
||||
|
||||
// proxy settings
|
||||
const proxy = strapi.config.get('server.proxy', {});
|
||||
|
||||
// check if proxy is enabled and construct url
|
||||
strapi.config.url = proxy.enabled
|
||||
? getURLFromSegments({
|
||||
hostname: proxy.host,
|
||||
port: proxy.port,
|
||||
ssl: proxy.ssl,
|
||||
})
|
||||
: getURLFromSegments({
|
||||
hostname,
|
||||
port,
|
||||
});
|
||||
|
||||
const adminPath = strapi.config.get('server.admin.path', 'admin');
|
||||
strapi.config.server = strapi.config.server || {};
|
||||
strapi.config.server.url = serverUrl;
|
||||
strapi.config.admin.url = adminUrl;
|
||||
strapi.config.admin.path = adminPath;
|
||||
|
||||
// check if we should serve admin panel
|
||||
const shouldServeAdmin = strapi.config.get(
|
||||
@ -216,6 +201,4 @@ module.exports = function(strapi) {
|
||||
if (!shouldServeAdmin) {
|
||||
strapi.config.serveAdminPanel = false;
|
||||
}
|
||||
|
||||
strapi.config.admin.url = new URL(adminPath, strapi.config.url).toString();
|
||||
};
|
||||
|
||||
@ -74,12 +74,10 @@ module.exports = strapi => {
|
||||
|
||||
if (!strapi.config.serveAdminPanel) return;
|
||||
|
||||
const basename = strapi.config.get('server.admin.path', '/admin');
|
||||
const buildDir = path.resolve(strapi.dir, 'build');
|
||||
|
||||
// Serve admin assets.
|
||||
strapi.router.get(
|
||||
`${basename}/*`,
|
||||
`${strapi.config.admin.path}/*`,
|
||||
async (ctx, next) => {
|
||||
ctx.url = path.basename(ctx.url);
|
||||
await next();
|
||||
@ -91,7 +89,7 @@ module.exports = strapi => {
|
||||
})
|
||||
);
|
||||
|
||||
strapi.router.get(`${basename}*`, ctx => {
|
||||
strapi.router.get(`${strapi.config.admin.path}*`, ctx => {
|
||||
ctx.type = 'html';
|
||||
ctx.body = fs.createReadStream(path.join(buildDir + '/index.html'));
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
module.exports = path => {
|
||||
if (typeof path !== 'string') throw new Error('admin.path must be a string');
|
||||
if (typeof path !== 'string') throw new Error('admin.url must be a string');
|
||||
if (path === '' || path === '/') return '/';
|
||||
|
||||
if (path[0] != '/') path = '/' + path;
|
||||
|
||||
@ -49,11 +49,7 @@ function executeNodeScript(scriptPath, url) {
|
||||
child.on('close', code => {
|
||||
if (code !== 0) {
|
||||
console.log();
|
||||
console.log(
|
||||
chalk.red(
|
||||
'The script specified as BROWSER environment variable failed.'
|
||||
)
|
||||
);
|
||||
console.log(chalk.red('The script specified as BROWSER environment variable failed.'));
|
||||
console.log(`${chalk.cyan(scriptPath)} exited with code ${code}.`);
|
||||
console.log();
|
||||
return;
|
||||
@ -68,21 +64,17 @@ function startBrowserProcess(browser, url) {
|
||||
// Chrome with AppleScript. This lets us reuse an
|
||||
// existing tab when possible instead of creating a new one.
|
||||
const shouldTryOpenChromeWithAppleScript =
|
||||
process.platform === 'darwin' &&
|
||||
(typeof browser !== 'string' || browser === OSX_CHROME);
|
||||
process.platform === 'darwin' && (typeof browser !== 'string' || browser === OSX_CHROME);
|
||||
|
||||
if (shouldTryOpenChromeWithAppleScript) {
|
||||
try {
|
||||
// Try our best to reuse existing tab
|
||||
// on OS X Google Chrome with AppleScript
|
||||
execSync('ps cax | grep "Google Chrome"');
|
||||
execSync(
|
||||
`osascript resources/openChrome.applescript "${encodeURI(url)}"`,
|
||||
{
|
||||
cwd: __dirname,
|
||||
stdio: 'ignore',
|
||||
}
|
||||
);
|
||||
execSync(`osascript resources/openChrome.applescript "${encodeURI(url)}"`, {
|
||||
cwd: __dirname,
|
||||
stdio: 'ignore',
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
strapi.log.error('Failed to open Google Chrome with AppleScript');
|
||||
@ -120,9 +112,7 @@ async function pingDashboard(url, multipleTime = false) {
|
||||
|
||||
// Only display once.
|
||||
if (!multipleTime) {
|
||||
this.log.warn(
|
||||
`⚠️ The admin panel is unavailable... Impossible to open it in the browser.`
|
||||
);
|
||||
this.log.warn(`⚠️ The admin panel is unavailable... Impossible to open it in the browser.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,7 +122,10 @@ async function pingDashboard(url, multipleTime = false) {
|
||||
* true if it opened a browser or ran a node.js script, otherwise false.
|
||||
*/
|
||||
async function openBrowser() {
|
||||
const url = this.config.admin.url;
|
||||
let url = this.config.admin.url;
|
||||
if (!url.startsWith('http')) {
|
||||
url = `http://${strapi.config.host}:${strapi.config.port}${this.config.admin.url}`;
|
||||
}
|
||||
|
||||
// Ping the dashboard to ensure it's available.
|
||||
await pingDashboard.call(this, url);
|
||||
|
||||
62
yarn.lock
62
yarn.lock
@ -8842,21 +8842,21 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
|
||||
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
|
||||
|
||||
grant-koa@^4.6.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/grant-koa/-/grant-koa-4.7.0.tgz#4c7b2e23afe492988cd6a5874d5592f6a813ca50"
|
||||
integrity sha512-dvu6FgtFOXncHM3faiJKehMN+4cRajb68E0FtmT5uMUUHZ4LZifv6ihANH9l0pvl0t+7UjEIosMrhnE73bhjpQ==
|
||||
grant-koa@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/grant-koa/-/grant-koa-5.0.1.tgz#6606b762d999855ae3bc3b2ecc222cf21154324f"
|
||||
integrity sha512-/vemHxSbyw8PNB04zqMMSSOiVhjercOZj1LL0AFIJGFZvdzBDiwmQEX2ioOmeaOBCLVCAdhQ0EfkEaln540Agg==
|
||||
dependencies:
|
||||
grant "4.7.0"
|
||||
grant "5.0.1"
|
||||
|
||||
grant@4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/grant/-/grant-4.7.0.tgz#ab879a38ced7860df668db6c66012aa02402f49b"
|
||||
integrity sha512-QGPjCYDrBnb/OIiTRxbK3TnNOE6Ycgfc/GcgPzI4vyNIr+b7yisEexYp7VM74zj6bxr+mDTzfGONRLzzsVPJIA==
|
||||
grant@5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/grant/-/grant-5.0.1.tgz#86d8c970fc54e860b5ad97a6544d3c7bc87c2fc2"
|
||||
integrity sha512-ZYlnlzMA9f9SielWBDSwGZ34XcB2BL8wktDE5T2OcM13T7GFirjLWI0oasqrigPcLetazRbCUIBqqsy2Mvl8Zw==
|
||||
dependencies:
|
||||
qs "^6.9.1"
|
||||
request-compose "^1.2.1"
|
||||
request-oauth "0.0.3"
|
||||
qs "^6.9.3"
|
||||
request-compose "^2.0.0"
|
||||
request-oauth "^1.0.0"
|
||||
|
||||
graphlib@^2.1.1, graphlib@^2.1.5:
|
||||
version "2.1.8"
|
||||
@ -13104,16 +13104,16 @@ nwsapi@^2.0.7:
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
|
||||
|
||||
oauth-sign@^0.8.2, oauth-sign@~0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
||||
integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
|
||||
|
||||
oauth-sign@~0.9.0:
|
||||
oauth-sign@^0.9.0, oauth-sign@~0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
oauth-sign@~0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
||||
integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
|
||||
|
||||
object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
@ -14836,7 +14836,7 @@ qs@6.7.0:
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
|
||||
|
||||
qs@^6.4.0, qs@^6.5.1, qs@^6.5.2, qs@^6.9.1:
|
||||
qs@^6.4.0, qs@^6.5.2:
|
||||
version "6.9.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
|
||||
integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==
|
||||
@ -15774,19 +15774,19 @@ reportback@^2.0.2:
|
||||
captains-log "^2.0.2"
|
||||
switchback "^2.0.1"
|
||||
|
||||
request-compose@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/request-compose/-/request-compose-1.2.2.tgz#9bd2ec8c8f52d154cff3302f637d81b73b371d49"
|
||||
integrity sha512-aXA7l8fGSp4ZUeM/7pcMh3rvor7vKMptT7kPnTQfbzLOW4wy/hJgMzVhz9l2YZYgsbVj4ZgAc9JMI02V4nZgsA==
|
||||
request-compose@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/request-compose/-/request-compose-2.0.0.tgz#064121f8c52087d33c6b487eb14f32bc4af99548"
|
||||
integrity sha512-+R9ka4bd3PH7A6B4iHn5SwAesGOUyPP2uCO6YJg6Ct/odLO0h9a7eWDPLXF1fws2us8sboGY0TtBl1wTpx60OA==
|
||||
|
||||
request-oauth@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/request-oauth/-/request-oauth-0.0.3.tgz#b3ea1ff857b9add3b0d49e42993a88e256d791ab"
|
||||
integrity sha512-q7WdJlpIcPaIDac0FZSy/yH37FO3UkUuPDIsiLALiLjuC6vzvuKIU14YIC3Lm0wtQRXS9GqvSo/fCYj8n75xSw==
|
||||
request-oauth@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/request-oauth/-/request-oauth-1.0.0.tgz#c8ebe047fb4ff4d5aa4ddb33e98b9ac74c625674"
|
||||
integrity sha512-wsDzIq1Qu2itLDlcpFph8xh5Q+FVyUj4os5zdQTlZL/JvZYF/qOyaawVPsxxhDG4QwCB3tzSFprj6dkjqR+e8w==
|
||||
dependencies:
|
||||
oauth-sign "^0.8.2"
|
||||
qs "^6.5.1"
|
||||
uuid "^3.2.1"
|
||||
oauth-sign "^0.9.0"
|
||||
qs "^6.9.3"
|
||||
uuid "^3.4.0"
|
||||
|
||||
request-progress@0.3.1:
|
||||
version "0.3.1"
|
||||
@ -18692,7 +18692,7 @@ uuid@3.3.2:
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
|
||||
|
||||
uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2, uuid@^3.3.3:
|
||||
uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user