Added support for new login/token endpoints.
This commit is contained in:
parent
176db54a72
commit
4f3b3257b0
8 changed files with 95 additions and 81 deletions
src/mami.js
31
src/mami.js/auth.js
Normal file
31
src/mami.js/auth.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const MamiIsAuth = value => {
|
||||
return typeof value === 'object'
|
||||
&& value !== null
|
||||
&& 'type' in value
|
||||
&& (value.type === null || typeof value.type === 'string')
|
||||
&& 'token' in value
|
||||
&& (value.token === null || typeof value.token === 'string')
|
||||
&& 'header' in value
|
||||
&& (value.header === null || typeof value.header === 'string')
|
||||
&& 'refresh' in value
|
||||
&& typeof value.refresh === 'function';
|
||||
};
|
||||
|
||||
const MamiFlashiiAuth = function(flashii) {
|
||||
let type = null;
|
||||
let token = null;
|
||||
|
||||
return {
|
||||
get type() { return type; },
|
||||
get token() { return token; },
|
||||
get header() { return type ? `${type} ${token}` : null; },
|
||||
|
||||
async refresh() {
|
||||
try {
|
||||
({ token_type: type=null, access_token: token=null } = await flashii.v1.chat.token());
|
||||
} catch(ex) {
|
||||
await flashii.v1.chat.login();
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
|
@ -1,19 +1,15 @@
|
|||
#include events.js
|
||||
#include flashii.js
|
||||
|
||||
const MamiContext = function(globalEventTarget, eventTarget) {
|
||||
const MamiContext = function(globalEventTarget, eventTarget, auth, flashii) {
|
||||
if(typeof globalEventTarget !== 'object' && globalEventTarget === null)
|
||||
throw 'globalEventTarget must be undefined or a non-null object';
|
||||
|
||||
if(eventTarget === undefined)
|
||||
if(eventTarget === undefined || eventTarget === null)
|
||||
eventTarget = 'mami';
|
||||
else if(typeof eventTarget !== 'object' || eventTarget === null)
|
||||
throw 'eventTarget must be a string or a non-null object';
|
||||
|
||||
if(typeof eventTarget === 'string')
|
||||
eventTarget = globalEventTarget.scopeTo(eventTarget);
|
||||
|
||||
const flashii = new Flashii(`${window.FII_URL}/api`);
|
||||
else if(typeof eventTarget !== 'object')
|
||||
throw 'eventTarget must be a string or a non-null object';
|
||||
|
||||
let isUnloading = false;
|
||||
|
||||
|
@ -28,6 +24,8 @@ const MamiContext = function(globalEventTarget, eventTarget) {
|
|||
return {
|
||||
get globalEvents() { return globalEventTarget; },
|
||||
get events() { return eventTarget; },
|
||||
|
||||
get auth() { return auth; },
|
||||
get flashii() { return flashii; },
|
||||
|
||||
get isUnloading() { return isUnloading; },
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
const MamiIsEventTarget = value => {
|
||||
if(typeof value !== 'object' || value === null)
|
||||
return false;
|
||||
|
||||
if(typeof value.scopeTo !== 'function'
|
||||
|| typeof value.create !== 'function'
|
||||
|| typeof value.watch !== 'function'
|
||||
|| typeof value.unwatch !== 'function'
|
||||
|| typeof value.dispatch !== 'function')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return value !== null
|
||||
&& typeof value === 'object'
|
||||
&& typeof value.scopeTo === 'function'
|
||||
&& typeof value.create === 'function'
|
||||
&& typeof value.watch === 'function'
|
||||
&& typeof value.unwatch === 'function'
|
||||
&& typeof value.dispatch === 'function';
|
||||
};
|
||||
|
||||
const MamiEventTargetScoped = function(eventTarget, prefix) {
|
||||
|
|
|
@ -45,6 +45,7 @@ const Flashii = function(baseUrl) {
|
|||
body=null,
|
||||
headers=null,
|
||||
type='json',
|
||||
authed=false,
|
||||
}) => {
|
||||
const url = createUrl(path, fields);
|
||||
if(params)
|
||||
|
@ -58,7 +59,7 @@ const Flashii = function(baseUrl) {
|
|||
headers ??= {};
|
||||
if(fresh) headers['Cache-Control'] = 'no-cache';
|
||||
|
||||
const options = { type, headers };
|
||||
const options = { type, headers, authed };
|
||||
|
||||
return await $xhr.send(method, url, options, body);
|
||||
};
|
||||
|
@ -67,6 +68,34 @@ const Flashii = function(baseUrl) {
|
|||
|
||||
fii.v1 = {};
|
||||
|
||||
fii.v1.chat = {};
|
||||
fii.v1.chat.login = function({ redirect=null, assign=true }) {
|
||||
return new Promise(resolve => {
|
||||
redirect ??= `${location.protocol}//${location.host}`;
|
||||
if(typeof redirect !== 'string')
|
||||
throw new Error('redirect must a string.');
|
||||
|
||||
const url = createUrl('/v1/chat/login');
|
||||
url.searchParams.set('redirect', redirect);
|
||||
|
||||
// intentionally does not resolve
|
||||
if(assign)
|
||||
location.assign(url);
|
||||
else
|
||||
resolve(url);
|
||||
});
|
||||
};
|
||||
fii.v1.chat.token = async function() {
|
||||
const { status, body } = await send({ method: 'GET', path: '/v1/chat/token', authed: true, fresh: true });
|
||||
|
||||
if(status === 403)
|
||||
throw new Error('You must be logged in to use chat.');
|
||||
if(status > 299)
|
||||
throw new Error(`Failed to fetch authorization token with error code ${status}.`);
|
||||
|
||||
return body;
|
||||
};
|
||||
|
||||
const verifyColourPresetName = name => {
|
||||
if(/^([^A-Za-z0-9\-_]+)$/gu.test(name))
|
||||
throw new Error('name argument is not an acceptable colour preset name.');
|
||||
|
|
|
@ -7,6 +7,7 @@ window.Umi = { UI: {} };
|
|||
|
||||
#include animate.js
|
||||
#include args.js
|
||||
#include auth.js
|
||||
#include awaitable.js
|
||||
#include common.js
|
||||
#include compat.js
|
||||
|
@ -14,8 +15,8 @@ window.Umi = { UI: {} };
|
|||
#include context.js
|
||||
#include emotes.js
|
||||
#include events.js
|
||||
#include flashii.js
|
||||
#include mobile.js
|
||||
#include mszauth.js
|
||||
#include parsing.js
|
||||
#include themes.js
|
||||
#include txtrigs.js
|
||||
|
@ -57,9 +58,19 @@ const MamiInit = async args => {
|
|||
define('parent').default(document.body).constraint(value => value instanceof Element).done();
|
||||
define('eventTarget').required().constraint(MamiIsEventTarget).done();
|
||||
define('settingsPrefix').default('umi-').done();
|
||||
define('auth').default(null).constraint(MamiIsAuth).done();
|
||||
});
|
||||
|
||||
const ctx = new MamiContext(args.eventTarget);
|
||||
const flashii = new Flashii(`${window.FII_URL}/api`);
|
||||
|
||||
let auth = args.auth;
|
||||
if(!auth) {
|
||||
auth = new MamiFlashiiAuth(flashii);
|
||||
await auth.refresh();
|
||||
setInterval(() => { auth.refresh(); }, 600000);
|
||||
}
|
||||
|
||||
const ctx = new MamiContext(args.eventTarget, null, auth, flashii);
|
||||
|
||||
// remove this later and replace with the one commented out way below
|
||||
if(!('mami' in window))
|
||||
|
@ -82,26 +93,6 @@ const MamiInit = async args => {
|
|||
}
|
||||
}
|
||||
|
||||
if(!MamiMisuzuAuth.hasInfo()) {
|
||||
try {
|
||||
const auth = await MamiMisuzuAuth.update();
|
||||
if(!auth.ok)
|
||||
throw 'Authentication failed.';
|
||||
} catch(ex) {
|
||||
console.error(ex);
|
||||
location.assign(`${window.FII_URL}/_sockchat/login`);
|
||||
return;
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
MamiMisuzuAuth.update()
|
||||
.then(auth => {
|
||||
if(!auth.ok)
|
||||
location.assign(`${window.FII_URL}/_sockchat/login`);
|
||||
})
|
||||
}, 600000);
|
||||
}
|
||||
|
||||
|
||||
const settings = new MamiSettings(args.settingsPrefix, ctx.events.scopeTo('settings'));
|
||||
ctx.settings = settings;
|
||||
|
@ -221,7 +212,7 @@ const MamiInit = async args => {
|
|||
// loading these asynchronously makes them not show up in the backlog
|
||||
// revisit when emote reparsing is implemented
|
||||
try {
|
||||
await MamiEmotes.loadApi(ctx.flashii);
|
||||
await MamiEmotes.loadApi(flashii);
|
||||
} catch(ex) {
|
||||
console.error('Failed to load emoticons.', ex);
|
||||
}
|
||||
|
@ -300,7 +291,7 @@ const MamiInit = async args => {
|
|||
onclick: ev => {
|
||||
if(bbCode.tag === 'color') {
|
||||
if(colourPicker === undefined) {
|
||||
colourPicker = new MamiColourPicker({ flashii: ctx.flashii });
|
||||
colourPicker = new MamiColourPicker({ flashii });
|
||||
layout.element.appendChild(colourPicker.element);
|
||||
}
|
||||
|
||||
|
@ -378,7 +369,7 @@ const MamiInit = async args => {
|
|||
});
|
||||
|
||||
settings.watch('weeaboo', ev => {
|
||||
if(ev.detail.value) Weeaboo.init(ctx.flashii);
|
||||
if(ev.detail.value) Weeaboo.init(flashii);
|
||||
});
|
||||
|
||||
settings.watch('osuKeysV2', ev => {
|
||||
|
@ -562,7 +553,7 @@ const MamiInit = async args => {
|
|||
button.disabled = true;
|
||||
button.textContent = 'Reloading emoticons...';
|
||||
try {
|
||||
await MamiEmotes.loadApi(ctx.flashii, true);
|
||||
await MamiEmotes.loadApi(flashii, true);
|
||||
} finally {
|
||||
button.textContent = textOrig;
|
||||
button.disabled = false;
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
#include common.js
|
||||
|
||||
const MamiMisuzuAuth = (() => {
|
||||
let userId = null;
|
||||
let authMethod = 'Misuzu';
|
||||
let authToken = null;
|
||||
|
||||
return {
|
||||
hasInfo: () => userId !== null && authToken !== null,
|
||||
getUserId: () => userId,
|
||||
getAuthToken: () => authToken,
|
||||
getLine: () => `${authMethod} ${authToken}`,
|
||||
getInfo: () => {
|
||||
return {
|
||||
method: authMethod,
|
||||
token: authToken,
|
||||
};
|
||||
},
|
||||
update: async () => {
|
||||
const { body } = await $xhr.get(`${window.FII_URL}/_sockchat/token`, { authed: true, type: 'json' });
|
||||
if(body.ok) {
|
||||
userId = body.usr.toString();
|
||||
authToken = body.tkn;
|
||||
}
|
||||
|
||||
return body;
|
||||
},
|
||||
};
|
||||
})();
|
|
@ -1,5 +1,4 @@
|
|||
#include compat.js
|
||||
#include mszauth.js
|
||||
#include proto/sockchat/client.js
|
||||
|
||||
const MamiSockChat = function(eventTarget) {
|
||||
|
@ -34,9 +33,8 @@ const MamiSockChat = function(eventTarget) {
|
|||
return ex.wasKicked === true;
|
||||
}
|
||||
},
|
||||
authenticate: async () => {
|
||||
const authInfo = MamiMisuzuAuth.getInfo();
|
||||
await client.sendAuth(authInfo.method, authInfo.token);
|
||||
authenticate: async auth => {
|
||||
await client.sendAuth(auth.type, auth.token);
|
||||
},
|
||||
setDumpPackets: state => {
|
||||
dumpPackets = !!state;
|
||||
|
|
|
@ -42,7 +42,7 @@ const MamiSockChatHandlers = function(
|
|||
handlers['conn:ready'] = ev => {
|
||||
if(dumpEvents) console.log('conn:ready');
|
||||
|
||||
client.authenticate().then(() => {
|
||||
client.authenticate(ctx.auth).then(() => {
|
||||
if(!legacyUmiConnectFired) {
|
||||
legacyUmiConnectFired = true;
|
||||
ctx.globalEvents.dispatch('umi:connect');
|
||||
|
@ -117,7 +117,7 @@ const MamiSockChatHandlers = function(
|
|||
}
|
||||
|
||||
if(ev.detail.session.needsAuth) {
|
||||
location.assign(`${window.FII_URL}/_sockchat/login`);
|
||||
ctx.flashii.v1.chat.login();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue