update INSTALL.md, refactor rpvhost, bitcoin, fixbugs

This commit is contained in:
jysperm
2014-12-16 15:23:58 +08:00
parent d86d33e3bd
commit 39e70bd604
19 changed files with 197 additions and 118 deletions

View File

@@ -6,43 +6,15 @@
apt-get update
apt-get upgrade
vi /etc/hostname
vi /etc/hosts
apt-get install mongodb=1:2.4.9-1ubuntu2
apt-get install python g++ make nodejs git nginx redis-server supervisor
npm install coffee-script -g
mongo
use admin
db.addUser({user: 'rpadmin', pwd: 'password', roles: ['readWriteAnyDatabase', 'userAdminAnyDatabase', 'dbAdminAnyDatabase', 'clusterAdmin']})
use RootPanel
db.addUser({user: 'rpadmin', pwd: 'password', roles: ['readWrite']})
vi /etc/mongodb.conf
auth = true
noprealloc = true
smallfiles = true
vi /etc/redis/redis.conf
requirepass password
rm /etc/nginx/sites-enabled/default
vi /etc/nginx/sites-enabled/rpadmin
ssl_certificate /home/rpadmin/rpvhost.crt;
ssl_certificate_key /home/rpadmin/keys/rpvhost.key;
ssl_session_cache shared:SSL:10m;
server {
listen 80 default_server;
listen 443 ssl default_server;
listen [::]:80 default_server ipv6only=on;
rewrite .* $scheme://rp.rpvhost.net/#redirect redirect;
@@ -50,7 +22,6 @@
server {
listen 80;
listen 443 ssl;
server_name rp.rpvhost.net;
@@ -67,8 +38,6 @@
useradd -m rpadmin
usermod -G rpadmin -a www-data
mkdir -m 750 /home/rpadmin/keys
vi /etc/sudoers
rpadmin ALL=(ALL) NOPASSWD: ALL
@@ -99,10 +68,70 @@
redirect_stderr = true
user = rpadmin
service nginx restart
service mongodb restart
service redis-server restart
service supervisor restart
### Optional Security Settings
mongo
use admin
db.addUser({user: 'rpadmin', pwd: 'password', roles: ['readWriteAnyDatabase', 'userAdminAnyDatabase', 'dbAdminAnyDatabase', 'clusterAdmin']})
use RootPanel
db.addUser({user: 'rpadmin', pwd: 'password', roles: ['readWrite']})
vi /etc/mongodb.conf
auth = true
vi /etc/redis/redis.conf
requirepass password
rm /etc/nginx/sites-enabled/default
### Optional Performance Settings
vi /etc/hostname
vi /etc/hosts
vi /etc/mongodb.conf
noprealloc = true
smallfiles = true
### Optional SSL Settings
vi /etc/nginx/sites-enabled/rpadmin
ssl_certificate /home/rpadmin/rpvhost.crt;
ssl_certificate_key /home/rpadmin/keys/rpvhost.key;
ssl_session_cache shared:SSL:10m;
server {
listen 80 default_server;
listen 443 ssl default_server;
listen [::]:80 default_server ipv6only=on;
rewrite .* $scheme://rp.rpvhost.net/#redirect redirect;
}
server {
listen 80;
listen 443 ssl;
server_name rp.rpvhost.net;
location ~ /\.git {
deny all;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://unix:/home/rpadmin/rootpanel.sock:/;
}
}
mkdir -m 750 /home/rpadmin/keys
### Clusters
@@ -111,7 +140,7 @@
su rpadmin
mkdir ~/.ssh
echo 'master key' >> ~/.ssh/authorized_keys
echo 'Master SSH Public Key' >> ~/.ssh/authorized_keys
chmod -R 700 ~/.ssh
### Plugins
@@ -180,3 +209,10 @@
# Node.js
npm install forever gulp mocha harp bower -g
### Restart Services
service nginx restart
service mongodb restart
service redis-server restart
service supervisor restart

View File

@@ -134,6 +134,7 @@ app.express.use app.middleware.accountHelpers
app.express.set 'views', path.join(__dirname, 'core/view')
app.express.set 'view engine', 'jade'
app.express.use '/component', require './core/router/component'
app.express.use '/account', require './core/router/account'
app.express.use '/billing', require './core/router/billing'
app.express.use '/ticket', require './core/router/ticket'
@@ -144,7 +145,7 @@ app.express.use '/panel', require './core/router/panel'
app.i18n.init()
app.interfaces.Plan.initPlans()
app.interfaces.Node.initNodes()
app.pluggable.initPlugins()
app.interfaces.Plugin.initPlugins()
app.express.get '/', (req, res) ->
unless res.headerSent

View File

@@ -3,9 +3,7 @@ getParameterNames = require 'get-parameter-names'
CounterCache = require 'counter-cache'
_ = require 'underscore'
config = require '../config'
{redis} = app
{redis, config} = app
exports.counter = new CounterCache()

View File

@@ -1,8 +1,9 @@
{_, async} = app.libs
{logger} = app
{Node} = app.interfaces
{Account, Component} = app.models
Node = require './Node'
module.exports = class ComponentType
@component_types = {}
@@ -19,29 +20,6 @@ module.exports = class ComponentType
initialize: (component, callback) ->
callback()
populateComponent: (component) ->
if component.toObject
component = component.toObject()
async.parallel
account: (callback) ->
Account.findById component.account_id, callback
coworkers: (callback) ->
async.each component.coworkers, (coworker, callback) ->
Account.findById coworker.account_id, (err, account) ->
callback _.extend coworker,
account: account
, callback
, (err, result) ->
{account, coworkers} = result
callback _.extend component,
account: account
coworkers: coworkers
physical_node: Node.nodes[component.physical_node]
# @param callback(err, component)
createComponent: (account, info, callback) ->
{name, physical_node} = info
@@ -54,18 +32,18 @@ module.exports = class ComponentType
physical_node: physical_node
dependencies: {}
, (err, component) =>
@populateComponent component, (component) =>
@initialize component, (err) =>
component.populateComponent (populated_component) =>
@initialize populated_component, (err) =>
return callback err if err
Component.markAsStatus component, 'running', callback
component.markAsStatus 'running', callback
# @param callback(err)
destroyComponent: (component, callback) ->
Component.markAsStatus component, 'destroying', (err) =>
component.markAsStatus 'destroying', (err) =>
return callback err if err
@populateComponent component, (component) =>
component.populateComponent (component) =>
@destroy component, (err) =>
return callback err if err

View File

@@ -1,3 +1,7 @@
{_, child_process, async} = app.libs
{config, logger} = app
{available_plugins} = config.plugin
module.exports = class Node
info: null
name: null
@@ -7,15 +11,20 @@ module.exports = class Node
@initNodes: ->
for name, info of config.nodes
@nodes[name] = new @constructor _.extend info,
@nodes[name] = new Node _.extend info,
name: name
@get: (name) ->
return @nodes[name]
constructor: (@info) ->
@name = @info.name
@master = true if @info.master
_.extend @, info
for component_type in @available_components
unless component_type in available_plugins
err = new Error "Node:#{@name} include unknown Component:#{component_type}"
logger.fatal err
throw err
# @param callback(err, stdout, stderr)
runCommand: (command, callback) ->

View File

@@ -1,9 +1,14 @@
{_} = app.libs
{config, logger} = app
{available_plugins} = config.plugin
module.exports = class Plan
@plans = {}
@initPlans: ->
for name, info of config.plans
@plans[name] = new @constructor _.extend info,
@plans[name] = new Plan _.extend info,
name: name
@get: (name) ->
@@ -13,6 +18,11 @@ module.exports = class Plan
_.extend @, info
for component_type, info of @available_components
unless component_type in available_plugins
err = new Error "Plan:#{@name} include unknown Component:#{component_type}"
logger.fatal err
throw err
if info.default
unless _.isArray info.default
info.default = [info.default]

View File

@@ -1,13 +1,35 @@
{_, path, fs, jade, harp} = app.libs
{config, logger, i18n} = app
{available_plugins} = config.plugin
pluggable = require '../pluggable'
module.exports = class Plugin
info: null
name: null
config: null
path: null
@plugins = {}
@get: (name) ->
return @plugins[name]
@initPlugins: ->
for name in available_plugins
Plugin.plugins[name] = require path.join __dirname, '../../plugin', name
constructor: (@info) ->
@name = info.name
@config = config.plugins[@name] ? {}
@path = path.join __dirname, '../plugin', @name
@path = path.join __dirname, '../../plugin', @name
if info.dependencies
for dependence in plugin.dependencies
unless dependence in available_plugins
err = new Error "Plugin:#{@name} is Dependent on Plugin:#{dependence} but not load"
logger.fatal err
throw err
for name, payload of info.register_hooks ? {}
if payload.register_if
@@ -69,7 +91,7 @@ module.exports = class Plugin
return t.apply @, _.toArray(arguments)
render: (name, req, view_data, callback) ->
template_path = path.join __dirname, '../plugin', @name, 'view', "#{name}.jade"
template_path = path.join __dirname, '../../plugin', @name, 'view', "#{name}.jade"
locals = _.extend _.clone(req.res.locals), view_data,
account: req.account
@@ -80,7 +102,7 @@ module.exports = class Plugin
callback html
renderTemplate: (name, view_data, callback) ->
template_path = path.join __dirname, '../plugin', @name, 'view', name
template_path = path.join __dirname, '../../plugin', @name, 'view', name
fs.readFile template_path, (err, template_file) ->
callback _.template(template_file.toString()) view_data

View File

@@ -1,11 +1,11 @@
{pluggable, utils, config, models} = app
{_, async, mongoose, mongooseUniqueValidator} = app.libs
{Financial, SecurityLog, Component} = app.models
{Plan} = app.interfaces
Plan = require '../interface/Plan'
process.nextTick ->
{Financial, SecurityLog, Component} = app.models
{Plan} = app.interfaces
Token = mongoose.Schema
type:
@@ -88,6 +88,7 @@ Account = mongoose.Schema
pluggable:
type: Object
default: {}
resources_limit:
type: Object

View File

@@ -1,4 +1,5 @@
{_, ObjectId, mongoose} = app.libs
{_, ObjectId, mongoose, async} = app.libs
{Account} = app.models
Component = mongoose.Schema
component_type:
@@ -43,10 +44,32 @@ Component = mongoose.Schema
type: String
enum: []
Component.statics.markAsStatus = (component, status, callback) ->
@findByIdAndUpdate component._id,
status: status
, callback
Component.methods.populateComponent = (callback) ->
component = @toObject()
async.parallel
account: (callback) ->
Account.findById component.account_id, callback
coworkers: (callback) ->
async.each component.coworkers, (coworker, callback) ->
Account.findById coworker.account_id, (err, account) ->
callback _.extend coworker,
account: account
, callback
, (err, result) ->
{account, coworkers} = result
callback _.extend component,
account: account
coworkers: coworkers
component_type: ComponentType.get component.component_type
physical_node: Node.get component.physical_node
Component.methods.markAsStatus = (status, callback) ->
@status = status
@save callback
_.extend app.models,
Component: mongoose.model 'Component', Component

View File

@@ -1,6 +1,8 @@
{async, path, harp, jade, tmp, fs, _, child_process} = app.libs
{i18n, config, logger} = app
Plugin = require './interface/Plugin'
pluggable = exports
pluggable.hooks =
@@ -28,8 +30,8 @@ pluggable.hooks =
billing:
# type
# widget_generator: function(req, callback(html)),
# details_message: function(req, deposit_log, callback(l_details))
# widgetGenerator: function(req, callback(html)),
# detailsMessage: function(req, deposit_log, callback(l_details))
payment_methods: []
view:
@@ -66,18 +68,3 @@ pluggable.selectHookPath = (name) ->
pluggable.selectHook = (name) ->
return pluggable.selectHookPath name
pluggable.initPlugins = ->
plugins_name = config.plugin.available_plugins
for name in plugins_name
plugin = require path.join __dirname, '../plugin', name
if plugin.dependencies
for dependence in plugin.dependencies
unless dependence in plugins_name
err = new Error "#{name} is Dependent on #{dependence} but not load"
logger.fatal err
throw err
exports.plugins[name] = plugin

View File

@@ -0,0 +1,3 @@
{_, express} = app.libs
module.exports = exports = express.Router()

View File

@@ -13,7 +13,7 @@ exports.get '/financials', (req, res) ->
async.parallel
payment_methods: (callback) ->
async.map pluggable.selectHook('billing.payment_methods'), (hook, callback) ->
hook.widget_generator req, (html) ->
hook.widgetGenerator req, (html) ->
callback null, html
, callback
@@ -29,13 +29,13 @@ exports.get '/financials', (req, res) ->
async.map deposit_logs, (deposit_log, callback) ->
deposit_log = deposit_log.toObject()
matched_hook = _.find pluggable.selectHook('view.pay.display_payment_details'), (hook) ->
return hook?.type == deposit_log.payload.type
matched_hook = _.find pluggable.selectHook('billing.payment_methods'), (hook) ->
return hook.type == deposit_log.payload.type
unless matched_hook
return callback null, deposit_log
matched_hook.filter req, deposit_log, (payment_details) ->
matched_hook.detailsMessage req, deposit_log, (payment_details) ->
deposit_log.payment_details = payment_details
callback null, deposit_log

4
library/Mabolo.coffee Normal file
View File

@@ -0,0 +1,4 @@
module.exports = class Mabolo
constructor: (options) ->
model: (name) ->

View File

@@ -4,7 +4,7 @@
# @param callback(address)
exports.genAddress = (bitcoin_secret, callback) ->
if config.plugins.bitcoin.coinbase_api_key == 'coinbase-simple-api-key'
app.deprecate 'Invalid coinbase-simple-api-key'
logger.wran plugin: 'bitcoin', new Error 'Invalid coinbase-simple-api-key'
return callback()
request 'https://coinbase.com/api/v1/account/generate_receive_address',

View File

@@ -1,7 +1,7 @@
{jade, path} = app.libs
{Account} = app.models
{pluggable, config, utils} = app
{Plugin} = app.classes
{Plugin} = app.interfaces
bitcoin = require './bitcoin'
@@ -25,16 +25,17 @@ bitcoinPlugin = module.exports = new Plugin
'billing.payment_methods':
type: 'bitcoin'
widget_generator: (req, callback) ->
widgetGenerator: (req, callback) ->
bitcoin.getExchangeRate config.billing.currency, (rate) ->
bitcoinPlugin.render 'payment_method', req,
exchange_rate: rate
, callback
details_message: (req, deposit_log, callback) ->
detailsMessage: (req, deposit_log, callback) ->
callback bitcoinPlugin.getTranslator(req) 'view.payment_details',
order_id: deposit_log.payload.order_id
short_order_id: deposit_log.payload.order_id[0 .. 40]
short_order_id: deposit_log.payload.order_id[... 40]
initialize: ->
app.express.post '/bitcoin/coinbase_callback', (req, res) ->
@@ -42,10 +43,10 @@ bitcoinPlugin = module.exports = new Plugin
'pluggable.bitcoin.bitcoin_deposit_address': req.body.address
, (err, account) ->
unless account
return res.send 400, 'Invalid Address'
return res.status(400).send 'Invalid Address'
unless req.query.secret == account.pluggable.bitcoin.bitcoin_secret
return res.send 400, 'Invalid Secret'
return res.status(400).send 'Invalid Secret'
bitcoin.getExchangeRate config.billing.currency, (rate) ->
amount = req.body.amount / rate

View File

@@ -3,6 +3,7 @@
"view": {
"payment_tips": "You can transfer directly to this address. system will automatically recharge for you after first confirmed. The minimum payment amount: 0.0005 BTC.",
"exchange_rate_tips": "Real-time Exchange Rates: 10 CNY = __rate10__ BTC",
"payment_details": "Bitcoin Payment <a href='https://blockchain.info/tx/__order_id__'>__short_order_id__</a>"
"payment_details": "Bitcoin Payment <a href='https://blockchain.info/tx/__order_id__'>__short_order_id__</a>",
"no_address": "No Address"
}
}

View File

@@ -3,6 +3,7 @@
"view": {
"payment_tips": "你可以直接向该地址发送比特币。在经过一次确认后,系统会实时地,自动为你折算充值金额,最小支付金额为 0.0005 BTC.",
"exchange_rate_tips": "实时汇率10 CNY = __rate10__ BTC",
"payment_details": "比特币支付 <a href='https://blockchain.info/tx/__order_id__'>__short_order_id__</a>"
"payment_details": "比特币支付 <a href='https://blockchain.info/tx/__order_id__'>__short_order_id__</a>",
"no_address": "暂无地址"
}
}

View File

@@ -2,4 +2,7 @@ div
h2= t('')
p= t('view.payment_tips')
p= t('view.exchange_rate_tips', {rate10: (exchange_rate * 10).toFixed(4)})
pre= account.pluggable.bitcoin.bitcoin_deposit_address
if account.pluggable.bitcoin
pre= account.pluggable.bitcoin.bitcoin_deposit_address
else
pre= t('view.no_address')

View File

@@ -1,6 +1,6 @@
{jade, path, fs} = app.libs
{path, fs} = app.libs
{pluggable, config} = app
{Plugin} = app.classes
{Plugin} = app.interfaces
rpvhostPlugin = module.exports = new Plugin
name: 'rpvhost'
@@ -21,10 +21,11 @@ rpvhostPlugin = module.exports = new Plugin
'billing.payment_methods':
type: 'taobao'
widget_generator: (req, callback) ->
widgetGenerator: (req, callback) ->
rpvhostPlugin.render 'payment_method', req, {}, callback
details_message: (req, deposit_log, callback) ->
detailsMessage: (req, deposit_log, callback) ->
callback rpvhostPlugin.getTranslator(req) 'view.payment_details',
order_id: deposit_log.payload.order_id