Change external login system so it uses common funtions, reducing repeated code
This commit is contained in:
parent
dd32345453
commit
8cb48abb39
@ -1,20 +1,26 @@
|
|||||||
import config from '../../scripts/load-config'
|
import config from '../../scripts/load-config'
|
||||||
import http from '../../scripts/http'
|
import http from '../../scripts/http'
|
||||||
import models from './models'
|
import models from './models'
|
||||||
|
import image from './image'
|
||||||
import UAPI from './index'
|
import UAPI from './index'
|
||||||
import qs from 'querystring'
|
import qs from 'querystring'
|
||||||
import oauth from 'oauth-libre'
|
import oauth from 'oauth-libre'
|
||||||
import path from 'path'
|
|
||||||
import url from 'url'
|
|
||||||
import uuidV1 from 'uuid/v1'
|
import uuidV1 from 'uuid/v1'
|
||||||
|
import crypto from 'crypto'
|
||||||
|
|
||||||
const imgdir = path.join(__dirname, '../../', 'usercontent', 'images')
|
const userFields = ['username', 'email', 'avatar_file', 'display_name', 'ip_address']
|
||||||
|
|
||||||
let twitterApp
|
let twitterApp
|
||||||
let discordApp
|
let discordApp
|
||||||
|
|
||||||
const API = {
|
const API = {
|
||||||
Common: {
|
Common: {
|
||||||
|
// Generate a hash based on the current session
|
||||||
|
stateGenerator: (req) => {
|
||||||
|
let sessionCrypto = req.session.id + ':' + config.server.session_secret
|
||||||
|
return crypto.createHash('sha256').update(sessionCrypto).digest('hex')
|
||||||
|
},
|
||||||
|
// Find an user with an external ID
|
||||||
getExternal: async (service, identifier) => {
|
getExternal: async (service, identifier) => {
|
||||||
let extr = await models.External.query().where('service', service).andWhere('identifier', identifier)
|
let extr = await models.External.query().where('service', service).andWhere('identifier', identifier)
|
||||||
if (!extr || !extr.length) return null
|
if (!extr || !extr.length) return null
|
||||||
@ -30,10 +36,12 @@ const API = {
|
|||||||
|
|
||||||
return extr
|
return extr
|
||||||
},
|
},
|
||||||
|
// Get user ban status
|
||||||
getBan: async (user, ipAddress) => {
|
getBan: async (user, ipAddress) => {
|
||||||
let banList = await UAPI.User.getBanStatus(ipAddress || user.id, ipAddress != null)
|
let banList = await UAPI.User.getBanStatus(ipAddress || user.id, ipAddress != null)
|
||||||
return banList
|
return banList
|
||||||
},
|
},
|
||||||
|
// Create a new `external` instance for a user
|
||||||
new: async (service, identifier, user) => {
|
new: async (service, identifier, user) => {
|
||||||
let data = {
|
let data = {
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
@ -45,6 +53,7 @@ const API = {
|
|||||||
await await models.External.query().insert(data)
|
await await models.External.query().insert(data)
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
// Create a new user
|
||||||
newUser: async (service, identifier, data) => {
|
newUser: async (service, identifier, data) => {
|
||||||
let udataLimited = Object.assign({
|
let udataLimited = Object.assign({
|
||||||
activated: 1,
|
activated: 1,
|
||||||
@ -74,6 +83,7 @@ const API = {
|
|||||||
|
|
||||||
return newUser
|
return newUser
|
||||||
},
|
},
|
||||||
|
// Remove an `external` object (thus unlinking from a service)
|
||||||
remove: async (user, service) => {
|
remove: async (user, service) => {
|
||||||
user = await UAPI.User.ensureObject(user, ['password'])
|
user = await UAPI.User.ensureObject(user, ['password'])
|
||||||
let userExterns = await models.External.query().orderBy('created_at', 'asc').where('user_id', user.id)
|
let userExterns = await models.External.query().orderBy('created_at', 'asc').where('user_id', user.id)
|
||||||
@ -89,30 +99,81 @@ const API = {
|
|||||||
|
|
||||||
return models.External.query().delete().where('user_id', user.id).andWhere('service', service)
|
return models.External.query().delete().where('user_id', user.id).andWhere('service', service)
|
||||||
},
|
},
|
||||||
saveAvatar: async (avatarUrl) => {
|
// Common code for all auth callbacks
|
||||||
if (!avatarUrl) return null
|
callback: async (identifier, uid, user, ipAddress, remoteData, avatarFunc) => {
|
||||||
let imageName = 'download-' + UAPI.Hash(12)
|
let exists = await API.Common.getExternal(identifier, uid)
|
||||||
let uridata = url.parse(avatarUrl)
|
|
||||||
let pathdata = path.parse(uridata.path)
|
|
||||||
|
|
||||||
imageName += pathdata.ext || '.png'
|
if (user) {
|
||||||
|
// Get bans for user
|
||||||
|
let bans = await API.Common.getBan(user)
|
||||||
|
if (bans.length) return { banned: bans, ip: false }
|
||||||
|
|
||||||
try {
|
if (exists) return {error: null, user: user}
|
||||||
await http.Download(avatarUrl, path.join(imgdir, imageName))
|
|
||||||
} catch (e) {
|
await API.Common.new(identifier, uid, user)
|
||||||
return null
|
return {error: null, user: user}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {fileName: imageName}
|
// Callback succeeded with user id and the external table exists, we log in the user
|
||||||
|
if (exists) {
|
||||||
|
// Get bans for user
|
||||||
|
let bans = await API.Common.getBan(exists.user)
|
||||||
|
|
||||||
|
if (bans.length) return { banned: bans, ip: false }
|
||||||
|
return {error: null, user: exists.user}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get bans for IP address
|
||||||
|
let bans = await API.Common.getBan(null, ipAddress)
|
||||||
|
if (bans.length) return { banned: bans, ip: true }
|
||||||
|
|
||||||
|
// Run the function for avatar fetching
|
||||||
|
let avatar = null
|
||||||
|
if (avatarFunc) {
|
||||||
|
avatar = await avatarFunc(remoteData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign the data
|
||||||
|
let newUData = Object.assign({
|
||||||
|
email: remoteData.email || '',
|
||||||
|
avatar_file: avatar,
|
||||||
|
ip_address: ipAddress
|
||||||
|
}, remoteData)
|
||||||
|
|
||||||
|
// Remove unnecessary fields
|
||||||
|
for (let i in newUData) {
|
||||||
|
if (userFields.indexOf(i) === -1) {
|
||||||
|
delete newUData[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let newUser = await API.Common.newUser(identifier, uid, newUData)
|
||||||
|
if (!newUser) return {error: 'Failed to create user.'}
|
||||||
|
|
||||||
|
return {error: null, user: newUser}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Facebook: {
|
Facebook: {
|
||||||
callback: async (user, data) => {
|
getAvatar: async (rawData) => {
|
||||||
if (!data.authResponse || data.status !== 'connected') {
|
let profilepic = null
|
||||||
|
|
||||||
|
if (rawData.picture) {
|
||||||
|
if (rawData.picture.is_silhouette === false && rawData.picture.url) {
|
||||||
|
let imgdata = await image.downloadImage(rawData.picture.url)
|
||||||
|
if (imgdata && imgdata.fileName) {
|
||||||
|
profilepic = imgdata.fileName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return profilepic
|
||||||
|
},
|
||||||
|
callback: async (user, authResponse, ipAddress) => {
|
||||||
|
if (!authResponse) {
|
||||||
return {error: 'No Authorization'}
|
return {error: 'No Authorization'}
|
||||||
}
|
}
|
||||||
|
|
||||||
let uid = data.authResponse.userID
|
let uid = authResponse.userID
|
||||||
if (!uid) {
|
if (!uid) {
|
||||||
return {error: 'No Authorization'}
|
return {error: 'No Authorization'}
|
||||||
}
|
}
|
||||||
@ -120,7 +181,7 @@ const API = {
|
|||||||
// Get facebook user information in order to create a new user or verify
|
// Get facebook user information in order to create a new user or verify
|
||||||
let fbdata
|
let fbdata
|
||||||
let intel = {
|
let intel = {
|
||||||
access_token: data.authResponse.accessToken,
|
access_token: authResponse.accessToken,
|
||||||
fields: 'name,email,picture,short_name'
|
fields: 'name,email,picture,short_name'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,57 +196,28 @@ const API = {
|
|||||||
return {error: fbdata.error.message}
|
return {error: fbdata.error.message}
|
||||||
}
|
}
|
||||||
|
|
||||||
let exists = await API.Common.getExternal('fb', uid)
|
let cleanedData = Object.assign(fbdata, {
|
||||||
|
username: fbdata.short_name || 'FB' + UAPI.Hash(4),
|
||||||
|
display_name: fbdata.name,
|
||||||
|
email: fbdata.email || ''
|
||||||
|
})
|
||||||
|
|
||||||
if (user) {
|
return API.Common.callback('facebook', uid, user, ipAddress, cleanedData, API.Facebook.getAvatar)
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
|
|
||||||
if (exists) return {error: null, user: user}
|
|
||||||
|
|
||||||
await API.Common.new('fb', uid, user)
|
|
||||||
return {error: null, user: user}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// Callback succeeded with user id and the external table exists, we log in the user
|
Twitter: {
|
||||||
if (exists) {
|
getAvatar: async function (rawData) {
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(exists.user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
return {error: null, user: exists.user}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get bans for IP address
|
|
||||||
let bans = await API.Common.getBan(null, data.ip_address)
|
|
||||||
if (bans.length) return { banned: bans, ip: true }
|
|
||||||
|
|
||||||
// Determine profile picture
|
|
||||||
let profilepic = null
|
let profilepic = null
|
||||||
if (fbdata.picture) {
|
|
||||||
if (fbdata.picture.is_silhouette === false && fbdata.picture.url) {
|
if (rawData.profile_image_url_https) {
|
||||||
let imgdata = await API.Common.saveAvatar(fbdata.picture.url)
|
let imgdata = await image.downloadImage(rawData.profile_image_url_https)
|
||||||
if (imgdata && imgdata.fileName) {
|
if (imgdata && imgdata.fileName) {
|
||||||
profilepic = imgdata.fileName
|
profilepic = imgdata.fileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let newUData = {
|
return profilepic
|
||||||
username: fbdata.short_name || 'FB' + UAPI.Hash(4),
|
|
||||||
display_name: fbdata.name,
|
|
||||||
email: fbdata.email || '',
|
|
||||||
avatar_file: profilepic,
|
|
||||||
ip_address: data.ip_address
|
|
||||||
}
|
|
||||||
|
|
||||||
let newUser = await API.Common.newUser('fb', uid, newUData)
|
|
||||||
if (!newUser) return {error: 'Failed to create user.'}
|
|
||||||
|
|
||||||
return {error: null, user: newUser}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Twitter: {
|
|
||||||
oauthApp: function () {
|
oauthApp: function () {
|
||||||
if (!twitterApp) {
|
if (!twitterApp) {
|
||||||
let redirectUri = config.server.domain + '/api/external/twitter/callback'
|
let redirectUri = config.server.domain + '/api/external/twitter/callback'
|
||||||
@ -243,56 +275,28 @@ const API = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let uid = twdata.id_str
|
let uid = twdata.id_str
|
||||||
let exists = await API.Common.getExternal('twitter', uid)
|
|
||||||
|
|
||||||
if (user) {
|
let cleanedData = Object.assign(twdata, {
|
||||||
// Get bans for user
|
username: twdata.screen_name,
|
||||||
let bans = await API.Common.getBan(user)
|
display_name: twdata.name,
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
email: twdata.email || ''
|
||||||
|
})
|
||||||
|
|
||||||
if (exists) return {error: null, user: user}
|
return API.Common.callback('twitter', uid, user, ipAddress, cleanedData, API.Twitter.getAvatar)
|
||||||
|
|
||||||
await API.Common.new('twitter', uid, user)
|
|
||||||
return {error: null, user: user}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// Callback succeeded with user id and the external table exists, we log in the user
|
Google: {
|
||||||
if (exists) {
|
getAvatar: async (rawData) => {
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(exists.user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
return {error: null, user: exists.user}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get bans for IP
|
|
||||||
let bans = await API.Common.getBan(null, ipAddress)
|
|
||||||
if (bans.length) return { banned: bans, ip: true }
|
|
||||||
|
|
||||||
// Determine profile picture
|
|
||||||
let profilepic = null
|
let profilepic = null
|
||||||
if (twdata.profile_image_url_https) {
|
if (rawData.image) {
|
||||||
let imgdata = await API.Common.saveAvatar(twdata.profile_image_url_https)
|
let imgdata = await image.downloadImage(rawData.image)
|
||||||
if (imgdata && imgdata.fileName) {
|
if (imgdata && imgdata.fileName) {
|
||||||
profilepic = imgdata.fileName
|
profilepic = imgdata.fileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new user
|
return profilepic
|
||||||
let newUData = {
|
|
||||||
username: twdata.screen_name,
|
|
||||||
display_name: twdata.name,
|
|
||||||
email: twdata.email || '',
|
|
||||||
avatar_file: profilepic,
|
|
||||||
ip_address: ipAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
let newUser = await API.Common.newUser('twitter', uid, newUData)
|
|
||||||
if (!newUser) return {error: 'Failed to create user.'}
|
|
||||||
|
|
||||||
return {error: null, user: newUser}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Google: {
|
|
||||||
callback: async (user, data, ipAddress) => {
|
callback: async (user, data, ipAddress) => {
|
||||||
let uid
|
let uid
|
||||||
|
|
||||||
@ -312,56 +316,32 @@ const API = {
|
|||||||
return {error: e.message}
|
return {error: e.message}
|
||||||
}
|
}
|
||||||
|
|
||||||
let exists = await API.Common.getExternal('google', uid)
|
let cleanedData = Object.assign(data, {
|
||||||
|
|
||||||
if (user) {
|
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
|
|
||||||
if (exists) return {error: null, user: user}
|
|
||||||
|
|
||||||
await API.Common.new('google', uid, user)
|
|
||||||
return {error: null, user: user}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback succeeded with user id and the external table exists, we log in the user
|
|
||||||
if (exists) {
|
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(exists.user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
return {error: null, user: exists.user}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get bans for IP
|
|
||||||
let bans = await API.Common.getBan(null, ipAddress)
|
|
||||||
if (bans.length) return { banned: bans, ip: true }
|
|
||||||
|
|
||||||
// Determine profile picture
|
|
||||||
let profilepic = null
|
|
||||||
if (data.image) {
|
|
||||||
let imgdata = await API.Common.saveAvatar(data.image)
|
|
||||||
if (imgdata && imgdata.fileName) {
|
|
||||||
profilepic = imgdata.fileName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new user
|
|
||||||
let newUData = {
|
|
||||||
username: data.name.replace(/\W+/gi, ''),
|
username: data.name.replace(/\W+/gi, ''),
|
||||||
display_name: data.name,
|
display_name: data.name,
|
||||||
email: data.email || '',
|
email: data.email || ''
|
||||||
avatar_file: profilepic,
|
})
|
||||||
ip_address: ipAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
let newUser = await API.Common.newUser('google', uid, newUData)
|
return API.Common.callback('google', uid, user, ipAddress, cleanedData, API.Google.getAvatar)
|
||||||
if (!newUser) return {error: 'Failed to create user.'}
|
|
||||||
|
|
||||||
return {error: null, user: newUser}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Discord: {
|
Discord: {
|
||||||
|
getAvatar: async (rawData) => {
|
||||||
|
let profilepic = null
|
||||||
|
let aviSnowflake = rawData.avatar
|
||||||
|
if (aviSnowflake) {
|
||||||
|
try {
|
||||||
|
let avpt = await image.downloadImage('https://cdn.discordapp.com/avatars/' + rawData.id + '/' + aviSnowflake + '.png')
|
||||||
|
if (avpt && avpt.fileName) {
|
||||||
|
profilepic = avpt.fileName
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
profilepic = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return profilepic
|
||||||
|
},
|
||||||
oauth2App: function () {
|
oauth2App: function () {
|
||||||
if (discordApp) return
|
if (discordApp) return
|
||||||
discordApp = new oauth.PromiseOAuth2(
|
discordApp = new oauth.PromiseOAuth2(
|
||||||
@ -374,9 +354,9 @@ const API = {
|
|||||||
|
|
||||||
discordApp.useAuthorizationHeaderforGET(true)
|
discordApp.useAuthorizationHeaderforGET(true)
|
||||||
},
|
},
|
||||||
getAuthorizeURL: function () {
|
getAuthorizeURL: function (req) {
|
||||||
if (!discordApp) API.Discord.oauth2App()
|
if (!discordApp) API.Discord.oauth2App()
|
||||||
let state = UAPI.Hash(6)
|
let state = API.Common.stateGenerator(req)
|
||||||
let redirectUri = config.server.domain + '/api/external/discord/callback'
|
let redirectUri = config.server.domain + '/api/external/discord/callback'
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
@ -421,58 +401,15 @@ const API = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let uid = ddata.id
|
let uid = ddata.id
|
||||||
let exists = await API.Common.getExternal('discord', uid)
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
|
|
||||||
if (exists) return {error: null, user: user}
|
|
||||||
|
|
||||||
await API.Common.new('discord', uid, user)
|
|
||||||
return {error: null, user: user}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback succeeded with user id and the external table exists, we log in the user
|
|
||||||
if (exists) {
|
|
||||||
// Get bans for user
|
|
||||||
let bans = await API.Common.getBan(exists.user)
|
|
||||||
if (bans.length) return { banned: bans, ip: false }
|
|
||||||
return {error: null, user: exists.user}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get bans for IP
|
|
||||||
let bans = await API.Common.getBan(null, ipAddress)
|
|
||||||
if (bans.length) return { banned: bans, ip: true }
|
|
||||||
|
|
||||||
// Download profile picture
|
|
||||||
let profilepic = null
|
|
||||||
let aviSnowflake = ddata.avatar
|
|
||||||
if (aviSnowflake) {
|
|
||||||
try {
|
|
||||||
let avpt = await API.Common.saveAvatar('https://cdn.discordapp.com/avatars/' + ddata.id + '/' + aviSnowflake + '.png')
|
|
||||||
if (avpt && avpt.fileName) {
|
|
||||||
profilepic = avpt.fileName
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
profilepic = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new user
|
// Create a new user
|
||||||
let newUData = {
|
let cleanedData = Object.assign(ddata, {
|
||||||
username: ddata.username.replace(/\W+/gi, '_'),
|
username: ddata.username.replace(/\W+/gi, '_'),
|
||||||
display_name: ddata.username,
|
display_name: ddata.username,
|
||||||
email: ddata.email || '',
|
email: ddata.email || ''
|
||||||
avatar_file: profilepic,
|
})
|
||||||
ip_address: ipAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
let newUser = await API.Common.newUser('discord', uid, newUData)
|
return API.Common.callback('discord', uid, user, ipAddress, cleanedData, API.Discord.getAvatar)
|
||||||
if (!newUser) return {error: 'Failed to create user.'}
|
|
||||||
|
|
||||||
return {error: null, user: newUser}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import gm from 'gm'
|
import gm from 'gm'
|
||||||
|
import url from 'url'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import Promise from 'bluebird'
|
import Promise from 'bluebird'
|
||||||
|
|
||||||
|
import http from '../../scripts/http'
|
||||||
|
|
||||||
const fs = Promise.promisifyAll(require('fs'))
|
const fs = Promise.promisifyAll(require('fs'))
|
||||||
|
|
||||||
const uploads = path.join(__dirname, '../../', 'usercontent')
|
const uploads = path.join(__dirname, '../../', 'usercontent')
|
||||||
@ -14,6 +17,10 @@ const imageTypes = {
|
|||||||
'image/jpeg': '.jpeg'
|
'image/jpeg': '.jpeg'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function imageUniquifier () {
|
||||||
|
return crypto.randomBytes(12).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
function decodeBase64Image (dataString) {
|
function decodeBase64Image (dataString) {
|
||||||
let matches = dataString.match(/^data:([A-Za-z-+/]+);base64,(.+)$/)
|
let matches = dataString.match(/^data:([A-Za-z-+/]+);base64,(.+)$/)
|
||||||
let response = {}
|
let response = {}
|
||||||
@ -53,7 +60,7 @@ async function imageBase64 (baseObj) {
|
|||||||
if (!imgData) return null
|
if (!imgData) return null
|
||||||
if (!imageTypes[imgData.type]) return null
|
if (!imageTypes[imgData.type]) return null
|
||||||
|
|
||||||
let imageName = 'base64-' + crypto.randomBytes(12).toString('hex')
|
let imageName = 'base64-' + imageUniquifier()
|
||||||
let ext = imageTypes[imgData.type] || '.png'
|
let ext = imageTypes[imgData.type] || '.png'
|
||||||
|
|
||||||
imageName += ext
|
imageName += ext
|
||||||
@ -70,6 +77,25 @@ async function imageBase64 (baseObj) {
|
|||||||
return {file: fpath}
|
return {file: fpath}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function downloadImage (imgUrl, designation) {
|
||||||
|
if (!imgUrl) return null
|
||||||
|
if (!designation) designation = 'download'
|
||||||
|
|
||||||
|
let imageName = designation + '-' + imageUniquifier()
|
||||||
|
let uridata = url.parse(imgUrl)
|
||||||
|
let pathdata = path.parse(uridata.path)
|
||||||
|
|
||||||
|
imageName += pathdata.ext || '.png'
|
||||||
|
|
||||||
|
try {
|
||||||
|
await http.Download(imgUrl, path.join(images, imageName))
|
||||||
|
} catch (e) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {fileName: imageName}
|
||||||
|
}
|
||||||
|
|
||||||
async function uploadImage (identifier, fields, files) {
|
async function uploadImage (identifier, fields, files) {
|
||||||
if (!files.image) return {error: 'No image file'}
|
if (!files.image) return {error: 'No image file'}
|
||||||
|
|
||||||
@ -142,6 +168,7 @@ async function uploadImage (identifier, fields, files) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
downloadImage: downloadImage,
|
||||||
uploadImage: uploadImage,
|
uploadImage: uploadImage,
|
||||||
imageBase64: imageBase64,
|
imageBase64: imageBase64,
|
||||||
types: imageTypes
|
types: imageTypes
|
||||||
|
@ -79,16 +79,34 @@ function JsonData (req, res, error, redirect = '/') {
|
|||||||
res.jsonp({error: error, redirect: redirect})
|
res.jsonp({error: error, redirect: redirect})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common middleware for all external account unlinks
|
||||||
|
function removeAuthMiddleware (identifier) {
|
||||||
|
return wrap(async (req, res) => {
|
||||||
|
if (!req.session.user) return res.redirect('/login')
|
||||||
|
let done = await APIExtern.Common.remove(req.session.user, identifier)
|
||||||
|
|
||||||
|
if (!done) {
|
||||||
|
req.flash('message', {error: true, text: 'Unable to unlink social media account'})
|
||||||
|
}
|
||||||
|
|
||||||
|
res.redirect('/user/manage')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/** FACEBOOK LOGIN
|
/** FACEBOOK LOGIN
|
||||||
* Ajax POST only <in-page javascript handeled>
|
* Ajax POST only <in-page javascript handeled>
|
||||||
* No tokens saved in configs, everything works out-of-the-box
|
* No tokens saved in configs, everything works out-of-the-box
|
||||||
*/
|
*/
|
||||||
router.post('/external/facebook/callback', wrap(async (req, res, next) => {
|
router.post('/external/facebook/callback', wrap(async (req, res, next) => {
|
||||||
if (!config.facebook || !config.facebook.client) return next()
|
if (!config.facebook || !config.facebook.client) return next()
|
||||||
let sane = objectAssembler(req.body)
|
|
||||||
sane.ip_address = req.realIP
|
|
||||||
|
|
||||||
let response = await APIExtern.Facebook.callback(req.session.user, sane)
|
// Fix up the retarded object Facebook sends us
|
||||||
|
let sane = objectAssembler(req.body)
|
||||||
|
if (!sane || !sane.authResponse) {
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = await APIExtern.Facebook.callback(req.session.user, sane.authResponse, req.realIP)
|
||||||
|
|
||||||
if (response.banned) {
|
if (response.banned) {
|
||||||
return JsonData(req, res, 'You are banned.')
|
return JsonData(req, res, 'You are banned.')
|
||||||
@ -107,16 +125,7 @@ router.post('/external/facebook/callback', wrap(async (req, res, next) => {
|
|||||||
JsonData(req, res, null, '/login')
|
JsonData(req, res, null, '/login')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
router.get('/external/facebook/remove', wrap(async (req, res) => {
|
router.get('/external/facebook/remove', removeAuthMiddleware('facebook'))
|
||||||
if (!req.session.user) return res.redirect('/login')
|
|
||||||
let done = await APIExtern.Common.remove(req.session.user, 'fb')
|
|
||||||
|
|
||||||
if (!done) {
|
|
||||||
req.flash('message', {error: true, text: 'Unable to unlink social media account'})
|
|
||||||
}
|
|
||||||
|
|
||||||
res.redirect('/user/manage')
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** TWITTER LOGIN
|
/** TWITTER LOGIN
|
||||||
* OAuth1.0a flows
|
* OAuth1.0a flows
|
||||||
@ -172,17 +181,7 @@ router.get('/external/twitter/callback', wrap(async (req, res) => {
|
|||||||
res.render('redirect', {url: uri})
|
res.render('redirect', {url: uri})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
router.get('/external/twitter/remove', wrap(async (req, res) => {
|
router.get('/external/twitter/remove', removeAuthMiddleware('twitter'))
|
||||||
if (!req.session.user) return res.redirect('/login')
|
|
||||||
|
|
||||||
let done = await APIExtern.Common.remove(req.session.user, 'twitter')
|
|
||||||
|
|
||||||
if (!done) {
|
|
||||||
req.flash('message', {error: true, text: 'Unable to unlink social media account'})
|
|
||||||
}
|
|
||||||
|
|
||||||
res.redirect('/user/manage')
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** DISCORD LOGIN
|
/** DISCORD LOGIN
|
||||||
* OAuth2 flows
|
* OAuth2 flows
|
||||||
@ -191,22 +190,16 @@ router.get('/external/twitter/remove', wrap(async (req, res) => {
|
|||||||
router.get('/external/discord/login', wrap(async (req, res) => {
|
router.get('/external/discord/login', wrap(async (req, res) => {
|
||||||
if (!config.discord || !config.discord.api) return res.redirect('/')
|
if (!config.discord || !config.discord.api) return res.redirect('/')
|
||||||
|
|
||||||
let infos = APIExtern.Discord.getAuthorizeURL()
|
let infos = APIExtern.Discord.getAuthorizeURL(req)
|
||||||
|
|
||||||
req.session.discord_auth = {
|
|
||||||
state: infos.state
|
|
||||||
}
|
|
||||||
|
|
||||||
res.redirect(infos.url)
|
res.redirect(infos.url)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
router.get('/external/discord/callback', wrap(async (req, res) => {
|
router.get('/external/discord/callback', wrap(async (req, res) => {
|
||||||
if (!config.discord || !config.discord.api) return res.redirect('/login')
|
if (!config.discord || !config.discord.api) return res.redirect('/login')
|
||||||
if (!req.session.discord_auth) return res.redirect('/login')
|
|
||||||
|
|
||||||
let code = req.query.code
|
let code = req.query.code
|
||||||
let state = req.query.state
|
let state = req.query.state
|
||||||
let da = req.session.discord_auth
|
|
||||||
let uri = '/login'
|
let uri = '/login'
|
||||||
|
|
||||||
if (!code) {
|
if (!code) {
|
||||||
@ -214,7 +207,7 @@ router.get('/external/discord/callback', wrap(async (req, res) => {
|
|||||||
return res.redirect(uri)
|
return res.redirect(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state || state !== da.state) {
|
if (!state || state !== APIExtern.Common.stateGenerator(req)) {
|
||||||
req.flash('message', {error: true, text: 'Request got intercepted, try again.'})
|
req.flash('message', {error: true, text: 'Request got intercepted, try again.'})
|
||||||
return res.redirect(uri)
|
return res.redirect(uri)
|
||||||
}
|
}
|
||||||
@ -245,29 +238,7 @@ router.get('/external/discord/callback', wrap(async (req, res) => {
|
|||||||
res.render('redirect', {url: uri})
|
res.render('redirect', {url: uri})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
router.get('/external/discord/remove', wrap(async (req, res) => {
|
router.get('/external/discord/remove', removeAuthMiddleware('discord'))
|
||||||
if (!req.session.user) return res.redirect('/login')
|
|
||||||
|
|
||||||
let done = await APIExtern.Common.remove(req.session.user, 'discord')
|
|
||||||
|
|
||||||
if (!done) {
|
|
||||||
req.flash('message', {error: true, text: 'Unable to unlink social media account'})
|
|
||||||
}
|
|
||||||
|
|
||||||
res.redirect('/user/manage')
|
|
||||||
}))
|
|
||||||
|
|
||||||
router.get('/external/discord/remove', wrap(async (req, res) => {
|
|
||||||
if (!req.session.user) return res.redirect('/login')
|
|
||||||
|
|
||||||
let done = await APIExtern.Common.remove(req.session.user, 'discord')
|
|
||||||
|
|
||||||
if (!done) {
|
|
||||||
req.flash('message', {error: true, text: 'Unable to unlink social media account'})
|
|
||||||
}
|
|
||||||
|
|
||||||
res.redirect('/user/manage')
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** GOOGLE LOGIN
|
/** GOOGLE LOGIN
|
||||||
* Google Token Verification
|
* Google Token Verification
|
||||||
@ -303,17 +274,7 @@ router.post('/external/google/callback', wrap(async (req, res) => {
|
|||||||
JsonData(req, res, null, '/login')
|
JsonData(req, res, null, '/login')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
router.get('/external/google/remove', wrap(async (req, res) => {
|
router.get('/external/google/remove', removeAuthMiddleware('google'))
|
||||||
if (!req.session.user) return res.redirect('/login')
|
|
||||||
|
|
||||||
let done = await APIExtern.Common.remove(req.session.user, 'google')
|
|
||||||
|
|
||||||
if (!done) {
|
|
||||||
req.flash('message', {error: true, text: 'Unable to unlink social media account'})
|
|
||||||
}
|
|
||||||
|
|
||||||
res.redirect('/user/manage')
|
|
||||||
}))
|
|
||||||
|
|
||||||
/* ========
|
/* ========
|
||||||
* NEWS
|
* NEWS
|
||||||
|
@ -205,9 +205,9 @@ router.get('/user/manage', ensureLogin, wrap(async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.facebook && config.facebook.client) {
|
if (config.facebook && config.facebook.client) {
|
||||||
if (!socialStatus.enabled.fb) {
|
if (!socialStatus.enabled.facebook) {
|
||||||
res.locals.facebook_auth = config.facebook.client
|
res.locals.facebook_auth = config.facebook.client
|
||||||
} else if (socialStatus.source !== 'fb') {
|
} else if (socialStatus.source !== 'facebook') {
|
||||||
res.locals.facebook_auth = false
|
res.locals.facebook_auth = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user