Final set of CSRFP -> CSRF renames, use headers instead of POST fields and build CSRF handling into the XHR wrapper.
This commit is contained in:
parent
2e9adf0d06
commit
bc2d7a08d0
12 changed files with 157 additions and 191 deletions
24
assets/misuzu.js/csrf.js
Normal file
24
assets/misuzu.js/csrf.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include utility.js
|
||||||
|
|
||||||
|
const MszCSRF = (() => {
|
||||||
|
let elem;
|
||||||
|
const getElement = () => {
|
||||||
|
if(elem === undefined)
|
||||||
|
elem = $q('meta[name="csrf-token"]');
|
||||||
|
return elem;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
get token() {
|
||||||
|
return getElement()?.content ?? '';
|
||||||
|
},
|
||||||
|
set token(token) {
|
||||||
|
if(typeof token !== 'string')
|
||||||
|
throw 'token must be a string';
|
||||||
|
|
||||||
|
const elem = getElement();
|
||||||
|
if(elem instanceof HTMLMetaElement)
|
||||||
|
elem.content = token;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})();
|
|
@ -1,40 +0,0 @@
|
||||||
#include utility.js
|
|
||||||
|
|
||||||
const MszCSRFP = (() => {
|
|
||||||
let elem;
|
|
||||||
const getElement = () => {
|
|
||||||
if(elem === undefined)
|
|
||||||
elem = $q('meta[name="csrfp-token"]');
|
|
||||||
return elem;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getToken = () => {
|
|
||||||
const elem = getElement();
|
|
||||||
return typeof elem.content === 'string' ? elem.content : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const setToken = token => {
|
|
||||||
if(typeof token !== 'string')
|
|
||||||
throw 'token must be a string';
|
|
||||||
|
|
||||||
const elem = getElement();
|
|
||||||
if(typeof elem.content === 'string')
|
|
||||||
elem.content = token;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
getToken: getToken,
|
|
||||||
setToken: setToken,
|
|
||||||
setFromHeaders: result => {
|
|
||||||
if(typeof result.headers !== 'function')
|
|
||||||
throw 'result.headers is not a function';
|
|
||||||
|
|
||||||
const headers = result.headers();
|
|
||||||
if(!(headers instanceof Map))
|
|
||||||
throw 'result of result.headers does not return a map';
|
|
||||||
|
|
||||||
if(headers.has('x-csrfp-token'))
|
|
||||||
setToken(headers.get('x-csrfp-token'));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
})();
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include utility.js
|
#include xhr.js
|
||||||
|
|
||||||
const MszUiharu = function(apiUrl) {
|
const MszUiharu = function(apiUrl) {
|
||||||
const maxBatchSize = 4;
|
const maxBatchSize = 4;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include msgbox.jsx
|
#include msgbox.jsx
|
||||||
#include parsing.js
|
#include parsing.js
|
||||||
#include utility.js
|
#include utility.js
|
||||||
|
#include xhr.js
|
||||||
#include ext/eeprom.js
|
#include ext/eeprom.js
|
||||||
|
|
||||||
let MszForumEditorAllowClose = false;
|
let MszForumEditorAllowClose = false;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include utility.js
|
#include utility.js
|
||||||
|
#include xhr.js
|
||||||
#include embed/embed.js
|
#include embed/embed.js
|
||||||
#include events/christmas2019.js
|
#include events/christmas2019.js
|
||||||
#include events/events.js
|
#include events/events.js
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include csrfp.js
|
|
||||||
#include msgbox.jsx
|
#include msgbox.jsx
|
||||||
#include utility.js
|
#include utility.js
|
||||||
|
#include xhr.js
|
||||||
#include messages/actbtn.js
|
#include messages/actbtn.js
|
||||||
#include messages/list.js
|
#include messages/list.js
|
||||||
#include messages/recipient.js
|
#include messages/recipient.js
|
||||||
|
@ -33,7 +33,6 @@ const MszMessages = () => {
|
||||||
|
|
||||||
const msgsCreate = async (title, text, parser, draft, recipient, replyTo) => {
|
const msgsCreate = async (title, text, parser, draft, recipient, replyTo) => {
|
||||||
const formData = new FormData;
|
const formData = new FormData;
|
||||||
formData.append('_csrfp', MszCSRFP.getToken());
|
|
||||||
formData.append('title', title);
|
formData.append('title', title);
|
||||||
formData.append('body', text);
|
formData.append('body', text);
|
||||||
formData.append('parser', parser);
|
formData.append('parser', parser);
|
||||||
|
@ -41,10 +40,7 @@ const MszMessages = () => {
|
||||||
formData.append('recipient', recipient);
|
formData.append('recipient', recipient);
|
||||||
formData.append('reply', replyTo);
|
formData.append('reply', replyTo);
|
||||||
|
|
||||||
const result = await $x.post('/messages/create', { type: 'json' }, formData);
|
const result = await $x.post('/messages/create', { type: 'json', csrf: true }, formData);
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
if(body.error !== undefined)
|
if(body.error !== undefined)
|
||||||
throw body.error;
|
throw body.error;
|
||||||
|
@ -54,16 +50,12 @@ const MszMessages = () => {
|
||||||
|
|
||||||
const msgsUpdate = async (messageId, title, text, parser, draft) => {
|
const msgsUpdate = async (messageId, title, text, parser, draft) => {
|
||||||
const formData = new FormData;
|
const formData = new FormData;
|
||||||
formData.append('_csrfp', MszCSRFP.getToken());
|
|
||||||
formData.append('title', title);
|
formData.append('title', title);
|
||||||
formData.append('body', text);
|
formData.append('body', text);
|
||||||
formData.append('parser', parser);
|
formData.append('parser', parser);
|
||||||
formData.append('draft', draft);
|
formData.append('draft', draft);
|
||||||
|
|
||||||
const result = await $x.post(`/messages/${encodeURIComponent(messageId)}`, { type: 'json' }, formData);
|
const result = await $x.post(`/messages/${encodeURIComponent(messageId)}`, { type: 'json', csrf: true }, formData);
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
if(body.error !== undefined)
|
if(body.error !== undefined)
|
||||||
throw body.error;
|
throw body.error;
|
||||||
|
@ -72,14 +64,10 @@ const MszMessages = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const msgsMark = async (msgs, state) => {
|
const msgsMark = async (msgs, state) => {
|
||||||
const result = await $x.post('/messages/mark', { type: 'json' }, {
|
const result = await $x.post('/messages/mark', { type: 'json', csrf: true }, {
|
||||||
_csrfp: MszCSRFP.getToken(),
|
|
||||||
type: state,
|
type: state,
|
||||||
messages: msgs.map(extractMsgIds).join(','),
|
messages: msgs.map(extractMsgIds).join(','),
|
||||||
});
|
});
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
if(body.error !== undefined)
|
if(body.error !== undefined)
|
||||||
throw body.error;
|
throw body.error;
|
||||||
|
@ -88,13 +76,9 @@ const MszMessages = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const msgsDelete = async msgs => {
|
const msgsDelete = async msgs => {
|
||||||
const result = await $x.post('/messages/delete', { type: 'json' }, {
|
const result = await $x.post('/messages/delete', { type: 'json', csrf: true }, {
|
||||||
_csrfp: MszCSRFP.getToken(),
|
|
||||||
messages: msgs.map(extractMsgIds).join(','),
|
messages: msgs.map(extractMsgIds).join(','),
|
||||||
});
|
});
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
if(body.error !== undefined)
|
if(body.error !== undefined)
|
||||||
throw body.error;
|
throw body.error;
|
||||||
|
@ -103,13 +87,9 @@ const MszMessages = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const msgsRestore = async msgs => {
|
const msgsRestore = async msgs => {
|
||||||
const result = await $x.post('/messages/restore', { type: 'json' }, {
|
const result = await $x.post('/messages/restore', { type: 'json', csrf: true }, {
|
||||||
_csrfp: MszCSRFP.getToken(),
|
|
||||||
messages: msgs.map(extractMsgIds).join(','),
|
messages: msgs.map(extractMsgIds).join(','),
|
||||||
});
|
});
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
if(body.error !== undefined)
|
if(body.error !== undefined)
|
||||||
throw body.error;
|
throw body.error;
|
||||||
|
@ -118,13 +98,10 @@ const MszMessages = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const msgsNuke = async msgs => {
|
const msgsNuke = async msgs => {
|
||||||
const result = await $x.post('/messages/nuke', { type: 'json' }, {
|
const result = await $x.post('/messages/nuke', { type: 'json', csrf: true }, {
|
||||||
_csrfp: MszCSRFP.getToken(),
|
|
||||||
messages: msgs.map(extractMsgIds).join(','),
|
messages: msgs.map(extractMsgIds).join(','),
|
||||||
});
|
});
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
if(body.error !== undefined)
|
if(body.error !== undefined)
|
||||||
throw body.error;
|
throw body.error;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include csrfp.js
|
#include xhr.js
|
||||||
#include utility.js
|
|
||||||
|
|
||||||
const MszMessagesRecipient = function(element) {
|
const MszMessagesRecipient = function(element) {
|
||||||
if(!(element instanceof Element))
|
if(!(element instanceof Element))
|
||||||
|
@ -10,13 +9,9 @@ const MszMessagesRecipient = function(element) {
|
||||||
|
|
||||||
let updateHandler = undefined;
|
let updateHandler = undefined;
|
||||||
const update = async () => {
|
const update = async () => {
|
||||||
const result = await $x.post(element.dataset.msgLookup, { type: 'json' }, {
|
const result = await $x.post(element.dataset.msgLookup, { type: 'json', csrf: true }, {
|
||||||
_csrfp: MszCSRFP.getToken(),
|
|
||||||
name: nameInput.value,
|
name: nameInput.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
MszCSRFP.setFromHeaders(result);
|
|
||||||
|
|
||||||
const body = result.body();
|
const body = result.body();
|
||||||
|
|
||||||
if(updateHandler !== undefined)
|
if(updateHandler !== undefined)
|
||||||
|
|
|
@ -162,114 +162,6 @@ const $as = function(array) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const $x = (function() {
|
|
||||||
const send = function(method, url, options, body) {
|
|
||||||
if(options === undefined)
|
|
||||||
options = {};
|
|
||||||
else if(typeof options !== 'object')
|
|
||||||
throw 'options must be undefined or an object';
|
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest;
|
|
||||||
const requestHeaders = new Map;
|
|
||||||
|
|
||||||
if('headers' in options && typeof options.headers === 'object')
|
|
||||||
for(const name in options.headers)
|
|
||||||
if(options.headers.hasOwnProperty(name))
|
|
||||||
requestHeaders.set(name.toLowerCase(), options.headers[name]);
|
|
||||||
|
|
||||||
if(typeof options.download === 'function') {
|
|
||||||
xhr.onloadstart = ev => options.download(ev);
|
|
||||||
xhr.onprogress = ev => options.download(ev);
|
|
||||||
xhr.onloadend = ev => options.download(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof options.upload === 'function') {
|
|
||||||
xhr.upload.onloadstart = ev => options.upload(ev);
|
|
||||||
xhr.upload.onprogress = ev => options.upload(ev);
|
|
||||||
xhr.upload.onloadend = ev => options.upload(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(options.authed)
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
|
|
||||||
if(typeof options.timeout === 'number')
|
|
||||||
xhr.timeout = options.timeout;
|
|
||||||
|
|
||||||
if(typeof options.type === 'string')
|
|
||||||
xhr.responseType = options.type;
|
|
||||||
|
|
||||||
if(typeof options.abort === 'function')
|
|
||||||
options.abort(() => xhr.abort());
|
|
||||||
|
|
||||||
if(typeof options.xhr === 'function')
|
|
||||||
options.xhr(() => xhr);
|
|
||||||
|
|
||||||
if(typeof body === 'object') {
|
|
||||||
if(body instanceof URLSearchParams) {
|
|
||||||
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
|
||||||
} else if(body instanceof FormData) {
|
|
||||||
// content-type is implicitly set
|
|
||||||
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
|
|
||||||
if(!requestHeaders.has('content-type'))
|
|
||||||
requestHeaders.set('content-type', 'application/octet-stream');
|
|
||||||
} else if(!requestHeaders.has('content-type')) {
|
|
||||||
const bodyParts = [];
|
|
||||||
for(const name in body)
|
|
||||||
if(body.hasOwnProperty(name))
|
|
||||||
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
|
|
||||||
body = bodyParts.join('&');
|
|
||||||
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let responseHeaders = undefined;
|
|
||||||
|
|
||||||
xhr.onload = ev => resolve({
|
|
||||||
status: xhr.status,
|
|
||||||
body: () => xhr.response,
|
|
||||||
text: () => xhr.responseText,
|
|
||||||
headers: () => {
|
|
||||||
if(responseHeaders !== undefined)
|
|
||||||
return responseHeaders;
|
|
||||||
|
|
||||||
responseHeaders = new Map;
|
|
||||||
|
|
||||||
const raw = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
|
|
||||||
for(const name in raw)
|
|
||||||
if(raw.hasOwnProperty(name)) {
|
|
||||||
const parts = raw[name].split(': ');
|
|
||||||
responseHeaders.set(parts.shift(), parts.join(': '));
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseHeaders;
|
|
||||||
},
|
|
||||||
xhr: xhr,
|
|
||||||
ev: ev,
|
|
||||||
});
|
|
||||||
|
|
||||||
xhr.onerror = ev => reject({
|
|
||||||
xhr: xhr,
|
|
||||||
ev: ev,
|
|
||||||
});
|
|
||||||
|
|
||||||
xhr.open(method, url);
|
|
||||||
for(const [name, value] of requestHeaders)
|
|
||||||
xhr.setRequestHeader(name, value);
|
|
||||||
xhr.send(body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
send: send,
|
|
||||||
get: (url, options, body) => send('GET', url, options, body),
|
|
||||||
post: (url, options, body) => send('POST', url, options, body),
|
|
||||||
delete: (url, options, body) => send('DELETE', url, options, body),
|
|
||||||
patch: (url, options, body) => send('PATCH', url, options, body),
|
|
||||||
put: (url, options, body) => send('PUT', url, options, body),
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
const $insertTags = function(target, tagOpen, tagClose) {
|
const $insertTags = function(target, tagOpen, tagClose) {
|
||||||
tagOpen = tagOpen || '';
|
tagOpen = tagOpen || '';
|
||||||
tagClose = tagClose || '';
|
tagClose = tagClose || '';
|
||||||
|
|
116
assets/misuzu.js/xhr.js
Normal file
116
assets/misuzu.js/xhr.js
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#include csrf.js
|
||||||
|
|
||||||
|
const $x = (function() {
|
||||||
|
const send = function(method, url, options, body) {
|
||||||
|
if(options === undefined)
|
||||||
|
options = {};
|
||||||
|
else if(typeof options !== 'object')
|
||||||
|
throw 'options must be undefined or an object';
|
||||||
|
|
||||||
|
Object.freeze(options);
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest;
|
||||||
|
const requestHeaders = new Map;
|
||||||
|
|
||||||
|
if('headers' in options && typeof options.headers === 'object')
|
||||||
|
for(const name in options.headers)
|
||||||
|
if(options.headers.hasOwnProperty(name))
|
||||||
|
requestHeaders.set(name.toLowerCase(), options.headers[name]);
|
||||||
|
|
||||||
|
if(options.csrf)
|
||||||
|
requestHeaders.set('x-csrf-token', MszCSRF.token);
|
||||||
|
|
||||||
|
if(typeof options.download === 'function') {
|
||||||
|
xhr.onloadstart = ev => options.download(ev);
|
||||||
|
xhr.onprogress = ev => options.download(ev);
|
||||||
|
xhr.onloadend = ev => options.download(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof options.upload === 'function') {
|
||||||
|
xhr.upload.onloadstart = ev => options.upload(ev);
|
||||||
|
xhr.upload.onprogress = ev => options.upload(ev);
|
||||||
|
xhr.upload.onloadend = ev => options.upload(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.authed)
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
|
||||||
|
if(typeof options.timeout === 'number')
|
||||||
|
xhr.timeout = options.timeout;
|
||||||
|
|
||||||
|
if(typeof options.type === 'string')
|
||||||
|
xhr.responseType = options.type;
|
||||||
|
|
||||||
|
if(typeof options.abort === 'function')
|
||||||
|
options.abort(() => xhr.abort());
|
||||||
|
|
||||||
|
if(typeof options.xhr === 'function')
|
||||||
|
options.xhr(() => xhr);
|
||||||
|
|
||||||
|
if(typeof body === 'object') {
|
||||||
|
if(body instanceof URLSearchParams) {
|
||||||
|
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||||
|
} else if(body instanceof FormData) {
|
||||||
|
// content-type is implicitly set
|
||||||
|
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
|
||||||
|
if(!requestHeaders.has('content-type'))
|
||||||
|
requestHeaders.set('content-type', 'application/octet-stream');
|
||||||
|
} else if(!requestHeaders.has('content-type')) {
|
||||||
|
const bodyParts = [];
|
||||||
|
for(const name in body)
|
||||||
|
if(body.hasOwnProperty(name))
|
||||||
|
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
|
||||||
|
body = bodyParts.join('&');
|
||||||
|
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
xhr.onload = ev => {
|
||||||
|
const headers = (headersString => {
|
||||||
|
const headers = new Map;
|
||||||
|
|
||||||
|
const raw = headersString.trim().split(/[\r\n]+/);
|
||||||
|
for(const name in raw)
|
||||||
|
if(raw.hasOwnProperty(name)) {
|
||||||
|
const parts = raw[name].split(': ');
|
||||||
|
headers.set(parts.shift(), parts.join(': '));
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
})(xhr.getAllResponseHeaders());
|
||||||
|
|
||||||
|
if(options.csrf && headers.has('x-csrf-token'))
|
||||||
|
MszCSRF.token = headers.get('x-csrf-token');
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
status: xhr.status,
|
||||||
|
body: () => xhr.response,
|
||||||
|
text: () => xhr.responseText,
|
||||||
|
headers: () => headers,
|
||||||
|
xhr: xhr,
|
||||||
|
ev: ev,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = ev => reject({
|
||||||
|
xhr: xhr,
|
||||||
|
ev: ev,
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.open(method, url);
|
||||||
|
for(const [name, value] of requestHeaders)
|
||||||
|
xhr.setRequestHeader(name, value);
|
||||||
|
xhr.send(body);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
send: send,
|
||||||
|
get: (url, options, body) => send('GET', url, options, body),
|
||||||
|
post: (url, options, body) => send('POST', url, options, body),
|
||||||
|
delete: (url, options, body) => send('DELETE', url, options, body),
|
||||||
|
patch: (url, options, body) => send('PATCH', url, options, body),
|
||||||
|
put: (url, options, body) => send('PUT', url, options, body),
|
||||||
|
};
|
||||||
|
})();
|
|
@ -160,8 +160,8 @@ final class HanyuuRpcHandler implements RpcHandler {
|
||||||
if($userInfo !== $userInfoReal) {
|
if($userInfo !== $userInfoReal) {
|
||||||
$response['guise'] = $extractUserInfo($userInfoReal);
|
$response['guise'] = $extractUserInfo($userInfoReal);
|
||||||
|
|
||||||
$csrfp = CSRF::create($sessionInfo->token);
|
$csrf = CSRF::create($sessionInfo->token);
|
||||||
$response['guise']['revert_url'] = $baseUrl . $this->urls->format('auth-revert', ['csrf' => $csrfp->createToken()]);
|
$response['guise']['revert_url'] = $baseUrl . $this->urls->format('auth-revert', ['csrf' => $csrf->createToken()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::createPayload('auth:check:success', $response);
|
return self::createPayload('auth:check:success', $response);
|
||||||
|
|
|
@ -60,7 +60,7 @@ class MessagesRoutes implements RouteHandler, UrlSource {
|
||||||
if(!($content instanceof FormHttpContent))
|
if(!($content instanceof FormHttpContent))
|
||||||
return 400;
|
return 400;
|
||||||
|
|
||||||
if(!$content->hasParam('_csrfp') || !CSRF::validate((string)$content->getParam('_csrfp')))
|
if(!CSRF::validate($request->getHeaderLine('x-csrf-token')))
|
||||||
return [
|
return [
|
||||||
'error' => [
|
'error' => [
|
||||||
'name' => 'msgs:verify',
|
'name' => 'msgs:verify',
|
||||||
|
@ -68,7 +68,7 @@ class MessagesRoutes implements RouteHandler, UrlSource {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$response->setHeader('X-CSRFP-Token', CSRF::token());
|
$response->setHeader('X-CSRF-Token', CSRF::token());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
{% include '_layout/meta.twig' %}
|
{% include '_layout/meta.twig' %}
|
||||||
<meta name="csrfp-token" content="{{ csrf_token() }}">
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
<link href="/vendor/fontawesome/css/all.min.css" type="text/css" rel="stylesheet">
|
<link href="/vendor/fontawesome/css/all.min.css" type="text/css" rel="stylesheet">
|
||||||
<link href="{{ asset('misuzu.css') }}" type="text/css" rel="stylesheet">
|
<link href="{{ asset('misuzu.css') }}" type="text/css" rel="stylesheet">
|
||||||
{% if site_background is defined %}
|
{% if site_background is defined %}
|
||||||
|
|
Reference in a new issue