mirror of
https://github.com/HackPlan/RootPanel.git
synced 2026-01-12 22:27:09 +08:00
improve shadowsocks
This commit is contained in:
@@ -45,6 +45,11 @@ exports.hooks =
|
||||
# path
|
||||
styles: []
|
||||
|
||||
admin:
|
||||
# generator: function(req, callback)
|
||||
sidebars: _.extend [],
|
||||
global_event: true
|
||||
|
||||
panel:
|
||||
# path
|
||||
scripts: []
|
||||
|
||||
@@ -9,9 +9,15 @@ exports.use requireAdminAuthenticate
|
||||
|
||||
exports.get '/', (req, res) ->
|
||||
Account.find {}, (err, accounts) ->
|
||||
return res.render 'admin',
|
||||
accounts: accounts
|
||||
coupon_code_types: _.keys config.coupons_meta
|
||||
async.map pluggable.selectHook(null, 'view.admin.sidebars'), (hook, callback) ->
|
||||
hook.generator req, (html) ->
|
||||
callback null, html
|
||||
|
||||
, (err, sidebars_html) ->
|
||||
res.render 'admin',
|
||||
accounts: accounts
|
||||
sidebars_html: sidebars_html
|
||||
coupon_code_types: _.keys config.coupons_meta
|
||||
|
||||
exports.get '/account_details', (req, res) ->
|
||||
Account.findById req.query.account_id, (err, account) ->
|
||||
|
||||
@@ -111,6 +111,9 @@ block main
|
||||
button.btn.btn-success.action-confirm-payment(type='button')= t('common.create')
|
||||
|
||||
prepend sidebar
|
||||
for sidebar_html in sidebars_html
|
||||
!= sidebar_html
|
||||
|
||||
.row
|
||||
a.btn.btn-lg.btn-success(href='/admin/ticket/')= t('ticket.ticket_list')
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{_, fs} = app.libs
|
||||
{pluggable, config, utils} = app
|
||||
{Financials} = app.models
|
||||
|
||||
exports = module.exports = class ShadowSocksPlugin extends pluggable.Plugin
|
||||
@NAME: 'shadowsocks'
|
||||
@@ -31,6 +32,32 @@ exports.registerHook 'view.panel.widgets',
|
||||
|
||||
exports.render 'widget', req, result, callback
|
||||
|
||||
exports.registerHook 'view.admin.sidebars',
|
||||
generator: (req, callback) ->
|
||||
Financials.find
|
||||
type: 'usage_billing'
|
||||
'payload.service': 'shadowsocks'
|
||||
created_at:
|
||||
$gte: new Date Date.now() - 30 * 24 * 3600 * 1000
|
||||
, (err, financials) ->
|
||||
time_range =
|
||||
traffic_24hours: 24 * 3600 * 1000
|
||||
traffic_3days: 3 * 24 * 3600 * 1000
|
||||
traffic_7days: 7 * 24 * 3600 * 1000
|
||||
traffic_30days: 30 * 24 * 3600 * 1000
|
||||
|
||||
traffic_result = {}
|
||||
|
||||
for name, range of time_range
|
||||
logs = _.filter financials, (i) ->
|
||||
return i.created_at.getTime() > Date.now() - range
|
||||
|
||||
traffic_result[name] = _.reduce logs, (memo, i) ->
|
||||
return memo + i.payload.traffic_mb
|
||||
, 0
|
||||
|
||||
exports.render 'admin/sidebar', req, traffic_result, callback
|
||||
|
||||
exports.registerHook 'app.started',
|
||||
action: ->
|
||||
shadowsocks.initSupervisor ->
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
"remote_port": "Port",
|
||||
"reset": "Reset",
|
||||
"transfer": "Traffic",
|
||||
"method": "method",
|
||||
"transfer_remainder": "About __traffic__ G remainder",
|
||||
"24hours_ago": "24 hours ago",
|
||||
"3days_ago": "3 days ago",
|
||||
"7days_ago": "7 days ago",
|
||||
"30days_ago": "30 days ago"
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
"remote_port": "端口",
|
||||
"reset": "重置",
|
||||
"transfer": "流量",
|
||||
"method": "加密算法",
|
||||
"transfer_remainder": "余额折合约 __traffic__ G 流量",
|
||||
"24hours_ago": "过去 24 小时",
|
||||
"3days_ago": "过去 3 天",
|
||||
"7days_ago": "过去 7 天",
|
||||
"30days_ago": "过去 30 天"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{utils} = app
|
||||
{utils, config} = app
|
||||
{markdown, fs, path, express} = app.libs
|
||||
{requireInService} = app.middleware
|
||||
|
||||
@@ -15,20 +15,19 @@ exports.post '/reset_password', (req, res) ->
|
||||
$set:
|
||||
'pluggable.shadowsocks.password': password
|
||||
, ->
|
||||
req.account.pluggable.shadowsocks.password = password
|
||||
|
||||
shadowsocks.updateConfigure req.account, ->
|
||||
shadowsocks.updateConfigure ->
|
||||
res.json {}
|
||||
|
||||
exports.post '/switch_method', (req, res) ->
|
||||
unless req.body.method in config.plugins.shadowsocks.available_ciphers
|
||||
return res.error 'invalid_method'
|
||||
|
||||
if req.body.method == req.account.pluggable.shadowsocks.method
|
||||
return res.error 'already_in_method'
|
||||
|
||||
req.account.update
|
||||
$set:
|
||||
'pluggable.shadowsocks.method': method
|
||||
'pluggable.shadowsocks.method': req.body.method
|
||||
, ->
|
||||
req.account.pluggable.shadowsocks.method = method
|
||||
|
||||
shadowsocks.updateConfigure req.account, ->
|
||||
shadowsocks.updateConfigure ->
|
||||
res.json {}
|
||||
|
||||
@@ -16,14 +16,14 @@ exports.initSupervisor = (callback) ->
|
||||
if program_name in _.pluck program_status, 'name'
|
||||
return callback()
|
||||
|
||||
shadowsocks_config_file = "/etc/shadowsocks/#{method}.json"
|
||||
configure = exports.generateConfigure [],
|
||||
method: method
|
||||
|
||||
ShadowsocksPlugin.writeConfigFile shadowsocks_config_file, configure, {mode: 0o755}, ->
|
||||
filename = "/etc/shadowsocks/#{method}.json"
|
||||
ShadowsocksPlugin.writeConfigFile filename, configure, {mode: 0o755}, ->
|
||||
supervisor.writeConfig {username: 'nobody'},
|
||||
program_name: program_name
|
||||
command: "ssserver -c #{shadowsocks_config_file}"
|
||||
command: "ssserver -c #{filename}"
|
||||
name: program_name
|
||||
autostart: true
|
||||
autorestart: true
|
||||
@@ -109,12 +109,12 @@ exports.initAccount = (account, callback) ->
|
||||
|
||||
child_process.exec "sudo iptables -I OUTPUT -p tcp --sport #{port}", ->
|
||||
child_process.exec 'sudo iptables-save | sudo tee /etc/iptables.rules', ->
|
||||
exports.updateConfigure account, ->
|
||||
exports.updateConfigure ->
|
||||
callback()
|
||||
|
||||
exports.deleteAccount = (account, callback) ->
|
||||
exports.queryIptablesInfo (iptables_info) ->
|
||||
{port, method} = account.pluggable.shadowsocks
|
||||
{port} = account.pluggable.shadowsocks
|
||||
|
||||
billing_traffic = iptables_info[port].bytes - account.pluggable.shadowsocks.last_traffic_value
|
||||
billing_traffic = iptables_info[port].bytes if billing_traffic < 0
|
||||
@@ -136,10 +136,7 @@ exports.deleteAccount = (account, callback) ->
|
||||
child_process.exec 'sudo iptables-save | sudo tee /etc/iptables.rules', callback
|
||||
|
||||
(callback) ->
|
||||
exports.deleteAccountConfigure account, callback
|
||||
|
||||
(callback) ->
|
||||
supervisor.updateProgram {}, {program_name: "shadowsocks-#{method}"}, callback
|
||||
exports.updateConfigure callback
|
||||
|
||||
], ->
|
||||
if amount > 0
|
||||
@@ -178,60 +175,24 @@ exports.accountUsage = (account, callback) ->
|
||||
|
||||
callback result
|
||||
|
||||
exports.updateConfigure = (account, callback) ->
|
||||
{port, method, password} = account.pluggable.shadowsocks
|
||||
original_method = null
|
||||
|
||||
exports.updateConfigure = (callback) ->
|
||||
async.eachSeries config.plugins.shadowsocks.available_ciphers, (method, callback) ->
|
||||
shadowsocks_config_file = "/etc/shadowsocks/#{method}.json"
|
||||
Account.find
|
||||
'pluggable.shadowsocks.method': method
|
||||
, (err, accounts) ->
|
||||
users = _.map accounts, (account) ->
|
||||
return account.pluggable.shadowsocks
|
||||
|
||||
fs.readFile shadowsocks_config_file, (err, content) ->
|
||||
if port.toString() in _.keys JSON.parse(content).port_password
|
||||
original_method = method
|
||||
callback true
|
||||
else
|
||||
callback()
|
||||
configure = exports.generateConfigure users,
|
||||
method: method
|
||||
|
||||
, ->
|
||||
async.series [
|
||||
(callback) ->
|
||||
shadowsocks_config_file = "/etc/shadowsocks/#{method}.json"
|
||||
|
||||
fs.readFile shadowsocks_config_file, (err, content) ->
|
||||
configure = JSON.parse content
|
||||
configure.port_password[port] = password
|
||||
|
||||
ShadowsocksPlugin.writeConfigFile shadowsocks_config_file, JSON.stringify(configure), {mode: 0o755}, ->
|
||||
callback()
|
||||
|
||||
(callback) ->
|
||||
filename = "/etc/shadowsocks/#{method}.json"
|
||||
ShadowsocksPlugin.writeConfigFile filename, configure, {mode: 0o755}, ->
|
||||
supervisor.updateProgram {}, {program_name: "shadowsocks-#{method}"}, ->
|
||||
callback()
|
||||
|
||||
(callback) ->
|
||||
if original_method == original_method
|
||||
return callback()
|
||||
|
||||
account = account.toObject()
|
||||
account.pluggable.shadowsocks.method = original_method
|
||||
|
||||
exports.deleteAccountConfigure account, ->
|
||||
supervisor.updateProgram {}, {program_name: "shadowsocks-#{original_method}"}, ->
|
||||
callback()
|
||||
|
||||
], ->
|
||||
callback()
|
||||
|
||||
exports.deleteAccountConfigure = (account, callback) ->
|
||||
{port, method} = account.pluggable.shadowsocks
|
||||
shadowsocks_config_file = "/etc/shadowsocks/#{method}.json"
|
||||
|
||||
fs.readFile shadowsocks_config_file, (err, content) ->
|
||||
configure = JSON.parse content
|
||||
delete configure.port_password[port]
|
||||
|
||||
fs.writeFile shadowsocks_config_file, JSON.stringify(configure), ->
|
||||
callback()
|
||||
, ->
|
||||
callback()
|
||||
|
||||
exports.monitoring = ->
|
||||
exports.queryIptablesInfo (iptables_info) ->
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
$ ->
|
||||
$('#widget-shadowsocks .action-reset-password').click ->
|
||||
$('.widget-shadowsocks .action-reset-password').click ->
|
||||
if window.confirm 'Are you sure?'
|
||||
$.post '/plugin/shadowsocks/reset_password/', {}
|
||||
.fail (jqXHR) ->
|
||||
if jqXHR.responseJSON?.error
|
||||
alert jqXHR.responseJSON.error
|
||||
else
|
||||
alert jqXHR.statusText
|
||||
.success ->
|
||||
request '/plugin/shadowsocks/reset_password/', {}, ->
|
||||
location.reload()
|
||||
|
||||
$('.widget-shadowsocks .action-switch-method').click ->
|
||||
request '/plugin/shadowsocks/switch_method/',
|
||||
method: $('.widget-shadowsocks .input-method').val()
|
||||
, ->
|
||||
alert 'Success'
|
||||
|
||||
15
plugin/shadowsocks/view/admin/sidebar.jade
Normal file
15
plugin/shadowsocks/view/admin/sidebar.jade
Normal file
@@ -0,0 +1,15 @@
|
||||
.row
|
||||
table.table.table-hover
|
||||
tbody
|
||||
tr
|
||||
td #{(traffic_24hours / 1000).toFixed(1)}G
|
||||
td= t('24hours_ago')
|
||||
tr
|
||||
td #{(traffic_3days / 1000).toFixed(1)}G
|
||||
td= t('3days_ago')
|
||||
tr
|
||||
td #{(traffic_7days / 1000).toFixed(1)}G
|
||||
td= t('7days_ago')
|
||||
tr
|
||||
td #{(traffic_30days / 1000).toFixed(1)}G
|
||||
td= t('30days_ago')
|
||||
@@ -13,6 +13,13 @@
|
||||
input.form-control(type='text', value=account.pluggable.shadowsocks.password, disabled)
|
||||
span.input-group-btn
|
||||
button.btn.btn-default.action-reset-password(type='button')= t('reset')
|
||||
.input-group
|
||||
span.input-group-addon= t('method')
|
||||
select.input-method.form-control(style='-webkit-appearance: none;')
|
||||
for method in config.plugins.shadowsocks.available_ciphers
|
||||
option= method
|
||||
span.input-group-btn
|
||||
button.btn.btn-default.action-switch-method(type='button')= t('common.change')
|
||||
|
||||
.col-md-6
|
||||
.panel.panel-default
|
||||
|
||||
@@ -9,7 +9,7 @@ exports.registerHook 'view.layout.menu_bar',
|
||||
href: '/wiki/'
|
||||
t_body: 'plugins.wiki.'
|
||||
|
||||
unless config.plugins.wiki.disable_default_wiki
|
||||
unless config.plugins.wiki?.disable_default_wiki
|
||||
wiki_path = "#{__dirname}/../../WIKI"
|
||||
|
||||
for category_name in fs.readdirSync(wiki_path)
|
||||
|
||||
Reference in New Issue
Block a user