2016-02-01 22:19:30 +00:00
|
|
|
{_} = require 'underscore'
|
|
|
|
|
|
|
|
crypto = require('crypto')
|
|
|
|
querystring = require('querystring');
|
|
|
|
Cookies = require( "cookies" )
|
|
|
|
|
|
|
|
|
|
|
|
request = require 'request'
|
|
|
|
authHeaders = {AUTHUSER: process.env.AUTHUSER, AUTHTOKEN: process.env.AUTHTOKEN}
|
|
|
|
request = request.defaults(json: true, headers: authHeaders, timeout: 30 * 1000)
|
|
|
|
|
|
|
|
config = require './config'
|
|
|
|
redis = require './redis'
|
|
|
|
|
|
|
|
USER_KEY = "users"
|
|
|
|
AUTH_KEY = "auth"
|
|
|
|
BANS_KEY = "bans"
|
|
|
|
MUTE_KEY = "mute"
|
|
|
|
|
2016-02-19 23:54:42 +00:00
|
|
|
return_sso_url="./"
|
2016-02-01 22:19:30 +00:00
|
|
|
secretstring = config.SECRET_KEY
|
|
|
|
loggedin = false
|
|
|
|
|
|
|
|
# This middleware checks if a user is authenticated through the site. If yes,
|
|
|
|
# then information about the user is stored in req.user. In addition, we store
|
|
|
|
# a token associated with that user into req.user.token.
|
|
|
|
#
|
|
|
|
# User information is also stored in redis.
|
|
|
|
exports.middleware = -> (req, res, next) ->
|
|
|
|
cookies = new Cookies( req, res )
|
|
|
|
|
|
|
|
return next() if req.path.match(/^\/css|^\/js|^\/fonts|^\/Sprites|^\/replays\/\b/)
|
|
|
|
return next() if req.path.match(/^\/leaderboard/) # add some proper site authentication later instead
|
|
|
|
|
|
|
|
authenticate req, (body) ->
|
|
|
|
if !loggedin
|
|
|
|
if req.query.sso
|
|
|
|
sso = req.query.sso
|
|
|
|
sig = req.query.sig
|
|
|
|
cryptedret = crypto.createHmac('SHA256', secretstring).update(sso).digest('hex')
|
|
|
|
if cryptedret != sig
|
|
|
|
return
|
|
|
|
else
|
|
|
|
base64decode = new Buffer(sso, 'base64').toString('ascii')
|
|
|
|
userobject = querystring.parse(base64decode)
|
|
|
|
nonce = cookies.get("nonce")
|
|
|
|
noncereturn = userobject.nonce
|
|
|
|
if noncereturn != nonce
|
|
|
|
return
|
|
|
|
else
|
|
|
|
setdatabasedata(req, cookies, userobject, next)
|
|
|
|
else
|
|
|
|
parameters = getparameters(req)
|
|
|
|
nonce = new Date().getTime() + '' + new Date().getMilliseconds();
|
|
|
|
cookies.set("nonce", nonce)
|
2016-02-19 23:54:42 +00:00
|
|
|
console.log(req.headers.host)
|
|
|
|
return_sso_url="http://" + req.headers.host + req.url
|
2016-02-01 22:19:30 +00:00
|
|
|
payload = "nonce=" + nonce + "&return_sso_url=" + return_sso_url
|
|
|
|
base64payload = new Buffer(payload).toString('base64')
|
|
|
|
urlencoded = encodeURIComponent(base64payload)
|
|
|
|
crypted = crypto.createHmac('SHA256', secretstring).update(base64payload).digest('hex')
|
2016-02-19 23:54:42 +00:00
|
|
|
return res.redirect("http://forums.p-insurgence.com/session/sso_provider?sso=" + urlencoded + "&sig=" + crypted)
|
2016-02-01 22:19:30 +00:00
|
|
|
|
|
|
|
exports.matchToken = (req, id, token, next) ->
|
|
|
|
hmac = crypto.createHmac('sha256', config.SECRET_KEY)
|
|
|
|
rawcookies = req.headers.cookie
|
|
|
|
rawcookiesarr = rawcookies.split('; ')
|
|
|
|
noncearr = rawcookiesarr.filter (x) -> x.substring(0, 6) == "nonce="
|
|
|
|
|
|
|
|
if (noncearr[0])
|
|
|
|
noncecookie = noncearr[0].replace("nonce=", "")
|
|
|
|
|
|
|
|
if token != noncecookie
|
|
|
|
return next(new Error("Invalid session!"))
|
|
|
|
redis.shard 'hget', USER_KEY, id, (err, jsonString) ->
|
|
|
|
if err then return next(err)
|
|
|
|
json = JSON.parse(jsonString)
|
|
|
|
return next(new Error("Invalid session!")) if !json
|
|
|
|
exports.getAuth json.name, (err, authLevel) ->
|
|
|
|
if err then return next(err)
|
|
|
|
json.authority = authLevel
|
|
|
|
return next(null, json)
|
|
|
|
|
|
|
|
setdatabasedata = (req, cookies, object, next) ->
|
|
|
|
username = object.username
|
|
|
|
id = object.external_id
|
|
|
|
admin = object.admin
|
|
|
|
mod = object.moderator
|
|
|
|
req.user = {}
|
|
|
|
req.user.token = cookies.get("nonce")
|
|
|
|
req.user.id = id
|
|
|
|
req.user.name = username
|
2016-02-19 23:54:42 +00:00
|
|
|
OWNERUSERNAMES = ["Deukhoofd", "thesuzerain"]
|
|
|
|
if username in OWNERUSERNAMES && admin == "true"
|
2016-02-01 22:19:30 +00:00
|
|
|
exports.setAuth username, exports.levels.OWNER
|
|
|
|
else if admin == "true"
|
|
|
|
exports.setAuth username, exports.levels.ADMIN
|
|
|
|
else if mod == "true"
|
|
|
|
exports.setAuth username, exports.levels.MOD
|
|
|
|
else
|
|
|
|
exports.setAuth username, exports.levels.USER
|
|
|
|
toJSON = {
|
|
|
|
name : username,
|
|
|
|
token : cookies.get("nonce")
|
|
|
|
id : id
|
|
|
|
}
|
|
|
|
redis.shard('hset', USER_KEY, id, JSON.stringify(toJSON), next)
|
|
|
|
|
|
|
|
|
|
|
|
authenticate = (req, next) ->
|
|
|
|
return next()
|
|
|
|
|
|
|
|
|
|
|
|
getparameters = (req) ->
|
|
|
|
return("1")
|
|
|
|
|
|
|
|
|
|
|
|
generateUsername = (req) ->
|
|
|
|
name = req.param('user')
|
|
|
|
return name if name
|
|
|
|
{SpeciesData} = require './xy/data'
|
|
|
|
randomName = (name for name of SpeciesData)
|
|
|
|
randomName = randomName[Math.floor(Math.random() * randomName.length)]
|
|
|
|
randomName = randomName.split(/\s+/)[0]
|
|
|
|
randomName += "Fan" + Math.floor(Math.random() * 10000)
|
|
|
|
randomName
|
|
|
|
|
|
|
|
generateId = (req) ->
|
|
|
|
req.param('id') || Math.floor(1000000 * Math.random())
|
|
|
|
|
|
|
|
generateUser = (req) ->
|
|
|
|
{id: generateId(req), username: generateUsername(req)}
|
|
|
|
|
|
|
|
# Authorization
|
|
|
|
|
|
|
|
exports.levels =
|
|
|
|
USER : 1
|
|
|
|
DRIVER : 2
|
|
|
|
MOD : 3
|
|
|
|
MODERATOR : 3
|
|
|
|
ADMIN : 4
|
|
|
|
ADMINISTRATOR : 4
|
|
|
|
OWNER : 5
|
|
|
|
|
|
|
|
LEVEL_VALUES = (value for key, value of exports.levels)
|
|
|
|
|
|
|
|
exports.getAuth = (id, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
redis.hget AUTH_KEY, id, (err, auth) ->
|
|
|
|
if err then return next(err)
|
|
|
|
auth = parseInt(auth, 10) || exports.levels.USER
|
|
|
|
next(null, auth)
|
|
|
|
|
|
|
|
exports.setAuth = (id, newAuthLevel, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
if newAuthLevel not in LEVEL_VALUES
|
|
|
|
next(new Error("Incorrect auth level: #{newAuthLevel}"))
|
|
|
|
redis.hset(AUTH_KEY, id, newAuthLevel, next)
|
|
|
|
|
|
|
|
# Ban
|
|
|
|
# Length is in seconds.
|
|
|
|
exports.ban = (id, reason, length, next) ->
|
|
|
|
id = id.toLowerCase()
|
|
|
|
key = "#{BANS_KEY}:#{id}"
|
|
|
|
if length > 0
|
|
|
|
redis.setex(key, length, reason, next)
|
|
|
|
else
|
|
|
|
redis.set(key, reason, next)
|
|
|
|
|
|
|
|
exports.unban = (id, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
redis.del("#{BANS_KEY}:#{id}", next)
|
|
|
|
|
|
|
|
exports.getBanReason = (id, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
redis.get("#{BANS_KEY}:#{id}", next)
|
|
|
|
|
|
|
|
exports.getBanTTL = (id, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
key = "#{BANS_KEY}:#{id}"
|
|
|
|
redis.exists key, (err, result) ->
|
|
|
|
if !result
|
|
|
|
# In older versions of Redis, TTL returns -1 if key doesn't exist.
|
|
|
|
return next(null, -2)
|
|
|
|
else
|
|
|
|
redis.ttl(key, next)
|
|
|
|
|
|
|
|
# Mute
|
|
|
|
# Length is in seconds.
|
|
|
|
exports.mute = (id, reason, length, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
key = "#{MUTE_KEY}:#{id}"
|
|
|
|
if length > 0
|
|
|
|
redis.setex(key, length, reason, next)
|
|
|
|
else
|
|
|
|
redis.set(key, reason, next)
|
|
|
|
|
|
|
|
exports.unmute = (id, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
key = "#{MUTE_KEY}:#{id}"
|
|
|
|
redis.del(key, next)
|
|
|
|
|
|
|
|
exports.getMuteTTL = (id, next) ->
|
|
|
|
id = String(id).toLowerCase()
|
|
|
|
key = "#{MUTE_KEY}:#{id}"
|
|
|
|
redis.exists key, (err, result) ->
|
|
|
|
if !result
|
|
|
|
# In older versions of Redis, TTL returns -1 if key doesn't exist.
|
|
|
|
return next(null, -2)
|
|
|
|
else
|
|
|
|
redis.ttl(key, next)
|