Ghost/ghost/admin/app/services/frontend.js
Kevin Ansfield 8b007802d4 🐛 Fixed login problems in Safari on private sites that have front-end/admin on different domains
no issue

- if the automatic private site login fails during post-auth setup, don't fully error because that will block Admin from loading properly
- the automatic login is a nice-to-have and making it look like it worked won't break anything that wouldn't already be broken when the browser is blocking x-domain requests
2021-11-09 15:38:58 +00:00

64 lines
2.1 KiB
JavaScript

import Service from '@ember/service';
import fetch from 'fetch';
import validator from 'validator';
import {inject as service} from '@ember/service';
export default class FrontendService extends Service {
@service settings;
@service config;
@service ajax;
_hasLoggedIn = false;
_lastPassword = null;
get hasPasswordChanged() {
return this._lastPassword !== this.settings.get('password');
}
getUrl(path) {
const siteUrl = new URL(this.config.get('blogUrl'));
const subdir = siteUrl.pathname.endsWith('/') ? siteUrl.pathname : `${siteUrl.pathname}/`;
const fullPath = `${subdir}${path.replace(/^\//, '')}`;
return `${siteUrl.origin}${fullPath}`;
}
async loginIfNeeded() {
if (this.settings.get('isPrivate') && (this.hasPasswordChanged || !this._hasLoggedIn)) {
const privateLoginUrl = this.getUrl('/private/?r=%2F');
this._lastPassword = this.settings.get('password');
return fetch(privateLoginUrl, {
method: 'POST',
mode: 'cors',
redirect: 'manual',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `password=${this._lastPassword}`
}).then(() => {
this._hasLoggedIn = true;
}).catch((e) => {
// Safari will error when x-site tracking is prevented and frontend/admin are separate
// we don't want to break anything else in that case so make it look like it succeeded
console.error(e); // eslint-disable-line
return true;
});
}
}
async fetch(urlOrPath, options) {
await this.loginIfNeeded();
let frontendUrl = urlOrPath;
if (!validator.isURL(urlOrPath)) {
frontendUrl = this.getUrl(urlOrPath);
}
return fetch(frontendUrl, {
mode: 'cors',
credentials: 'include',
...options
});
}
}