From 39e70bd60476a03cd63f03cbc36e5ec2dc4d91e2 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 16 Dec 2014 15:23:58 +0800 Subject: [PATCH] update INSTALL.md, refactor rpvhost, bitcoin, fixbugs --- INSTALL.md | 108 ++++++++++++++++-------- app.coffee | 3 +- core/cache.coffee | 4 +- core/interface/ComponentType.coffee | 36 ++------ core/interface/Node.coffee | 15 +++- core/interface/Plan.coffee | 12 ++- core/interface/Plugin.coffee | 28 +++++- core/model/Account.coffee | 5 +- core/model/Component.coffee | 33 ++++++-- core/pluggable.coffee | 21 +---- core/router/component.coffee | 3 + core/router/panel.coffee | 8 +- library/Mabolo.coffee | 4 + plugin/bitcoin/bitcoin.coffee | 2 +- plugin/bitcoin/index.coffee | 13 +-- plugin/bitcoin/locale/en.json | 3 +- plugin/bitcoin/locale/zh_CN.json | 3 +- plugin/bitcoin/view/payment_method.jade | 5 +- plugin/rpvhost/index.coffee | 9 +- 19 files changed, 197 insertions(+), 118 deletions(-) create mode 100644 core/router/component.coffee create mode 100644 library/Mabolo.coffee diff --git a/INSTALL.md b/INSTALL.md index 47fb424..a6bcf34 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -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 diff --git a/app.coffee b/app.coffee index 0620912..183fb2b 100755 --- a/app.coffee +++ b/app.coffee @@ -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 diff --git a/core/cache.coffee b/core/cache.coffee index 831ccc5..f2474d5 100644 --- a/core/cache.coffee +++ b/core/cache.coffee @@ -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() diff --git a/core/interface/ComponentType.coffee b/core/interface/ComponentType.coffee index aec0c1a..bf1ae08 100644 --- a/core/interface/ComponentType.coffee +++ b/core/interface/ComponentType.coffee @@ -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 diff --git a/core/interface/Node.coffee b/core/interface/Node.coffee index 489dd5e..b21436e 100644 --- a/core/interface/Node.coffee +++ b/core/interface/Node.coffee @@ -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) -> diff --git a/core/interface/Plan.coffee b/core/interface/Plan.coffee index 40c24f4..aafd141 100644 --- a/core/interface/Plan.coffee +++ b/core/interface/Plan.coffee @@ -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] diff --git a/core/interface/Plugin.coffee b/core/interface/Plugin.coffee index 0909575..86432e0 100644 --- a/core/interface/Plugin.coffee +++ b/core/interface/Plugin.coffee @@ -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 diff --git a/core/model/Account.coffee b/core/model/Account.coffee index db524af..28cb89e 100644 --- a/core/model/Account.coffee +++ b/core/model/Account.coffee @@ -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 diff --git a/core/model/Component.coffee b/core/model/Component.coffee index 6ffde7c..42523e7 100644 --- a/core/model/Component.coffee +++ b/core/model/Component.coffee @@ -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 diff --git a/core/pluggable.coffee b/core/pluggable.coffee index a2a1133..51f0f47 100644 --- a/core/pluggable.coffee +++ b/core/pluggable.coffee @@ -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 diff --git a/core/router/component.coffee b/core/router/component.coffee new file mode 100644 index 0000000..ee0ba93 --- /dev/null +++ b/core/router/component.coffee @@ -0,0 +1,3 @@ +{_, express} = app.libs + +module.exports = exports = express.Router() diff --git a/core/router/panel.coffee b/core/router/panel.coffee index 73b6bce..0f93f15 100644 --- a/core/router/panel.coffee +++ b/core/router/panel.coffee @@ -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 diff --git a/library/Mabolo.coffee b/library/Mabolo.coffee new file mode 100644 index 0000000..bb1adac --- /dev/null +++ b/library/Mabolo.coffee @@ -0,0 +1,4 @@ +module.exports = class Mabolo + constructor: (options) -> + + model: (name) -> diff --git a/plugin/bitcoin/bitcoin.coffee b/plugin/bitcoin/bitcoin.coffee index 16fda6d..bf09c4b 100644 --- a/plugin/bitcoin/bitcoin.coffee +++ b/plugin/bitcoin/bitcoin.coffee @@ -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', diff --git a/plugin/bitcoin/index.coffee b/plugin/bitcoin/index.coffee index c5eccd3..22b3561 100644 --- a/plugin/bitcoin/index.coffee +++ b/plugin/bitcoin/index.coffee @@ -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 diff --git a/plugin/bitcoin/locale/en.json b/plugin/bitcoin/locale/en.json index fbad29b..d4030f9 100644 --- a/plugin/bitcoin/locale/en.json +++ b/plugin/bitcoin/locale/en.json @@ -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 __short_order_id__" + "payment_details": "Bitcoin Payment __short_order_id__", + "no_address": "No Address" } } diff --git a/plugin/bitcoin/locale/zh_CN.json b/plugin/bitcoin/locale/zh_CN.json index 4b40c99..437e198 100644 --- a/plugin/bitcoin/locale/zh_CN.json +++ b/plugin/bitcoin/locale/zh_CN.json @@ -3,6 +3,7 @@ "view": { "payment_tips": "你可以直接向该地址发送比特币。在经过一次确认后,系统会实时地,自动为你折算充值金额,最小支付金额为 0.0005 BTC.", "exchange_rate_tips": "实时汇率:10 CNY = __rate10__ BTC", - "payment_details": "比特币支付 __short_order_id__" + "payment_details": "比特币支付 __short_order_id__", + "no_address": "暂无地址" } } diff --git a/plugin/bitcoin/view/payment_method.jade b/plugin/bitcoin/view/payment_method.jade index 3ae8b48..e9a6b1e 100644 --- a/plugin/bitcoin/view/payment_method.jade +++ b/plugin/bitcoin/view/payment_method.jade @@ -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') diff --git a/plugin/rpvhost/index.coffee b/plugin/rpvhost/index.coffee index 009640e..7454e64 100644 --- a/plugin/rpvhost/index.coffee +++ b/plugin/rpvhost/index.coffee @@ -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