|
@@ -1,7 +1,7 @@
|
|
const crypto = require('crypto');
|
|
const crypto = require('crypto');
|
|
const cheerio = require('cheerio');
|
|
const cheerio = require('cheerio');
|
|
const {defaultPermissions} = require('../util/default.json');
|
|
const {defaultPermissions} = require('../util/default.json');
|
|
-const {settingsData, sendMsg, createNotice, hasPerm} = require('./util.js');
|
|
|
|
|
|
+const {db, settingsData, sendMsg, createNotice, hasPerm} = require('./util.js');
|
|
|
|
|
|
const DiscordOauth2 = require('discord-oauth2');
|
|
const DiscordOauth2 = require('discord-oauth2');
|
|
const oauth = new DiscordOauth2( {
|
|
const oauth = new DiscordOauth2( {
|
|
@@ -19,54 +19,66 @@ const file = require('fs').readFileSync('./dashboard/login.html');
|
|
* @param {String} [action] - The action the user made
|
|
* @param {String} [action] - The action the user made
|
|
*/
|
|
*/
|
|
function dashboard_login(res, state, action) {
|
|
function dashboard_login(res, state, action) {
|
|
- if ( state ) {
|
|
|
|
- if ( settingsData.has(state) ) {
|
|
|
|
|
|
+ if ( state && settingsData.has(state) ) {
|
|
|
|
+ if ( !action ) {
|
|
res.writeHead(302, {Location: '/'});
|
|
res.writeHead(302, {Location: '/'});
|
|
return res.end();
|
|
return res.end();
|
|
}
|
|
}
|
|
- res.setHeader('Set-Cookie', [`wikibot="${state}"; Max-Age=0; HttpOnly`]);
|
|
|
|
|
|
+ settingsData.delete(state);
|
|
}
|
|
}
|
|
var $ = cheerio.load(file);
|
|
var $ = cheerio.load(file);
|
|
let invite = oauth.generateAuthUrl( {
|
|
let invite = oauth.generateAuthUrl( {
|
|
scope: ['identify', 'guilds', 'bot'],
|
|
scope: ['identify', 'guilds', 'bot'],
|
|
permissions: defaultPermissions, state
|
|
permissions: defaultPermissions, state
|
|
} );
|
|
} );
|
|
- $('.guild#invite a').attr('href', invite);
|
|
|
|
- $('.channel#invite-wikibot').attr('href', invite);
|
|
|
|
|
|
+ $('.guild#invite a, .channel#invite-wikibot').attr('href', invite);
|
|
let responseCode = 200;
|
|
let responseCode = 200;
|
|
|
|
+ let prompt = 'none';
|
|
|
|
+ if ( action === 'unauthorized' ) {
|
|
|
|
+ createNotice($, {
|
|
|
|
+ type: 'info',
|
|
|
|
+ title: 'Not logged in!',
|
|
|
|
+ text: 'Please login before you can change any settings.'
|
|
|
|
+ }).prependTo('#text');
|
|
|
|
+ }
|
|
if ( action === 'failed' ) {
|
|
if ( action === 'failed' ) {
|
|
responseCode = 400;
|
|
responseCode = 400;
|
|
createNotice($, {
|
|
createNotice($, {
|
|
|
|
+ type: 'error',
|
|
title: 'Login failed!',
|
|
title: 'Login failed!',
|
|
text: 'An error occurred while logging you in, please try again.'
|
|
text: 'An error occurred while logging you in, please try again.'
|
|
}).prependTo('#text');
|
|
}).prependTo('#text');
|
|
}
|
|
}
|
|
- if ( action === 'unauthorized' ) {
|
|
|
|
- responseCode = 401;
|
|
|
|
- createNotice($, {
|
|
|
|
- title: 'Not logged in!',
|
|
|
|
- text: 'Please login before you can change any settings.'
|
|
|
|
- }).prependTo('#text');
|
|
|
|
- }
|
|
|
|
if ( action === 'logout' ) {
|
|
if ( action === 'logout' ) {
|
|
|
|
+ prompt = 'consent';
|
|
createNotice($, {
|
|
createNotice($, {
|
|
|
|
+ type: 'success',
|
|
title: 'Successfully logged out!',
|
|
title: 'Successfully logged out!',
|
|
text: 'You have been successfully logged out. To change any settings you need to login again.'
|
|
text: 'You have been successfully logged out. To change any settings you need to login again.'
|
|
}).prependTo('#text');
|
|
}).prependTo('#text');
|
|
}
|
|
}
|
|
|
|
+ if ( process.env.READONLY ) {
|
|
|
|
+ createNotice($, {
|
|
|
|
+ type: 'info',
|
|
|
|
+ title: 'Read-only database!',
|
|
|
|
+ text: 'You can currently only view your settings but not change them.'
|
|
|
|
+ }).prependTo('#text');
|
|
|
|
+ }
|
|
state = crypto.randomBytes(16).toString("hex");
|
|
state = crypto.randomBytes(16).toString("hex");
|
|
while ( settingsData.has(state) ) {
|
|
while ( settingsData.has(state) ) {
|
|
state = crypto.randomBytes(16).toString("hex");
|
|
state = crypto.randomBytes(16).toString("hex");
|
|
}
|
|
}
|
|
let url = oauth.generateAuthUrl( {
|
|
let url = oauth.generateAuthUrl( {
|
|
scope: ['identify', 'guilds'],
|
|
scope: ['identify', 'guilds'],
|
|
- prompt: 'none', state
|
|
|
|
|
|
+ prompt, state
|
|
} );
|
|
} );
|
|
- $('.channel#login').attr('href', url);
|
|
|
|
- $('<a>').attr('href', url).text('Login').appendTo('#text .description');
|
|
|
|
|
|
+ $('.channel#login, #login-button').attr('href', url);
|
|
let body = $.html();
|
|
let body = $.html();
|
|
res.writeHead(responseCode, {
|
|
res.writeHead(responseCode, {
|
|
- 'Set-Cookie': [`wikibot="${state}"; HttpOnly`],
|
|
|
|
|
|
+ 'Set-Cookie': [
|
|
|
|
+ ...( res.getHeader('Set-Cookie') || [] ),
|
|
|
|
+ `wikibot="${state}"; HttpOnly; Path=/`
|
|
|
|
+ ],
|
|
'Content-Length': body.length
|
|
'Content-Length': body.length
|
|
});
|
|
});
|
|
res.write( body );
|
|
res.write( body );
|
|
@@ -81,14 +93,11 @@ function dashboard_login(res, state, action) {
|
|
* @param {String} [lastGuild] - The guild to return to
|
|
* @param {String} [lastGuild] - The guild to return to
|
|
*/
|
|
*/
|
|
function dashboard_oauth(res, state, searchParams, lastGuild) {
|
|
function dashboard_oauth(res, state, searchParams, lastGuild) {
|
|
- if ( settingsData.has(state) ) {
|
|
|
|
- res.writeHead(302, {Location: '/'});
|
|
|
|
- return res.end();
|
|
|
|
- }
|
|
|
|
if ( state !== searchParams.get('state') || !searchParams.get('code') ) {
|
|
if ( state !== searchParams.get('state') || !searchParams.get('code') ) {
|
|
- res.writeHead(302, {Location: '/login?action=unauthorized'});
|
|
|
|
|
|
+ res.writeHead(302, {Location: '/login?action=failed'});
|
|
return res.end();
|
|
return res.end();
|
|
}
|
|
}
|
|
|
|
+ settingsData.delete(state);
|
|
return oauth.tokenRequest( {
|
|
return oauth.tokenRequest( {
|
|
scope: ['identify', 'guilds'],
|
|
scope: ['identify', 'guilds'],
|
|
code: searchParams.get('code'),
|
|
code: searchParams.get('code'),
|
|
@@ -107,46 +116,69 @@ function dashboard_oauth(res, state, searchParams, lastGuild) {
|
|
acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
|
|
acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
|
|
icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
|
|
icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
|
|
+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) : null ),
|
|
+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) : null ),
|
|
- permissions: guild.permissions
|
|
|
|
|
|
+ userPermissions: guild.permissions
|
|
};
|
|
};
|
|
} );
|
|
} );
|
|
|
|
+ var settings = {
|
|
|
|
+ state: `${state}-${user.id}`,
|
|
|
|
+ access_token,
|
|
|
|
+ user: {
|
|
|
|
+ id: user.id,
|
|
|
|
+ username: user.username,
|
|
|
|
+ discriminator: user.discriminator,
|
|
|
|
+ avatar: 'https://cdn.discordapp.com/' + ( user.avatar ?
|
|
|
|
+ `avatars/${user.id}/${user.avatar}.` +
|
|
|
|
+ ( user.avatar.startsWith( 'a_' ) ? 'gif' : 'png' ) :
|
|
|
|
+ `embed/avatars/${user.discriminator % 5}.png` ) + '?size=64',
|
|
|
|
+ locale: user.locale
|
|
|
|
+ },
|
|
|
|
+ guilds: {
|
|
|
|
+ count: guilds.length,
|
|
|
|
+ isMember: new Map(),
|
|
|
|
+ notMember: new Map()
|
|
|
|
+ }
|
|
|
|
+ };
|
|
sendMsg( {
|
|
sendMsg( {
|
|
- type: 'isMemberAll',
|
|
|
|
|
|
+ type: 'getGuilds',
|
|
|
|
+ member: user.id,
|
|
guilds: guilds.map( guild => guild.id )
|
|
guilds: guilds.map( guild => guild.id )
|
|
} ).then( response => {
|
|
} ).then( response => {
|
|
- let isMember = new Map();
|
|
|
|
- let notMember = new Map();
|
|
|
|
response.forEach( (guild, i) => {
|
|
response.forEach( (guild, i) => {
|
|
- if ( guild ) isMember.set(guilds[i].id, guilds[i]);
|
|
|
|
- else notMember.set(guilds[i].id, guilds[i]);
|
|
|
|
|
|
+ if ( guild ) {
|
|
|
|
+ settings.guilds.isMember.set(guilds[i].id, Object.assign(guilds[i], guild));
|
|
|
|
+ }
|
|
|
|
+ else settings.guilds.notMember.set(guilds[i].id, guilds[i]);
|
|
} );
|
|
} );
|
|
- settingsData.set(`${state}-${user.id}`, {
|
|
|
|
- state: `${state}-${user.id}`,
|
|
|
|
- access_token,
|
|
|
|
- user: {
|
|
|
|
- id: user.id,
|
|
|
|
- username: user.username,
|
|
|
|
- discriminator: user.discriminator,
|
|
|
|
- avatar: 'https://cdn.discordapp.com/' + ( user.avatar ?
|
|
|
|
- `avatars/${user.id}/${user.avatar}.` +
|
|
|
|
- ( user.avatar.startsWith( 'a_' ) ? 'gif' : 'png' ) :
|
|
|
|
- `embed/avatars/${user.discriminator % 5}.png` ) + '?size=64',
|
|
|
|
- locale: user.locale
|
|
|
|
- },
|
|
|
|
- guilds: {count: guilds.length, isMember, notMember}
|
|
|
|
- });
|
|
|
|
|
|
+ settingsData.set(settings.state, settings);
|
|
res.writeHead(302, {
|
|
res.writeHead(302, {
|
|
Location: ( lastGuild ? '/guild/' + lastGuild : '/' ),
|
|
Location: ( lastGuild ? '/guild/' + lastGuild : '/' ),
|
|
- 'Set-Cookie': [
|
|
|
|
- `wikibot="${state}"; Max-Age=0; HttpOnly`,
|
|
|
|
- `wikibot="${state}-${user.id}"; HttpOnly`
|
|
|
|
- ]
|
|
|
|
|
|
+ 'Set-Cookie': [`wikibot="${settings.state}"; HttpOnly; Path=/`]
|
|
});
|
|
});
|
|
return res.end();
|
|
return res.end();
|
|
}, error => {
|
|
}, error => {
|
|
- console.log( '- Dashboard: Error while checking the guilds:', error );
|
|
|
|
- res.writeHead(302, {Location: '/login?action=failed'});
|
|
|
|
- return res.end();
|
|
|
|
|
|
+ console.log( '- Dashboard: Error while getting the guilds:', error );
|
|
|
|
+ db.all( 'SELECT guild FROM discord WHERE guild IN (' + guilds.map( guild => '?' ).join(', ') + ') AND channel IS NULL', guilds.map( guild => guild.id ), (dberror, rows) => {
|
|
|
|
+ if ( dberror ) {
|
|
|
|
+ console.log( '- Error while checking for settings: ' + dberror );
|
|
|
|
+ res.writeHead(302, {Location: '/login?action=failed'});
|
|
|
|
+ return res.end();
|
|
|
|
+ }
|
|
|
|
+ guilds.forEach( guild => {
|
|
|
|
+ if ( rows.some( row => row.guild === guild.id ) ) {
|
|
|
|
+ settings.guilds.isMember.set(guild.id, Object.assign(guild, {
|
|
|
|
+ botPermissions: 0,
|
|
|
|
+ channels: []
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+ else settings.guilds.notMember.set(guild.id, guild);
|
|
|
|
+ } );
|
|
|
|
+ settingsData.set(settings.state, settings);
|
|
|
|
+ res.writeHead(302, {
|
|
|
|
+ Location: ( lastGuild ? '/guild/' + lastGuild : '/' ),
|
|
|
|
+ 'Set-Cookie': [`wikibot="${settings.state}"; HttpOnly; Path=/`]
|
|
|
|
+ });
|
|
|
|
+ return res.end();
|
|
|
|
+ } );
|
|
} );
|
|
} );
|
|
}, error => {
|
|
}, error => {
|
|
console.log( '- Dashboard: Error while getting user and guilds: ' + error );
|
|
console.log( '- Dashboard: Error while getting user and guilds: ' + error );
|
|
@@ -178,30 +210,31 @@ function dashboard_refresh(res, state, returnLocation = '/') {
|
|
acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
|
|
acronym: guild.name.replace( /'s /g, ' ' ).replace( /\w+/g, e => e[0] ).replace( /\s/g, '' ),
|
|
icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
|
|
icon: ( guild.icon ? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.`
|
|
+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) : null ),
|
|
+ ( guild.icon.startsWith( 'a_' ) ? 'gif' : 'png' ) : null ),
|
|
- permissions: guild.permissions
|
|
|
|
|
|
+ userPermissions: guild.permissions
|
|
};
|
|
};
|
|
} );
|
|
} );
|
|
sendMsg( {
|
|
sendMsg( {
|
|
- type: 'isMemberAll',
|
|
|
|
|
|
+ type: 'getGuilds',
|
|
|
|
+ member: settings.user.id,
|
|
guilds: guilds.map( guild => guild.id )
|
|
guilds: guilds.map( guild => guild.id )
|
|
} ).then( response => {
|
|
} ).then( response => {
|
|
let isMember = new Map();
|
|
let isMember = new Map();
|
|
let notMember = new Map();
|
|
let notMember = new Map();
|
|
response.forEach( (guild, i) => {
|
|
response.forEach( (guild, i) => {
|
|
- if ( guild ) isMember.set(guilds[i].id, guilds[i]);
|
|
|
|
|
|
+ if ( guild ) isMember.set(guilds[i].id, Object.assign(guilds[i], guild));
|
|
else notMember.set(guilds[i].id, guilds[i]);
|
|
else notMember.set(guilds[i].id, guilds[i]);
|
|
} );
|
|
} );
|
|
settings.guilds = {count: guilds.length, isMember, notMember};
|
|
settings.guilds = {count: guilds.length, isMember, notMember};
|
|
- res.writeHead(302, {Location: returnLocation});
|
|
|
|
|
|
+ res.writeHead(302, {Location: returnLocation + '?refresh=success'});
|
|
return res.end();
|
|
return res.end();
|
|
}, error => {
|
|
}, error => {
|
|
- console.log( '- Dashboard: Error while checking refreshed guilds:', error );
|
|
|
|
- res.writeHead(302, {Location: '/login?action=failed'});
|
|
|
|
|
|
+ console.log( '- Dashboard: Error while getting the refreshed guilds:', error );
|
|
|
|
+ res.writeHead(302, {Location: returnLocation + '?refresh=failed'});
|
|
return res.end();
|
|
return res.end();
|
|
} );
|
|
} );
|
|
}, error => {
|
|
}, error => {
|
|
console.log( '- Dashboard: Error while refreshing guilds: ' + error );
|
|
console.log( '- Dashboard: Error while refreshing guilds: ' + error );
|
|
- res.writeHead(302, {Location: '/login?action=failed'});
|
|
|
|
|
|
+ res.writeHead(302, {Location: returnLocation + '?refresh=failed'});
|
|
return res.end();
|
|
return res.end();
|
|
} );
|
|
} );
|
|
}
|
|
}
|