shadowsocks-manager
Version:
A shadowsocks manager tool for multi user and traffic control.
664 lines (626 loc) • 21.4 kB
JavaScript
const user = appRequire('plugins/user/index');
const account = appRequire('plugins/account/index');
const flow = appRequire('plugins/flowSaver/flow');
const knex = appRequire('init/knex').knex;
const emailPlugin = appRequire('plugins/email/index');
const orderPlugin = appRequire('plugins/webgui_order');
const groupPlugin = appRequire('plugins/group');
const config = appRequire('services/config').all();
const giftcard = appRequire('plugins/giftcard');
const log4js = require('log4js');
const logger = log4js.getLogger('webgui');
const ref = appRequire('plugins/webgui_ref/index');
const refUser = appRequire('plugins/webgui_ref/user');
const refOrder = appRequire('plugins/webgui_ref/order');
const crypto = require('crypto');
const flowPack = appRequire('plugins/webgui_order/flowPack');
const alipayPlugin = appRequire('plugins/alipay/index');
const macAccountPlugin = appRequire('plugins/macAccount/index');
const alipay = appRequire('plugins/alipay/index');
exports.getAccount = async (req, res) => {
try {
const userId = req.session.user;
const accounts = await account.getAccount({ userId });
for(let account of accounts) {
account.data = JSON.parse(account.data);
if (account.type >= 2 && account.type <= 5) {
const time = {
'2': 7 * 24 * 3600000,
'3': 30 * 24 * 3600000,
'4': 24 * 3600000,
'5': 3600000,
};
account.data.expire = account.data.create + account.data.limit * time[account.type];
account.data.from = account.data.create;
account.data.to = account.data.create + time[account.type];
while (account.data.to <= Date.now()) {
account.data.from = account.data.to;
account.data.to = account.data.from + time[account.type];
}
account.data.flowPack = await flowPack.getFlowPack(account.id, account.data.from, account.data.to);
}
account.server = account.server ? JSON.parse(account.server) : account.server;
}
res.send(accounts);
} catch (err) {
console.log(err);
res.status(403).end();
}
};
exports.getOneAccount = async (req, res) => {
try {
const userId = req.session.user;
const accountId = +req.params.accountId;
const accountInfo = account.getAccount({ id: accountId, userId }).then(s => s[0]);
if(!accountInfo) { return Promise.reject('account not found'); }
if (accountInfo.type >= 2 && accountInfo.type <= 5) {
accountInfo.data = JSON.parse(accountInfo.data);
const time = {
'2': 7 * 24 * 3600000,
'3': 30 * 24 * 3600000,
'4': 24 * 3600000,
'5': 3600000,
};
accountInfo.data.expire = accountInfo.data.create + accountInfo.data.limit * time[accountInfo.type];
accountInfo.data.from = accountInfo.data.create;
accountInfo.data.to = accountInfo.data.create + time[accountInfo.type];
while (accountInfo.data.to <= Date.now()) {
accountInfo.data.from = accountInfo.data.to;
accountInfo.data.to = accountInfo.data.from + time[accountInfo.type];
}
accountInfo.server = accountInfo.server ? JSON.parse(accountInfo.server) : accountInfo.server;
accountInfo.data.flowPack = await flowPack.getFlowPack(accountId, accountInfo.data.from, accountInfo.data.to);
}
res.send(accountInfo);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.getServers = (req, res) => {
const userId = req.session.user;
const serverAliasFilter = servers => {
return servers.map(server => {
if(server.host.indexOf(':') >= 0) {
const hosts = server.host.split(':');
const number = Math.ceil(Math.random() * (hosts.length - 1));
server.host = hosts[number];
}
return server;
});
};
let servers;
knex('server').select(['id', 'host', 'name', 'method', 'scale', 'comment', 'shift']).orderBy('name')
.then(success => {
servers = serverAliasFilter(success);
return account.getAccount({
userId,
}).then(accounts => {
return accounts.map(f => {
f.server = f.server ? JSON.parse(f.server) : f.server;
return f;
});
});
})
.then(success => {
if (!success.length) {
return res.send([]);
}
const isAll = success.some(account => {
if (!account.server) { return true; }
});
if (isAll) {
return res.send(servers);
} else {
let accountArray = [];
success.forEach(account => {
account.server.forEach(s => {
if (accountArray.indexOf(s) < 0) {
accountArray.push(s);
}
});
});
return res.send(servers.filter(f => {
return accountArray.indexOf(f.id) >= 0;
}));
}
}).catch(err => {
console.log(err);
res.status(500).end();
});
};
exports.getServerPortFlow = (req, res) => {
const serverId = +req.params.serverId;
const accountId = +req.params.accountId;
let account = null;
knex('account_plugin').select().where({
id: accountId,
}).then(success => {
if (!success.length) {
return Promise.reject('account not found');
}
account = success[0];
account.data = JSON.parse(account.data);
const time = {
'2': 7 * 24 * 3600000,
'3': 30 * 24 * 3600000,
'4': 24 * 3600000,
'5': 3600000,
};
if (account.type >= 2 && account.type <= 5) {
const timeArray = [account.data.create, account.data.create + time[account.type]];
if (account.data.create <= Date.now()) {
let i = 0;
while (account.data.create + i * time[account.type] <= Date.now()) {
timeArray[0] = account.data.create + i * time[account.type];
timeArray[1] = account.data.create + (i + 1) * time[account.type];
i++;
}
}
return flow.getServerPortFlowWithScale(serverId, accountId, timeArray, account.multiServerFlow);
} else {
return [0];
}
}).then(success => {
res.send(success);
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.getServerPortLastConnect = (req, res) => {
const serverId = +req.params.serverId;
const accountId = +req.params.accountId;
flow.getlastConnectTime(serverId, accountId)
.then(success => {
res.send(success);
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.changeShadowsocksPassword = (req, res) => {
const accountId = +req.params.accountId;
let password = req.body.password;
if (!password) { return res.status(403).end(); }
if (password.length > 20) { password = password.substr(0, 20); }
const isUserHasTheAccount = (accountId) => {
return account.getAccount({ userId: req.session.user, id: accountId }).then(success => {
if (success.length) {
return;
}
return Promise.reject();
});
};
isUserHasTheAccount(accountId).then(() => {
return account.changePassword(accountId, password);
}).then(() => {
res.send('success');
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.createOrder = async (req, res) => {
try {
const userId = req.session.user;
const accountId = req.body.accountId;
const orderId = req.body.orderId;
const alipayOrder = await alipay.createOrder(userId, accountId, orderId);
return res.send(alipayOrder);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.checkOrder = (req, res) => {
const orderId = req.body.orderId;
alipay.checkOrder(orderId).then(success => {
return res.send({ status: success });
}).catch(() => {
res.status(403).end();
});
};
exports.alipayCallback = (req, res) => {
const signStatus = alipay.verifyCallback(req.body);
if (signStatus === false) {
return res.send('error');
}
return res.send('success');
};
exports.getPrice = async (req, res) => {
try {
const accountId = +req.query.accountId;
let accountInfo;
let changeOrderTypeId = 0;
let orderInfo;
const isExpired = account => {
if(!account) { return true; }
const accountData = JSON.parse(account.data);
const time = {
'2': 7 * 24 * 3600000,
'3': 30 * 24 * 3600000,
'4': 24 * 3600000,
'5': 3600000,
};
const expire = accountData.create + time[account.type] * accountData.limit;
return expire <= Date.now();
};
if(accountId) {
orderInfo = await orderPlugin.getOneOrderByAccountId(accountId);
accountInfo = await knex('account_plugin').where({ id: accountId }).then(s => s[0]);
if(orderInfo && !orderInfo.changeOrderType) {
changeOrderTypeId = orderInfo.id;
}
}
const groupId = req.userInfo.group;
let orders = await orderPlugin.getOrders();
const groupSetting = await groupPlugin.getOneGroup(groupId);
if(groupSetting.order) {
orders = orders.filter(f => {
return JSON.parse(groupSetting.order).indexOf(f.id) >= 0;
});
if(orderInfo) {
orders = orders.filter(f => {
if(!f.baseId) { return true; }
if(f.baseId === orderInfo.id && !isExpired(accountInfo)) { return true; }
return false;
});
} else {
orders = orders.filter(f => !f.baseId);
}
}
let currentOrder = [];
if(changeOrderTypeId && !isExpired(accountInfo)) {
currentOrder = orders.filter(f => {
return (f.id === changeOrderTypeId || f.baseId === changeOrderTypeId);
});
}
return res.send(currentOrder.length ? currentOrder : orders);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.getNotice = async (req, res) => {
try {
const userId = req.session.user;
const groupInfo = await knex('user').select([
'group.id as id',
'group.showNotice as showNotice',
]).innerJoin('group', 'user.group', 'group.id').where({
'user.id': userId,
}).then(s => s[0]);
const group = [groupInfo.id];
if(groupInfo.showNotice) { group.push(-1); }
const notices = await knex('notice').select().whereIn('group', group).orderBy('time', 'desc');
return res.send(notices);
} catch (err) {
console.log(err);
res.status(403).end();
}
};
exports.getAlipayStatus = (req, res) => {
return res.send({
status: config.plugins.alipay && config.plugins.alipay.use,
});
};
exports.getMultiServerFlowStatus = (req, res) => {
knex('webguiSetting').select().where({
key: 'account',
}).then(success => {
if (!success.length) {
return Promise.reject('settings not found');
}
success[0].value = JSON.parse(success[0].value);
return success[0];
}).then(success => {
return res.send({ status: success.value.multiServerFlow });
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
const paypal = appRequire('plugins/paypal/index');
exports.createPaypalOrder = async (req, res) => {
try {
const userId = req.session.user;
const accountId = req.body.accountId;
const orderId = req.body.orderId;
const paypalOrder = await paypal.createOrder(userId, accountId, orderId);
return res.send(paypalOrder);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.executePaypalOrder = (req, res) => {
paypal.executeOrder(req.body)
.then(success => {
res.send(success);
})
.catch(error => {
res.status(403).end();
});
};
exports.paypalCallback = (req, res) => {
console.log(req.body);
return res.send('success');
};
exports.changePassword = (req, res) => {
const oldPassword = req.body.password;
const newPassword = req.body.newPassword;
if (!oldPassword || !newPassword) {
return res.status(403).end();
}
const userId = req.session.user;
user.changePassword(userId, oldPassword, newPassword).then(success => {
res.send('success');
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.getTelegramCode = (req, res) => {
const telegramUser = appRequire('plugins/webgui_telegram/user');
const userId = req.session.user;
telegramUser.getCode(userId).then(success => {
res.send(success);
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.unbindTelegram = (req, res) => {
const telegramUser = appRequire('plugins/webgui_telegram/user');
const userId = req.session.user;
telegramUser.unbindUser(userId).then(success => {
res.send('success');
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.payByGiftCard = async (req, res) => {
const password = req.body.password;
const userId = +req.session.user;
const accountId = req.body.accountId ? +req.body.accountId : null;
if (!userId) {
res.status(400).end();
return;
}
try {
const checkGiftcardType = async () => {
let accountInfo;
let changeOrderTypeId = 0;
let orderInfo;
const isExpired = account => {
if(!account) { return true; }
const accountData = JSON.parse(account.data);
const time = {
'2': 7 * 24 * 3600000,
'3': 30 * 24 * 3600000,
'4': 24 * 3600000,
'5': 3600000,
};
const expire = accountData.create + time[account.type] * accountData.limit;
return expire <= Date.now();
};
if(accountId) {
orderInfo = await orderPlugin.getOneOrderByAccountId(accountId);
accountInfo = await knex('account_plugin').where({ id: accountId }).then(s => s[0]);
if(orderInfo && !orderInfo.changeOrderType) {
changeOrderTypeId = orderInfo.id;
}
}
const groupId = req.userInfo.group;
let orders = await orderPlugin.getOrders();
const groupSetting = await groupPlugin.getOneGroup(groupId);
if(groupSetting.order) {
orders = orders.filter(f => {
return JSON.parse(groupSetting.order).indexOf(f.id) >= 0;
});
if(orderInfo) {
orders = orders.filter(f => {
if(!f.baseId) { return true; }
if(f.baseId === orderInfo.id && !isExpired(accountInfo)) { return true; }
return false;
});
} else {
orders = orders.filter(f => !f.baseId);
}
}
let currentOrder = [];
if(changeOrderTypeId && !isExpired(accountInfo)) {
currentOrder = orders.filter(f => {
return (f.id === changeOrderTypeId || f.baseId === changeOrderTypeId);
});
}
// return res.send(currentOrder.length ? currentOrder : orders);
const giftCardInfo = await knex('giftcard').where({ password }).then(s => s[0]);
const validTypes = currentOrder.length ? currentOrder.map(m => m.id) : orders.map(m => m.id);
return validTypes.indexOf(giftCardInfo.orderType) < 0;
// if(!accountId) { return false; }
// const orderInfo = await orderPlugin.getOneOrderByAccountId(accountId);
// if(!orderInfo || orderInfo.changeOrderType) { return false; }
// const changeOrderTypeId = orderInfo.id;
// const accountInfo = await knex('account_plugin').where({ id: accountId }).then(s => s[0]);
// const groupId = req.userInfo.group;
// let orders = await orderPlugin.getOrders();
// const groupSetting = await groupPlugin.getOneGroup(groupId);
// if(groupSetting.order) {
// orders = orders.filter(f => {
// return JSON.parse(groupSetting.order).indexOf(f.id) >= 0;
// });
// }
// let currentOrder = [];
// const isExpired = account => {
// if(!account) { return true; }
// const accountData = JSON.parse(account.data);
// const time = {
// '2': 7 * 24 * 3600000,
// '3': 30 * 24 * 3600000,
// '4': 24 * 3600000,
// '5': 3600000,
// };
// const expire = accountData.create + time[account.type] * accountData.limit;
// return expire <= Date.now();
// };
// if(changeOrderTypeId && !isExpired(accountInfo)) {
// currentOrder = orders.filter(f => {
// return f.id === changeOrderTypeId;
// });
// }
// const giftCardInfo = await knex('giftcard').where({ password }).then(s => s[0]);
// if(currentOrder.length && giftCardInfo) {
// if(giftCardInfo.orderType !== currentOrder[0].id) {
// return true;
// }
// }
// return false;
};
if(await checkGiftcardType()) {
return res.send({ success: false, message: '充值码类型错误' });
};
const result = await giftcard.processOrder(userId, accountId, password);
res.send(result);
} catch (err) {
logger.error(`使用充值码时出现错误:${err.toString()}`);
res.status(500).end();
}
};
exports.getRefCode = (req, res) => {
const userId = +req.session.user;
refUser.getRefCode(userId).then(success => {
const result = success.filter(f => {
return f.count < f.maxUser;
});
res.send(result);
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.getRefUser = (req, res) => {
const userId = +req.session.user;
refUser.getRefUser(userId).then(success => {
res.send(success);
}).catch(err => {
console.log(err);
res.status(403).end();
});
};
exports.getAccountSubscribe = async (req, res) => {
try {
const userId = req.session.user;
const accountId = +req.params.accountId;
const account = await knex('account_plugin').select([
'id',
'subscribe'
]).where({
id: accountId,
userId,
}).then(s => s[0]);
if(!account.subscribe) {
const subscribeToken = crypto.randomBytes(16).toString('hex');;
await await knex('account_plugin').update({
subscribe: subscribeToken
}).where({
id: accountId,
userId,
});
account.subscribe = subscribeToken;
}
res.send(account);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.updateAccountSubscribe = async (req, res) => {
try {
const userId = req.session.user;
const accountId = +req.params.accountId;
const account = await knex('account_plugin').select([
'id',
'subscribe'
]).where({
id: accountId,
userId,
}).then(s => s[0]);
if(!account) { return Promise.reject('account not found'); }
const subscribeToken = crypto.randomBytes(16).toString('hex');;
await await knex('account_plugin').update({
subscribe: subscribeToken
}).where({
id: accountId,
userId,
});
account.subscribe = subscribeToken;
res.send(account);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.activeAccount = async (req, res) => {
try {
const userId = req.session.user;
const accountId = +req.params.accountId;
const accountInfo = await account.getAccount({ id: accountId, userId }).then(s => s[0]);
if(!accountInfo) { return Promise.reject('account not found'); }
await account.activeAccount(accountInfo.id);
res.send('success');
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.getOrder = async (req, res) => {
try {
const userId = req.session.user;
let orders = [];
if(config.plugins.alipay && config.plugins.alipay.use) {
const alipayOrders = await alipayPlugin.getUserFinishOrder(userId);
orders = [...orders, ...alipayOrders];
}
if(config.plugins.paypal && config.plugins.paypal.use) {
const paypalOrders = await paypal.getUserFinishOrder(userId);
orders = [...orders, ...paypalOrders];
}
const refOrders = await refOrder.getUserFinishOrder(userId);
orders = [...orders, ...refOrders];
if(config.plugins.giftcard && config.plugins.giftcard.use) {
const giftCardOrders = await giftcard.getUserFinishOrder(userId);
orders = [...orders, ...giftCardOrders];
}
orders = orders.sort((a, b) => {
return b.createTime - a.createTime;
});
res.send(orders);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.getMacAccount = async (req, res) => {
try {
const userId = req.session.user;
const accounts = await macAccountPlugin.getAccountByUserId(userId);
res.send(accounts);
} catch(err) {
console.log(err);
res.status(403).end();
}
};
exports.addMacAccount = async (req, res) => {
try {
const userId = req.session.user;
const { mac } = req.body;
await macAccountPlugin.userAddMacAccount(userId, mac);
res.send('success');
} catch(err) {
console.log(err);
res.status(403).end();
}
};