mirror of
https://github.com/HackPlan/RootPanel.git
synced 2026-04-01 10:43:02 +08:00
fix unit test
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.11
|
||||
- 0.10
|
||||
- 0.12
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
* (新增) 帐号安全事件记录
|
||||
* (新增) 兑换代码
|
||||
* (新增) 管理员面板:删除账户
|
||||
* (改进) 在 Token 中记录 IP, UA, 和最后使用时间。
|
||||
* (改进) 在 Token 中记录 IP, UA, 和最后使用时间
|
||||
|
||||
18 commits, 27 changed files with 366 additions and 29 deletions, by 1 contributors: jysperm.
|
||||
|
||||
|
||||
@@ -30,11 +30,10 @@ harp = require 'harp'
|
||||
|
||||
{_, fs, path, express} = app.libs
|
||||
|
||||
unless global.config
|
||||
if fs.existsSync "#{__dirname}/config.coffee"
|
||||
config = require './config'
|
||||
else
|
||||
config = require './sample/core.config.coffee'
|
||||
if fs.existsSync "#{__dirname}/config.coffee"
|
||||
config = require './config'
|
||||
else
|
||||
config = require './sample/core.config.coffee'
|
||||
|
||||
app.package = require './package'
|
||||
utils = require './core/utils'
|
||||
|
||||
@@ -29,7 +29,7 @@ exports.reqHelpers = (req, res, next) ->
|
||||
req.createSecurityLog = (type, payload, options) ->
|
||||
SecurityLog.createLog
|
||||
account: options?.account ? req.account
|
||||
token: token
|
||||
token: options?.token ? req.token
|
||||
type: type
|
||||
, payload
|
||||
|
||||
@@ -40,12 +40,10 @@ exports.reqHelpers = (req, res, next) ->
|
||||
if name?.message
|
||||
name = name.message
|
||||
|
||||
param ?= {}
|
||||
|
||||
if req.method in ['GET', 'HEAD', 'OPTIONS']
|
||||
res.status(status).send name.toString()
|
||||
else
|
||||
res.status(status).json _.extend param,
|
||||
res.status(status).json _.extend {}, param,
|
||||
error: name.toString()
|
||||
|
||||
res.createCookie = (name, value) ->
|
||||
@@ -116,18 +114,13 @@ exports.csrf = ->
|
||||
validator()
|
||||
|
||||
exports.authenticate = (req, res, next) ->
|
||||
code = req.getTokenCode()
|
||||
|
||||
unless code
|
||||
return next()
|
||||
|
||||
Account.authenticate(code).then ({token, account}) ->
|
||||
if token and token.type == 'full_access'
|
||||
Account.authenticate(req.getTokenCode()).then ({token, account}) ->
|
||||
if token?.type == 'full_access'
|
||||
_.extend req,
|
||||
token: token
|
||||
account: account
|
||||
else
|
||||
next()
|
||||
|
||||
.finally next
|
||||
|
||||
exports.accountHelpers = (req, res, next) ->
|
||||
_.extend res,
|
||||
|
||||
@@ -74,14 +74,27 @@ Account = mabolo.model 'Account',
|
||||
type: Date
|
||||
default: -> new Date()
|
||||
|
||||
Account.ensureIndex
|
||||
username: 1
|
||||
,
|
||||
unique: true
|
||||
|
||||
Account.ensureIndex
|
||||
email: 1
|
||||
,
|
||||
unique: true
|
||||
|
||||
Account.ensureIndex
|
||||
'tokens.code': 1
|
||||
,
|
||||
unique: true
|
||||
|
||||
Token::revoke = ->
|
||||
@parent().update
|
||||
$pull:
|
||||
tokens:
|
||||
code: @code
|
||||
|
||||
Account.ensureIndex
|
||||
|
||||
Account.register = ({username, email, password}) ->
|
||||
password_salt = utils.randomSalt()
|
||||
password = utils.hashPassword password, password_salt
|
||||
@@ -89,7 +102,7 @@ Account.register = ({username, email, password}) ->
|
||||
avatar_url = '//cdn.v2ex.com/gravatar/' + utils.md5(email)
|
||||
|
||||
account = new Account
|
||||
email: email
|
||||
email: email.toLowerCase()
|
||||
username: username
|
||||
password: password
|
||||
password_salt: password_salt
|
||||
@@ -120,7 +133,7 @@ Account.search = (identification) ->
|
||||
|
||||
Account.authenticate = (token_code) ->
|
||||
@findOneAndUpdate(
|
||||
'tokens.token': token_code
|
||||
'tokens.code': token_code
|
||||
,
|
||||
$set:
|
||||
'tokens.$.updated_at': new Date()
|
||||
|
||||
@@ -26,7 +26,7 @@ exports.get '/session_info/', (req, res) ->
|
||||
|
||||
if req.account
|
||||
_.extend response,
|
||||
id: req.account.id
|
||||
account_id: req.account._id
|
||||
username: req.account.username
|
||||
preferences: req.account.preferences
|
||||
|
||||
@@ -35,11 +35,17 @@ exports.get '/session_info/', (req, res) ->
|
||||
exports.post '/register', (req, res) ->
|
||||
Account.register(req.body).then (account) ->
|
||||
res.createToken account
|
||||
.catch res.error
|
||||
.catch (err) ->
|
||||
if err.message.match /duplicate.*username/
|
||||
res.error 'username_exist'
|
||||
else if err.message.match /Validating.*email/
|
||||
res.error 'invalid_email'
|
||||
else
|
||||
res.error err
|
||||
|
||||
exports.post '/login', (req, res) ->
|
||||
Account.search(req.body.username).then (account) ->
|
||||
if account?.matchPassword req.body.password
|
||||
unless account?.matchPassword req.body.password
|
||||
throw new Error 'wrong_password'
|
||||
|
||||
res.createCookie 'language', account.preferences.language
|
||||
@@ -49,7 +55,11 @@ exports.post '/login', (req, res) ->
|
||||
account: account
|
||||
token: token
|
||||
|
||||
.catch res.error
|
||||
.catch (err) ->
|
||||
if err.message.match /must be a/
|
||||
res.error 'wrong_password'
|
||||
else
|
||||
res.error err
|
||||
|
||||
exports.post '/logout', requireAuthenticate, (req, res) ->
|
||||
req.token.revoke().then ->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe 'account.register.test', ->
|
||||
describe 'account.register', ->
|
||||
agent = null
|
||||
csrf_token = null
|
||||
|
||||
@@ -28,7 +28,7 @@ describe 'account.register.test', ->
|
||||
.expect 200
|
||||
.end (err, res) ->
|
||||
res.body.csrf_token.should.be.exist
|
||||
csrf_token = res.body.csrf_token
|
||||
{csrf_token} = res.body
|
||||
done err
|
||||
|
||||
it 'POST register', (done) ->
|
||||
@@ -45,8 +45,8 @@ describe 'account.register.test', ->
|
||||
.expect 200
|
||||
.expect 'set-cookie', /token=/
|
||||
.end (err, res) ->
|
||||
res.body.id.should.have.length 24
|
||||
account_id = res.body.id
|
||||
res.body.account_id.should.have.length 24
|
||||
{account_id} = res.body
|
||||
done err
|
||||
|
||||
it 'POST register with existed username', (done) ->
|
||||
@@ -82,7 +82,7 @@ describe 'account.register.test', ->
|
||||
.expect 200
|
||||
.expect 'set-cookie', /token=/
|
||||
.end (err, res) ->
|
||||
res.body.id.should.be.equal account_id
|
||||
res.body.account_id.should.be.equal account_id
|
||||
res.body.token.should.be.exist
|
||||
done err
|
||||
|
||||
@@ -99,7 +99,7 @@ describe 'account.register.test', ->
|
||||
agent.post '/account/logout'
|
||||
.send
|
||||
csrf_token: csrf_token
|
||||
.expect 200
|
||||
.expect 204
|
||||
.expect 'set-cookie', /token=;/
|
||||
.end done
|
||||
|
||||
@@ -112,7 +112,7 @@ describe 'account.register.test', ->
|
||||
.expect 200
|
||||
.expect 'set-cookie', /token=/
|
||||
.end (err, res) ->
|
||||
res.body.id.should.be.equal account_id
|
||||
res.body.account_id.should.be.equal account_id
|
||||
res.body.token.should.be.exist
|
||||
done err
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
describe 'cache', ->
|
||||
cache = null
|
||||
redis = null
|
||||
|
||||
before ->
|
||||
{cache, redis} = app
|
||||
|
||||
describe 'hashKey', ->
|
||||
it 'should success', ->
|
||||
cache.hashKey('cache_key').should.be.equal 'RP:cache_key'
|
||||
cache.hashKey({param: 'value'}).should.equal 'RP:{"param":"value"}'
|
||||
cache.hashKey({a: 'b', c: 'd', e: 2}).should.equal 'RP:{"a":"b","c":"d","e":2}'
|
||||
cache.hashKey({e: 2, a: 'b', c: 'd'}).should.equal 'RP:{"a":"b","c":"d","e":2}'
|
||||
|
||||
describe 'try', ->
|
||||
it 'should success when cache not exist', (done) ->
|
||||
cache.try 'test_key', (SET, key) ->
|
||||
key.should.be.equal 'test_key'
|
||||
SET 'test_key_value'
|
||||
, (value) ->
|
||||
value.should.be.equal 'test_key_value'
|
||||
|
||||
redis.get 'RP:test_key', (err, value) ->
|
||||
value.should.be.equal 'test_key_value'
|
||||
done err
|
||||
|
||||
it 'should success when cache exist', (done) ->
|
||||
cache.try 'test_key', ->
|
||||
throw new Error 'should not be called'
|
||||
, (value) ->
|
||||
value.should.be.equal 'test_key_value'
|
||||
done()
|
||||
|
||||
it 'should success with param', (done) ->
|
||||
cache.try
|
||||
key: 'test2'
|
||||
object_id: 10
|
||||
, (SET, key) ->
|
||||
key.object_id.should.be.equal 10
|
||||
SET 100
|
||||
, (value) ->
|
||||
value.should.be.equal 100
|
||||
done()
|
||||
|
||||
it 'should success with JSON and SETEX', (done) ->
|
||||
cache.try 'test_key3', (SETEX) ->
|
||||
SETEX
|
||||
value_of: 'test_key3'
|
||||
, 60
|
||||
|
||||
, (value) ->
|
||||
value.value_of.should.be.equal 'test_key3'
|
||||
|
||||
redis.ttl 'RP:test_key3', (err, seconds) ->
|
||||
seconds.should.above 0
|
||||
cache.refresh 'test_key3', done
|
||||
|
||||
describe 'refresh', ->
|
||||
it 'should success', (done) ->
|
||||
cache.refresh 'test_key', ->
|
||||
redis.get 'RP:test_key', (err, value) ->
|
||||
expect(value).to.not.exist
|
||||
done()
|
||||
|
||||
it 'should success with param', (done) ->
|
||||
cache.refresh
|
||||
key: 'test2'
|
||||
object_id: 10
|
||||
, ->
|
||||
redis.get
|
||||
key: 'test2'
|
||||
object_id: 10
|
||||
, (err, value) ->
|
||||
expect(value).to.not.exist
|
||||
done()
|
||||
@@ -1,98 +0,0 @@
|
||||
express = require 'express'
|
||||
bodyParser = require 'body-parser'
|
||||
cookieParser = require 'cookie-parser'
|
||||
|
||||
Account = null
|
||||
middleware = null
|
||||
|
||||
describe 'middleware', ->
|
||||
before ->
|
||||
require '../../app'
|
||||
{middleware} = app
|
||||
{Account} = app.models
|
||||
|
||||
describe 'errorHandling', ->
|
||||
it 'should work with param', (done) ->
|
||||
server = express()
|
||||
server.use middleware.errorHandling
|
||||
|
||||
server.use (req, res) ->
|
||||
res.error 'error_name',
|
||||
message: 'error_message'
|
||||
|
||||
supertest server
|
||||
.get '/'
|
||||
.expect 400
|
||||
.end (err, res) ->
|
||||
res.body.error.should.be.equal 'error_name'
|
||||
res.body.message.should.be.equal 'error_message'
|
||||
done err
|
||||
|
||||
it 'should work with status code', (done) ->
|
||||
server = express()
|
||||
server.use middleware.errorHandling
|
||||
|
||||
server.use (req, res) ->
|
||||
res.error 403, 'error_name'
|
||||
|
||||
supertest server
|
||||
.get '/'
|
||||
.expect 403
|
||||
.end (err, res) ->
|
||||
res.body.error.should.be.equal 'error_name'
|
||||
done err
|
||||
|
||||
describe 'session', ->
|
||||
it 'session should be available', (done) ->
|
||||
server = express()
|
||||
server.use middleware.session()
|
||||
|
||||
server.use (req, res, next) ->
|
||||
req.session.should.be.exist
|
||||
req.session.test_field = 'test_value'
|
||||
next()
|
||||
|
||||
server.use (req, res) ->
|
||||
req.session.test_field.should.be.equal 'test_value'
|
||||
res.send()
|
||||
|
||||
supertest server
|
||||
.get '/'
|
||||
.expect 200
|
||||
.end done
|
||||
|
||||
describe 'csrf', ->
|
||||
server = express()
|
||||
agent = supertest.agent server
|
||||
token = null
|
||||
|
||||
before ->
|
||||
server.use bodyParser.json()
|
||||
server.use cookieParser()
|
||||
server.use middleware.session()
|
||||
server.use middleware.errorHandling
|
||||
server.use middleware.csrf()
|
||||
|
||||
server.use (req, res) ->
|
||||
req.session.csrf_token.should.be.exist
|
||||
res.json
|
||||
csrf_token: req.session.csrf_token
|
||||
|
||||
it 'should ignore GET request', (done) ->
|
||||
agent.get '/'
|
||||
.expect 200
|
||||
.end (err, res) ->
|
||||
token = res.body.csrf_token
|
||||
done err
|
||||
|
||||
it 'should reject with no token', (done) ->
|
||||
agent.post '/'
|
||||
.expect 403
|
||||
.end done
|
||||
|
||||
it 'should success with token', (done) ->
|
||||
agent.post '/'
|
||||
.send
|
||||
csrf_token: token
|
||||
.expect 200
|
||||
.end done
|
||||
@@ -44,74 +44,6 @@ describe 'utils', ->
|
||||
utils.rx.url.test('https://jysperm.me/about').should.be.ok
|
||||
utils.rx.url.test('ssh://jysperm.me').should.not.be.ok
|
||||
|
||||
it 'sha256', ->
|
||||
expect(utils.sha256()).to.be.not.exist
|
||||
sha256 = '0554af0347e02ce032a1c6a292ed7e704c734ce338e71b39e21a73fa9b4d8fea'
|
||||
utils.sha256('jysperm').should.be.equal sha256
|
||||
|
||||
it 'md5', ->
|
||||
expect(utils.md5()).to.be.not.exist
|
||||
utils.md5('jysperm').should.be.equal 'ff42fce67bcd7dd060293d3cb42638ba'
|
||||
|
||||
it 'randomSalt', ->
|
||||
random1 = utils.randomSalt()
|
||||
random2 = utils.randomSalt()
|
||||
|
||||
random1.should.have.length 64
|
||||
random1.should.be.not.equal random2
|
||||
|
||||
it 'randomString', ->
|
||||
random1 = utils.randomString 10
|
||||
random2 = utils.randomString 10
|
||||
random3 = utils.randomString 20
|
||||
|
||||
random1.should.have.length 10
|
||||
random1.should.be.not.equal random2
|
||||
random3.should.have.length 20
|
||||
|
||||
it 'hashPassword', ->
|
||||
sha256 = '016899230b83a136fea361680e3a0c687440cd866ae67448fa72b007b04269dc'
|
||||
utils.hashPassword('passwd', 'salt').should.be.equal sha256
|
||||
|
||||
describe 'wrapAsync', ->
|
||||
it 'should work with basic usage', (done) ->
|
||||
func = (callback) ->
|
||||
callback 'result'
|
||||
|
||||
utils.wrapAsync(func) (err, result) ->
|
||||
expect(err).to.be.not.exist
|
||||
result.should.be.equal 'result'
|
||||
|
||||
done()
|
||||
|
||||
it 'should work with async', (done) ->
|
||||
func = (callback) ->
|
||||
callback 'result'
|
||||
|
||||
async.parallel [
|
||||
utils.wrapAsync func
|
||||
utils.wrapAsync func
|
||||
], (err, result) ->
|
||||
expect(err).to.be.not.exist
|
||||
result[0].should.be.equal 'result'
|
||||
result[1].should.be.equal 'result'
|
||||
|
||||
done()
|
||||
|
||||
describe 'pickErrorName', ->
|
||||
it 'should work with two errors', ->
|
||||
error =
|
||||
errors:
|
||||
email:
|
||||
message: 'invalid_email'
|
||||
|
||||
username:
|
||||
message: 'invalid_username'
|
||||
|
||||
expect(utils.pickErrorName(error) in [
|
||||
'invalid_email', 'invalid_username'
|
||||
]).to.be.ok
|
||||
|
||||
it 'should work with no error', ->
|
||||
expect(utils.pickErrorName({})).to.be.null
|
||||
expect(utils.pickErrorName({errors: {}})).to.be.null
|
||||
|
||||
Reference in New Issue
Block a user