shadowsocks-manager
Version:
A shadowsocks manager tool for multi user and traffic control.
496 lines (490 loc) • 16.8 kB
JavaScript
const app = angular.module('app');
app.controller('AdminServerController', ['$scope', '$http', '$state', 'moment', '$localStorage', 'adminApi', '$timeout', '$interval', 'serverChartDialog',
($scope, $http, $state, moment, $localStorage, adminApi, $timeout, $interval, serverChartDialog) => {
$scope.setTitle('服务器');
$scope.setMenuRightButton('timeline');
if(!$localStorage.admin.serverChart) {
$localStorage.admin.serverChart = { showFlow: true, showChart: true };
}
$scope.serverChart = $localStorage.admin.serverChart;
$scope.$on('RightButtonClick', () => {
serverChartDialog.show($scope.serverChart);
});
const scaleLabel = number => {
if(number < 1) {
return number.toFixed(1) +' B';
} else if (number < 1000) {
return number.toFixed(0) +' B';
} else if (number < 1000000) {
return (number/1000).toFixed(0) +' KB';
} else if (number < 1000000000) {
return (number/1000000).toFixed(0) +' MB';
} else if (number < 1000000000000) {
return (number/1000000000).toFixed(1) +' GB';
} else {
return number;
}
};
$scope.chart = {
labels: ['', '', '', '', '', '', '', '', '', '', '', ''],
series: 'day',
datasetOverride: [{ yAxisID: 'y-axis-1' }],
options: {
tooltips: {
callbacks: {
label: function(tooltipItem) {
return scaleLabel(tooltipItem.yLabel);
}
}
},
scales: {
yAxes: [
{
id: 'y-axis-1',
type: 'linear',
display: true,
position: 'left',
ticks: {
callback: scaleLabel,
},
}
]
}
},
};
if(!$localStorage.admin.serverInfo) {
$localStorage.admin.serverInfo = {
time: Date.now(),
data: [],
};
}
$scope.servers = $localStorage.admin.serverInfo.data;
const updateServerInfo = () => {
adminApi.getServer(true).then(servers => {
if(servers.map(s => s.id).join('') === $scope.servers.map(s => s.id).join('')) {
$scope.servers.forEach((server, index) => {
server.host = servers[index].host;
server.name = servers[index].name;
server.port = servers[index].port;
server.status = servers[index].status;
server.isGfw = servers[index].isGfw;
adminApi.getServerFlow(server.id).then(flow => {
if(!server.flow) {
server.flow = {};
}
server.flow.today = flow.today;
server.flow.week = flow.week;
server.flow.month = flow.month;
});
if($scope.serverChart.showChart) {
$timeout(() => {
adminApi.getServerFlowLastHour(server.id)
.then(success => {
if(!server.chart) {
server.chart = {
data: [[]],
};
}
success.flow.forEach((number, index) => {
server.chart.data[0][index] = number;
});
});
}, index * 1000);
}
});
} else {
$localStorage.admin.serverInfo = {
time: Date.now(),
data: servers,
};
$scope.servers = servers;
$scope.servers.forEach((server, index) => {
adminApi.getServerFlow(server.id).then(flow => {
server.flow = flow;
});
if($scope.serverChart.showChart) {
$timeout(() => {
adminApi.getServerFlowLastHour(server.id)
.then(success => {
if(!server.chart) {
server.chart = {
data: [[]],
};
}
success.flow.forEach((number, index) => {
server.chart.data[0][index] = number;
});
});
}, index * 1000);
}
});
}
});
};
updateServerInfo();
$scope.$on('visibilitychange', (event, status) => {
if(status === 'visible') {
if($localStorage.admin.serverInfo && Date.now() - $localStorage.admin.serverInfo.time >= 30 * 1000) {
updateServerInfo();
}
}
});
$scope.setInterval($interval(() => {
if(document.visibilityState === 'visible' && $localStorage.admin.serverInfo && Date.now() - $localStorage.admin.serverInfo.time >= 90 * 1000) {
updateServerInfo();
}
}, 15 * 1000));
$scope.toServerPage = (serverId) => {
$state.go('admin.serverPage', { serverId });
};
$scope.setFabButton($scope.id === 1 ? () => {
$state.go('admin.addServer');
} : null);
}
])
.controller('AdminServerPageController', ['$scope', '$state', '$stateParams', '$http', 'moment', '$mdDialog', 'adminApi', '$q', '$mdMedia', '$interval', 'banDialog',
($scope, $state, $stateParams, $http, moment, $mdDialog, adminApi, $q, $mdMedia, $interval, banDialog) => {
$scope.setTitle('服务器');
$scope.setMenuButton('arrow_back', 'admin.server');
const serverId = $stateParams.serverId;
const getServerInfo = () => {
$http.get(`/api/admin/server/${ serverId }`).then(success => {
$scope.server = success.data;
$scope.currentPorts = {};
$scope.server.ports.forEach(f => {
$scope.currentPorts[f.port] = {
port: f.port,
password: f.password,
exists: true,
};
});
return adminApi.getAccount();
}).then(accounts => {
accounts.forEach(account => {
if(!$scope.currentPorts[account.port + $scope.server.shift]) {
$scope.currentPorts[account.port + $scope.server.shift] = {
id: account.id,
port: account.port + $scope.server.shift,
password: account.password,
exists: false,
};
} else {
$scope.currentPorts[account.port + $scope.server.shift].id = account.id;
}
});
$scope.portNumber = Object.keys($scope.currentPorts).filter(f => {
return $scope.currentPorts[f].exists;
}).length;
});
};
getServerInfo();
$scope.setInterval($interval(() => {
getServerInfo();
}, 60 * 1000));
$scope.toAccountPage = port => {
adminApi.getAccountId(port - $scope.server.shift).then(id => {
$state.go('admin.accountPage', { accountId: id });
});
};
$scope.deleteServer = id => {
const confirm = $mdDialog.confirm()
.title('')
.textContent('删除服务器?')
.ariaLabel('deleteServer')
.ok('确认')
.cancel('取消');
$mdDialog.show(confirm).then(() => {
return $http.delete(`/api/admin/server/${ serverId }`);
}).then(() => {
$state.go('admin.server');
}).catch(() => {
});
};
$scope.flowType = 'day';
const flowTime = {
hour: Date.now(),
day: Date.now(),
week: Date.now(),
};
const flowLabel = {
hour: ['0', '', '', '15', '', '', '30', '', '', '45', '', ''],
day: ['0', '', '', '', '', '', '6', '', '', '', '', '', '12', '', '', '', '', '', '18', '', '', '', '', '', ],
week: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
};
const scaleLabel = (number) => {
if(number < 1) {
return number.toFixed(1) +' B';
} else if (number < 1000) {
return number.toFixed(0) +' B';
} else if (number < 1000000) {
return (number/1000).toFixed(0) +' KB';
} else if (number < 1000000000) {
return (number/1000000).toFixed(0) +' MB';
} else if (number < 1000000000000) {
return (number/1000000000).toFixed(1) +' GB';
} else {
return number;
}
};
const setChart = (lineData, pieData) => {
const pieDataSort = pieData.sort((a, b) => {
return a.flow >= b.flow;
});
$scope.pieChart = {
data: pieDataSort.map(m => m.flow),
labels: pieDataSort.map(m => m.port + (m.userName ? ` [${ m.userName }]` : '')),
options: {
responsive: false,
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label: function(tooltipItem, data) {
const label = data.labels[tooltipItem.index];
const datasetLabel = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
return [
label, scaleLabel(datasetLabel)
];
}
}
},
},
};
$scope.lineChart = {
data: [lineData],
labels: flowLabel[$scope.flowType],
series: 'day',
datasetOverride: [{ yAxisID: 'y-axis-1' }],
options: {
responsive: false,
tooltips: {
callbacks: {
label: function(tooltipItem) {
return scaleLabel(tooltipItem.yLabel);
}
}
},
scales: {
yAxes: [
{
id: 'y-axis-1',
type: 'linear',
display: true,
position: 'left',
ticks: {
callback: scaleLabel,
},
}
]
}
},
};
};
$scope.getChartData = () => {
adminApi.getChartData(serverId, $scope.flowType, flowTime[$scope.flowType])
.then(success => {
$scope.sumFlow = success[0].data.reduce((a, b) => {
return a + b;
}, 0);
setChart(success[0].data, success[1].data);
});
if($scope.flowType === 'hour') {
$scope.time = moment(flowTime[$scope.flowType]).format('YYYY-MM-DD HH:00');
}
if($scope.flowType === 'day') {
$scope.time = moment(flowTime[$scope.flowType]).format('YYYY-MM-DD');
}
if($scope.flowType === 'week') {
$scope.time = moment(flowTime[$scope.flowType]).day(0).format('YYYY-MM-DD') + ' / ' + moment(flowTime[$scope.flowType]).day(6).format('YYYY-MM-DD');
}
};
$scope.getChartData();
$scope.changeFlowTime = (number) => {
const time = {
hour: 3600 * 1000,
day: 24 * 3600 * 1000,
week: 7 * 24 * 3600 * 1000,
};
flowTime[$scope.flowType] += number * time[$scope.flowType];
$scope.getChartData();
};
$scope.resetFlowTime = () => {
flowTime[$scope.flowType] = Date.now();
$scope.getChartData();
};
$scope.getChartSize = () => {
if($mdMedia('xs')) {
return {
line: [ 320, 170 ],
pie: [ 170, 170 ],
};
} else if($mdMedia('sm')) {
return {
line: [ 360, 190 ],
pie: [ 190, 190 ],
};
} else if($mdMedia('md')) {
return {
line: [ 360, 180 ],
pie: [ 180, 180 ],
};
} else if($mdMedia('gt-md')) {
return {
line: [ 540, 240 ],
pie: [ 240, 240 ],
};
}
};
$scope.setFabButton($scope.id === 1 ? () => {
$state.go('admin.editServer', { serverId });
} : null, 'mode_edit');
$scope.banAccount = (accountId) => {
banDialog.show(serverId, accountId);
};
$scope.setMenuSearchButton('search');
$scope.matchPort = (port, passowrd, search) => {
if(!search) { return true; }
return port.toString().indexOf(search) >= 0 || passowrd.toString().indexOf(search) >= 0;
};
// $scope.$on('cancelSearch', () => {
// });
// let timeoutPromise;
// $scope.$watch('menuSearch.text', () => {
// if(!$scope.menuSearch.text) { return; }
// timeoutPromise && $timeout.cancel(timeoutPromise);
// timeoutPromise = $timeout(() => {
// }, 500);
// });
}
])
.controller('AdminAddServerController', ['$scope', '$state', '$stateParams', '$http', 'alertDialog',
($scope, $state, $stateParams, $http, alertDialog) => {
$scope.setTitle('新增服务器');
$scope.setMenuButton('arrow_back', 'admin.server');
$scope.methods = [
'aes-256-cfb',
'aes-192-cfb',
'aes-128-cfb',
'aes-256-ctr',
'aes-192-ctr',
'aes-128-ctr',
'camellia-256-cfb',
'camellia-192-cfb',
'camellia-128-cfb',
'aes-256-gcm',
'aes-192-gcm',
'aes-128-gcm',
'chacha20-ietf',
'chacha20-ietf-poly1305'
];
$scope.setMethod = () => {
$scope.server.method = $scope.methodSearch;
};
$scope.server = {
scale: 1,
shift: 0,
};
$scope.confirm = () => {
alertDialog.loading();
$http.post('/api/admin/server', {
name: $scope.server.name,
address: $scope.server.address,
port: +$scope.server.port,
password: $scope.server.password,
method: $scope.server.method,
comment: $scope.server.comment,
scale: $scope.server.scale,
shift: $scope.server.shift,
}, {
timeout: 15000,
}).then(success => {
alertDialog.show('添加服务器成功', '确定');
$state.go('admin.server');
}).catch(() => {
alertDialog.show('添加服务器失败', '确定');
});
};
$scope.cancel = () => {
$state.go('admin.server');
};
}
])
.controller('AdminEditServerController', ['$scope', '$state', '$stateParams', '$http', 'confirmDialog', 'alertDialog',
($scope, $state, $stateParams, $http, confirmDialog, alertDialog) => {
$scope.setTitle('编辑服务器');
const serverId = $stateParams.serverId;
$scope.setMenuButton('arrow_back', function() {
$state.go('admin.serverPage', { serverId: $stateParams.serverId });
});
$scope.server = { check: 1 };
$scope.methods = [
'aes-256-cfb',
'aes-192-cfb',
'aes-128-cfb',
'aes-256-ctr',
'aes-192-ctr',
'aes-128-ctr',
'camellia-256-cfb',
'camellia-192-cfb',
'camellia-128-cfb',
'aes-256-gcm',
'aes-192-gcm',
'aes-128-gcm',
'chacha20-ietf',
'chacha20-ietf-poly1305'
];
$scope.setMethod = () => {
$scope.server.method = $scope.methodSearch;
};
$scope.serverInfoloaded = false;
$http.get(`/api/admin/server/${ serverId }`, {
params: {
noPort: true,
}
})
.then(success => {
$scope.serverInfoloaded = true;
$scope.server.name = success.data.name;
$scope.server.comment = success.data.comment;
$scope.server.address = success.data.host;
$scope.server.port = +success.data.port;
$scope.server.password = success.data.password;
$scope.server.method = success.data.method;
$scope.server.scale = success.data.scale;
$scope.server.shift = success.data.shift;
});
$scope.confirm = () => {
alertDialog.loading();
$http.put('/api/admin/server/' + $stateParams.serverId, {
name: $scope.server.name,
comment: $scope.server.comment,
address: $scope.server.address,
port: +$scope.server.port,
password: $scope.server.password,
method: $scope.server.method,
scale: $scope.server.scale,
shift: $scope.server.shift,
check: $scope.server.check,
}).then(success => {
alertDialog.show('修改服务器成功', '确定');
$state.go('admin.serverPage', { serverId: $stateParams.serverId });
}).catch(() => {
alertDialog.show('修改服务器失败', '确定');
});
};
$scope.cancel = () => {
$state.go('admin.serverPage', { serverId: $stateParams.serverId });
};
$scope.deleteServer = () => {
confirmDialog.show({
text: '真的要删除服务器吗?',
cancel: '取消',
confirm: '删除',
error: '删除服务器失败',
fn: function () { return $http.delete('/api/admin/server/' + $stateParams.serverId); },
}).then(() => {
$state.go('admin.server');
});
};
}
]);