sequelize-game-bank 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/database/models/Account.js +5 -0
- package/database/services/account/cardTransfer.js +91 -0
- package/database/services/account/create.js +10 -1
- package/database/services/account/linkACard.js +18 -0
- package/database/services/accounts.js +3 -1
- package/index.js +2 -2
- package/package.json +1 -1
- package/public/accounts.html +9 -6
- package/public/credit.html +18 -15
- package/public/css/style.css +4 -1
- package/public/general.html +18 -15
- package/public/history.html +9 -6
- package/public/js/js.js +102 -22
- package/public/profile.html +18 -15
- package/public/transfer.html +10 -7
- package/public/uploads/avatars/root_1791699307597.png +0 -0
- package/public/uploads/avatars/root_1791723384225.png +0 -0
- package/server/server.js +16 -3
|
@@ -35,6 +35,11 @@ const Account = sequelize.define('account', {
|
|
|
35
35
|
allowNull: false,
|
|
36
36
|
defaultValue: false,
|
|
37
37
|
field: '2FA-status'
|
|
38
|
+
},
|
|
39
|
+
cardNumber:{
|
|
40
|
+
type:DataTypes.STRING,
|
|
41
|
+
allowNull:true,
|
|
42
|
+
unique:true
|
|
38
43
|
}
|
|
39
44
|
});
|
|
40
45
|
User.hasMany(Account, { foreignKey: 'user', sourceKey: 'name' });
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const bcrypt = require('bcrypt');
|
|
3
|
+
const Account = require(path.join(__dirname, '..', '..', 'models', 'Account'));
|
|
4
|
+
const User = require(path.join(__dirname, '..', '..', 'models', 'User'));
|
|
5
|
+
const Transaction = require(path.join(__dirname, '..', '..', 'models', 'Transaction'));
|
|
6
|
+
const sequelize = require(path.join(__dirname, '..', '..', 'config', 'init-db'));
|
|
7
|
+
const { sendBotNotification } = require(path.join(__dirname, '..', 'bot', 'bot'));
|
|
8
|
+
const logger = require("custom-color-logs").print;
|
|
9
|
+
async function getIdByCard(card) {
|
|
10
|
+
const result = await Account.findOne({
|
|
11
|
+
where:{cardNumber:card.toString()},
|
|
12
|
+
attributes: ['id']
|
|
13
|
+
});
|
|
14
|
+
if (!result) return false
|
|
15
|
+
return result
|
|
16
|
+
}
|
|
17
|
+
module.exports = async function cardTransfer(card, toId, amount, pinCode) {
|
|
18
|
+
const t = await sequelize.transaction();
|
|
19
|
+
try {
|
|
20
|
+
const fromId = await getIdByCard(card);
|
|
21
|
+
const numericAmount = parseFloat(amount);
|
|
22
|
+
if (isNaN(numericAmount) || numericAmount <= 0) {
|
|
23
|
+
await t.rollback();
|
|
24
|
+
return { status: false, statusCode: -2, message: 'Некорректная сумма перевода' };
|
|
25
|
+
}
|
|
26
|
+
const fromAcc = await Account.findByPk(fromId, {
|
|
27
|
+
transaction: t,
|
|
28
|
+
lock: t.LOCK.UPDATE
|
|
29
|
+
});
|
|
30
|
+
const toAcc = await Account.findByPk(toId, {
|
|
31
|
+
transaction: t,
|
|
32
|
+
lock: t.LOCK.UPDATE
|
|
33
|
+
});
|
|
34
|
+
if (!fromAcc || !toAcc) {
|
|
35
|
+
await t.rollback();
|
|
36
|
+
return { status: false, statusCode: -2, message: 'Один из счетов не найден' };
|
|
37
|
+
}
|
|
38
|
+
if (!fromAcc.active || !toAcc.active) {
|
|
39
|
+
await t.rollback();
|
|
40
|
+
return { status: false, statusCode: -11, message: 'Один из счетов заблокирован' };
|
|
41
|
+
}
|
|
42
|
+
const isPinValid = await bcrypt.compare(pinCode, fromAcc.pin_code);
|
|
43
|
+
if (!isPinValid) {
|
|
44
|
+
await t.rollback();
|
|
45
|
+
return { status: false, statusCode: -23, message: 'Неверный пароль счета отправителя' };
|
|
46
|
+
}
|
|
47
|
+
if (fromAcc.user !== 'root' && parseFloat(fromAcc.manny) < numericAmount) {
|
|
48
|
+
await t.rollback();
|
|
49
|
+
return { status: false, statusCode: -11, message: 'Недостаточно средств на счете' };
|
|
50
|
+
}
|
|
51
|
+
if (fromAcc.two_fa_status) {
|
|
52
|
+
const owner = await User.findByPk(fromAcc.user, { transaction: t });
|
|
53
|
+
if (owner && owner.two_fa_status) {
|
|
54
|
+
const isTotpValid = await bcrypt.compare(totpCode, owner.two_fa_token);
|
|
55
|
+
if (!isTotpValid) {
|
|
56
|
+
await t.rollback();
|
|
57
|
+
return { status: false, statusCode: -2, message: 'Неверный токен подтверждения 2FA' };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
await fromAcc.decrement('manny', { by: numericAmount, transaction: t });
|
|
62
|
+
await toAcc.increment('manny', { by: numericAmount, transaction: t });
|
|
63
|
+
await Transaction.create({
|
|
64
|
+
account_id: fromId,
|
|
65
|
+
type: 'TRANSFER_OUT',
|
|
66
|
+
sender_or_receiver: `На счет #${toId} (${toAcc.user})`,
|
|
67
|
+
amount: numericAmount
|
|
68
|
+
}, { transaction: t });
|
|
69
|
+
await Transaction.create({
|
|
70
|
+
account_id: toId,
|
|
71
|
+
type: 'TRANSFER_IN',
|
|
72
|
+
sender_or_receiver: `Со счета #${fromId} (${fromAcc.user})`,
|
|
73
|
+
amount: numericAmount
|
|
74
|
+
}, { transaction: t });
|
|
75
|
+
await t.commit();
|
|
76
|
+
await fromAcc.reload();
|
|
77
|
+
await toAcc.reload();
|
|
78
|
+
try {
|
|
79
|
+
await sendBotNotification('transfer-from-bot', { fromId, toId, amount: numericAmount, balance: fromAcc.manny });
|
|
80
|
+
await sendBotNotification('transfer-to-bot', { toId, fromId, amount: numericAmount, balance: toAcc.manny });
|
|
81
|
+
} catch (botErr) {
|
|
82
|
+
console.log(logger.DatabaseError('Ошибка отправки уведомления боту:', botErr.message))
|
|
83
|
+
}
|
|
84
|
+
return { status: true, statusCode: 1 };
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (!t.finished) {
|
|
87
|
+
await t.rollback();
|
|
88
|
+
}
|
|
89
|
+
return { status: false, statusCode: -10, message: err.message };
|
|
90
|
+
}
|
|
91
|
+
};
|
|
@@ -12,10 +12,19 @@ module.exports = async function createAccount(username, pinCode, enable2FA) {
|
|
|
12
12
|
pin_code: hashedPin,
|
|
13
13
|
manny: 0.00,
|
|
14
14
|
active: true,
|
|
15
|
-
two_fa_status: enable2FA
|
|
15
|
+
two_fa_status: enable2FA,
|
|
16
|
+
cardNumber:null
|
|
16
17
|
});
|
|
17
18
|
return { status: true, statusCode: 1, accountId: newAccount.id };
|
|
18
19
|
} catch (err) {
|
|
20
|
+
console.log(err)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
19
28
|
return { status: false, statusCode: -10, message: err.message };
|
|
20
29
|
}
|
|
21
30
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const Account = require(path.join(__dirname, '..', '..', 'models', 'Account'));
|
|
3
|
+
const logger = require("custom-color-logs").print;
|
|
4
|
+
module.exports = async function linkACard(card, id, pin_code) {
|
|
5
|
+
try {
|
|
6
|
+
const account = await Account.findByPk(id);
|
|
7
|
+
if (!account) return { status: false, statusCode: -2, message: "?¿?" };
|
|
8
|
+
if(!account.active) return { status: false, statusCode: -11, message: 'Один из счетов заблокирован' };
|
|
9
|
+
if (account.pin_code !== pin_code) return { status: false, statusCode: -23, message: "Неправильны пароль!" };
|
|
10
|
+
if (account.cardNumber !== null) return { status: false, statusCode: -19, message: "Карты уже привязана" };
|
|
11
|
+
account.cardNumber = card;
|
|
12
|
+
await account.save();
|
|
13
|
+
return {status: true, statusCode: 1, message: 'Привязка карты удалась'};
|
|
14
|
+
} catch (err) {
|
|
15
|
+
console.log(logger.BankError(err));
|
|
16
|
+
return { status: false, statusCode: -10, message: err.message };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -9,5 +9,7 @@ module.exports = {
|
|
|
9
9
|
findManny: require(path.join(__dirname, 'account', 'find-manny')),
|
|
10
10
|
creatCredit: require(path.join(__dirname, 'account', 'create-credit')),
|
|
11
11
|
getLogs: require(path.join(__dirname, 'account', 'logs')),
|
|
12
|
-
changeAccountStatus: require(path.join(__dirname, 'account', 'change-status'))
|
|
12
|
+
changeAccountStatus: require(path.join(__dirname, 'account', 'change-status')),
|
|
13
|
+
linkACard: require(path.join(__dirname, 'account', 'linkACard')),
|
|
14
|
+
cardTransfer: require(path.join(__dirname, 'account', 'cardTransfer'))
|
|
13
15
|
};
|
package/index.js
CHANGED
|
@@ -11,11 +11,9 @@ const { writeTemplatesIfNotExist } = require(path.join(__dirname, 'database', 's
|
|
|
11
11
|
const registerRoutes = require(path.join(__dirname, 'server', 'server'));
|
|
12
12
|
const Transaction = require(path.join(__dirname, 'database', 'models', 'Transaction'));
|
|
13
13
|
const app = express();
|
|
14
|
-
|
|
15
14
|
const { verifySession } = require(path.join(__dirname, 'server', 'server'));
|
|
16
15
|
app.use(express.json());
|
|
17
16
|
app.use(cookieParser());
|
|
18
|
-
require(path.join(__dirname, 'database', 'services', 'bot', 'cron-schedule'));
|
|
19
17
|
async function Bank() {
|
|
20
18
|
try {
|
|
21
19
|
await sequelize.sync();
|
|
@@ -53,6 +51,8 @@ async function Bank() {
|
|
|
53
51
|
app.get('/home.html', (req, res) => res.sendFile(path.join(__dirname, 'public', 'home.html')));
|
|
54
52
|
app.get('/favicon.ico', (req, res) => res.sendFile(path.join(__dirname, 'public', 'icon', 'icon.png')));
|
|
55
53
|
app.get('/', (req, res) => res.redirect('/home.html'));
|
|
54
|
+
|
|
55
|
+
require(path.join(__dirname, 'database', 'services', 'bot', 'cron-schedule'));
|
|
56
56
|
return configuredApp;
|
|
57
57
|
} catch (err) {
|
|
58
58
|
console.log(logger.ServerBankError("Критическая ошибка инициализации модулей", err));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sequelize-game-bank",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A Sequelize-based gaming economy and banking system featuring user profiles, credits, admin management, and detailed transaction history.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
package/public/accounts.html
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>City-Bank | Мои Счета</title>
|
|
6
6
|
<link rel="stylesheet" href="/css/style.css">
|
|
7
|
+
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/>
|
|
7
8
|
</head>
|
|
8
9
|
<body>
|
|
9
10
|
<div class="main-container">
|
|
@@ -14,12 +15,12 @@
|
|
|
14
15
|
<h2 id="user-display">Загрузка...</h2>
|
|
15
16
|
<p style="text-align: center; color: #bbb;">Всего средств: <span id="total-manny" style="font-weight: bold; color: #1abc9c;">0.00</span> руб.</p>
|
|
16
17
|
<hr style="border-color: #34495e;">
|
|
17
|
-
<a href="/general.html" class="nav-item"><button class="menu-btn">Главная</button></a>
|
|
18
|
-
<a
|
|
19
|
-
<a href="/transfer.html" class="nav-item"><button class="menu-btn">Перевод средств</button></a>
|
|
20
|
-
<a href="/history.html" class="nav-item"><button class="menu-btn">История транзакций</button></a>
|
|
21
|
-
<a href="/credit.html" class="nav-item"><button class="menu-btn">Оформить Кредит</button></a>
|
|
22
|
-
<a href="/profile.html" class="nav-item"><button class="menu-btn">Управление профилем</button></a>
|
|
18
|
+
<a href="/general.html" class="nav-item"><button class="menu-btn" id="general">Главная</button></a>
|
|
19
|
+
<a class="nav-item"><button class="menu-btn active" id="acccount">Мои Счета</button></a>
|
|
20
|
+
<a href="/transfer.html" class="nav-item"><button class="menu-btn" id="transfer">Перевод средств</button></a>
|
|
21
|
+
<a href="/history.html" class="nav-item"><button class="menu-btn" id="history">История транзакций</button></a>
|
|
22
|
+
<a href="/credit.html" class="nav-item"><button class="menu-btn" id="credit">Оформить Кредит</button></a>
|
|
23
|
+
<a href="/profile.html" class="nav-item"><button class="menu-btn" id="profile">Управление профилем</button></a>
|
|
23
24
|
<button class="menu-btn" onclick="location.href='/admin.html'" id="admin-nav" style="display: none; color: #ffc107;">Админ-панель</button>
|
|
24
25
|
<br><br>
|
|
25
26
|
<button class="menu-btn btn-danger" id="logoutBtn" style="text-align: center;">Выйти из системы</button>
|
|
@@ -39,6 +40,8 @@
|
|
|
39
40
|
</div>
|
|
40
41
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"></script>
|
|
41
42
|
<script src="/js/sweetalert2.js"></script>
|
|
43
|
+
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js"></script>
|
|
44
|
+
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js"></script>
|
|
42
45
|
<script src="/js/js.js"></script>
|
|
43
46
|
</body>
|
|
44
47
|
</html>
|
package/public/credit.html
CHANGED
|
@@ -4,26 +4,27 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>City-Bank | Кредитование</title>
|
|
6
6
|
<link rel="stylesheet" href="/css/style.css">
|
|
7
|
+
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/>
|
|
7
8
|
</head>
|
|
8
9
|
<body>
|
|
9
10
|
<div class="main-container">
|
|
10
11
|
<div class="sidebar">
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
<div style="text-align: center; margin-bottom: 15px;">
|
|
13
|
+
<img id="user-avatar" src="/uploads/avatars/default.png" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid #1abc9c;">
|
|
14
|
+
</div>
|
|
15
|
+
<h2 id="user-display">Загрузка...</h2>
|
|
16
|
+
<p style="text-align: center; color: #bbb;">Всего средств: <span id="total-manny" style="font-weight: bold; color: #1abc9c;">0.00</span> руб.</p>
|
|
17
|
+
<hr style="border-color: #34495e;">
|
|
18
|
+
<a href="/general.html" class="nav-item"><button class="menu-btn" id="general">Главная</button></a>
|
|
19
|
+
<a href="/accounts.html" class="nav-item"><button class="menu-btn" id="acccount">Мои Счета</button></a>
|
|
20
|
+
<a href="/transfer.html" class="nav-item"><button class="menu-btn" id="transfer">Перевод средств</button></a>
|
|
21
|
+
<a href="/history.html" class="nav-item"><button class="menu-btn" id="history">История транзакций</button></a>
|
|
22
|
+
<a class="nav-item"><button class="menu-btn active" id="credit">Оформить Кредит</button></a>
|
|
23
|
+
<a href="/profile.html" class="nav-item"><button class="menu-btn" id="profile">Управление профилем</button></a>
|
|
23
24
|
<button class="menu-btn" onclick="location.href='/admin.html'" id="admin-nav" style="display: none; color: #ffc107;">Админ-панель</button>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</div>
|
|
25
|
+
<br><br>
|
|
26
|
+
<button class="menu-btn btn-danger" id="logoutBtn" style="text-align: center;">Выйти из системы</button>
|
|
27
|
+
</div>
|
|
27
28
|
|
|
28
29
|
<div class="container">
|
|
29
30
|
<div class="container-center">
|
|
@@ -82,6 +83,8 @@
|
|
|
82
83
|
</div>
|
|
83
84
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"></script>
|
|
84
85
|
<script src="/js/sweetalert2.js"></script>
|
|
86
|
+
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js"></script>
|
|
87
|
+
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js"></script>
|
|
85
88
|
<script src="/js/js.js"></script>
|
|
86
89
|
</body>
|
|
87
90
|
</html>
|
package/public/css/style.css
CHANGED
package/public/general.html
CHANGED
|
@@ -5,28 +5,29 @@
|
|
|
5
5
|
<title>City-Bank | Главная</title>
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
7
|
<link rel="stylesheet" href="/css/style.css">
|
|
8
|
+
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/>
|
|
8
9
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
|
|
9
10
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
|
|
10
11
|
</head>
|
|
11
12
|
<body>
|
|
12
13
|
<div class="main-container">
|
|
13
14
|
<div class="sidebar">
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
<div style="text-align: center; margin-bottom: 15px;">
|
|
16
|
+
<img id="user-avatar" src="/uploads/avatars/default.png" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid #1abc9c;">
|
|
17
|
+
</div>
|
|
18
|
+
<h2 id="user-display">Загрузка...</h2>
|
|
19
|
+
<p style="text-align: center; color: #bbb;">Всего средств: <span id="total-manny" style="font-weight: bold; color: #1abc9c;">0.00</span> руб.</p>
|
|
20
|
+
<hr style="border-color: #34495e;">
|
|
21
|
+
<a class="nav-item"><button class="menu-btn active" id="general">Главная</button></a>
|
|
22
|
+
<a href="/accounts.html" class="nav-item"><button class="menu-btn" id="acccount">Мои Счета</button></a>
|
|
23
|
+
<a href="/transfer.html" class="nav-item"><button class="menu-btn" id="transfer">Перевод средств</button></a>
|
|
24
|
+
<a href="/history.html" class="nav-item"><button class="menu-btn" id="history">История транзакций</button></a>
|
|
25
|
+
<a href="/credit.html" class="nav-item"><button class="menu-btn" id="credit">Оформить Кредит</button></a>
|
|
26
|
+
<a href="/profile.html" class="nav-item"><button class="menu-btn" id="profile">Управление профилем</button></a>
|
|
26
27
|
<button class="menu-btn" onclick="location.href='/admin.html'" id="admin-nav" style="display: none; color: #ffc107;">Админ-панель</button>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
</div>
|
|
28
|
+
<br><br>
|
|
29
|
+
<button class="menu-btn btn-danger" id="logoutBtn" style="text-align: center;">Выйти из системы</button>
|
|
30
|
+
</div>
|
|
30
31
|
|
|
31
32
|
<div class="container">
|
|
32
33
|
<div class="container-center">
|
|
@@ -48,6 +49,8 @@
|
|
|
48
49
|
</div>
|
|
49
50
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"></script>
|
|
50
51
|
<script src="/js/sweetalert2.js"></script>
|
|
52
|
+
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js"></script>
|
|
53
|
+
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js"></script>
|
|
51
54
|
<script src="/js/js.js"></script>
|
|
52
55
|
</body>
|
|
53
56
|
</html>
|
package/public/history.html
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>City-Bank | История</title>
|
|
6
6
|
<link rel="stylesheet" href="/css/style.css">
|
|
7
|
+
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/>
|
|
7
8
|
</head>
|
|
8
9
|
<body>
|
|
9
10
|
<div class="main-container">
|
|
@@ -14,12 +15,12 @@
|
|
|
14
15
|
<h2 id="user-display">Загрузка...</h2>
|
|
15
16
|
<p style="text-align: center; color: #bbb;">Всего средств: <span id="total-manny" style="font-weight: bold; color: #1abc9c;">0.00</span> руб.</p>
|
|
16
17
|
<hr style="border-color: #34495e;">
|
|
17
|
-
<a href="/general.html" class="nav-item"><button class="menu-btn
|
|
18
|
-
<a href="/accounts.html" class="nav-item"><button class="menu-btn">Мои Счета</button></a>
|
|
19
|
-
<a href="/transfer.html" class="nav-item"><button class="menu-btn">Перевод средств</button></a>
|
|
20
|
-
<a
|
|
21
|
-
<a href="/credit.html" class="nav-item"><button class="menu-btn">Оформить Кредит</button></a>
|
|
22
|
-
<a href="/profile.html" class="nav-item"><button class="menu-btn">Управление профилем</button></a>
|
|
18
|
+
<a href="/general.html" class="nav-item"><button class="menu-btn" id="general">Главная</button></a>
|
|
19
|
+
<a href="/accounts.html" class="nav-item"><button class="menu-btn" id="acccount">Мои Счета</button></a>
|
|
20
|
+
<a href="/transfer.html" class="nav-item"><button class="menu-btn" id="transfer">Перевод средств</button></a>
|
|
21
|
+
<a class="nav-item"><button class="menu-btn active" id="history">История транзакций</button></a>
|
|
22
|
+
<a href="/credit.html" class="nav-item"><button class="menu-btn" id="credit">Оформить Кредит</button></a>
|
|
23
|
+
<a href="/profile.html" class="nav-item"><button class="menu-btn" id="profile">Управление профилем</button></a>
|
|
23
24
|
<button class="menu-btn" onclick="location.href='/admin.html'" id="admin-nav" style="display: none; color: #ffc107;">Админ-панель</button>
|
|
24
25
|
<br><br>
|
|
25
26
|
<button class="menu-btn btn-danger" id="logoutBtn" style="text-align: center;">Выйти из системы</button>
|
|
@@ -57,6 +58,8 @@
|
|
|
57
58
|
</dialog>
|
|
58
59
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"></script>
|
|
59
60
|
<script src="/js/sweetalert2.js"></script>
|
|
61
|
+
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js"></script>
|
|
62
|
+
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js"></script>
|
|
60
63
|
<script src="/js/js.js"></script>
|
|
61
64
|
</body>
|
|
62
65
|
</html>
|
package/public/js/js.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
const toastifyScript = document.createElement('script');
|
|
3
3
|
toastifyScript.src = 'https://cdn.jsdelivr.net/npm/toastify-js';
|
|
4
4
|
document.head.append(toastifyScript);
|
|
5
|
-
|
|
6
|
-
|
|
7
5
|
let currentUsername = "";
|
|
8
6
|
|
|
9
7
|
function showTab(tabId) {
|
|
@@ -12,6 +10,66 @@ let currentUsername = "";
|
|
|
12
10
|
document.getElementById(tabId).classList.add('active');
|
|
13
11
|
event.target.classList.add('active');
|
|
14
12
|
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
window.tippy('#general', {
|
|
19
|
+
content: "Главная",
|
|
20
|
+
placement:'top-end',
|
|
21
|
+
arrow: false,
|
|
22
|
+
animation:'scale-extreme',
|
|
23
|
+
theme:"light"
|
|
24
|
+
});
|
|
25
|
+
window.tippy('#acccount', {
|
|
26
|
+
content: "Щета",
|
|
27
|
+
placement:'top-end',
|
|
28
|
+
arrow: false,
|
|
29
|
+
animation:'scale-extreme',
|
|
30
|
+
theme:"light"
|
|
31
|
+
});
|
|
32
|
+
window.tippy('#transfer', {
|
|
33
|
+
content: "Перевод",
|
|
34
|
+
placement:'top-end',
|
|
35
|
+
arrow: false,
|
|
36
|
+
animation:'scale-extreme',
|
|
37
|
+
theme:"light"
|
|
38
|
+
});
|
|
39
|
+
window.tippy('#history', {
|
|
40
|
+
content: "История",
|
|
41
|
+
placement:'top-end',
|
|
42
|
+
arrow: false,
|
|
43
|
+
animation:'scale-extreme',
|
|
44
|
+
theme:"light"
|
|
45
|
+
});
|
|
46
|
+
window.tippy('#credit', {
|
|
47
|
+
content: "Кредит",
|
|
48
|
+
placement:'top-end',
|
|
49
|
+
arrow: false,
|
|
50
|
+
animation:'scale-extreme',
|
|
51
|
+
theme:"light"
|
|
52
|
+
});
|
|
53
|
+
window.tippy('#profile', {
|
|
54
|
+
content: "Редактировать профиль",
|
|
55
|
+
placement:'top-end',
|
|
56
|
+
arrow: false,
|
|
57
|
+
animation:'scale-extreme',
|
|
58
|
+
theme:"light"
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
15
73
|
async function loadData() {
|
|
16
74
|
try {
|
|
17
75
|
let response = await fetch('/api/accounts/my');
|
|
@@ -97,6 +155,13 @@ let currentUsername = "";
|
|
|
97
155
|
let profileRes = await fetch('/api/users/profile');
|
|
98
156
|
let profileData = await profileRes.json();
|
|
99
157
|
const userAvatar = document.getElementById('user-avatar');
|
|
158
|
+
window.tippy("#user-avatar", {
|
|
159
|
+
content:`<span style='color:blue'>${currentUsername.toLocaleUpperCase()}</span> — <span style='color:lightgreen;'>${mannyData.totalManny.toFixed(2)}</span>`,
|
|
160
|
+
placement:"right",
|
|
161
|
+
allowHTML:true,
|
|
162
|
+
theme:'user-info',
|
|
163
|
+
arrow:false
|
|
164
|
+
})
|
|
100
165
|
const userAvatar2 = document.getElementById('user-avatar2');
|
|
101
166
|
if (profileData.status && profileData.user && profileData.user.avatar && userAvatar) {
|
|
102
167
|
userAvatar.src = profileData.user.avatar;
|
|
@@ -120,6 +185,33 @@ let currentUsername = "";
|
|
|
120
185
|
});
|
|
121
186
|
}
|
|
122
187
|
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
123
215
|
async function openCreateAccountModal() {
|
|
124
216
|
const pin = await window.Swal.fire({title: 'Создание щёта', text: 'Введите надёжный пин-код!', icon: 'question', iconColor:"blue", input:"number", inputAttributes: { autocapitalize: "off" }, preConfirm:async(pincode)=>{return pincode}, confirmButtonText: 'ОК', confirmButtonColor: '#3085d6', background:'#ffffffaf'})
|
|
125
217
|
if (!pin.value) return;
|
|
@@ -191,33 +283,25 @@ let currentUsername = "";
|
|
|
191
283
|
|
|
192
284
|
|
|
193
285
|
async function applyForCredit() {
|
|
194
|
-
// 1. Извлекаем значения из ваших оригинальных ID элементов HTML
|
|
195
286
|
const targetAccountId = document.getElementById('credit-target').value;
|
|
196
287
|
const amount = document.getElementById('credit-amount').value;
|
|
197
288
|
const paymentsCount = document.getElementById('credit-payments').value;
|
|
198
289
|
const autoWithdrawal = document.getElementById('credit-auto').checked;
|
|
199
290
|
const pinCode = document.getElementById('credit-pin').value;
|
|
200
|
-
|
|
201
|
-
// 2. Отправляем fetch-запрос на ваш бэкенд-роут
|
|
202
291
|
const res = await fetch('/api/accounts/credit', {
|
|
203
292
|
method: 'POST',
|
|
204
293
|
headers: {'Content-Type': 'application/json'},
|
|
205
|
-
// Маппим ваши оригинальные фронтенд-переменные в ключи, которые ожидает бэкенд-сервис
|
|
206
294
|
body: JSON.stringify({
|
|
207
|
-
accountId: targetAccountId,
|
|
208
|
-
amount: parseFloat(amount),
|
|
209
|
-
termMonths: parseInt(paymentsCount, 10),
|
|
210
|
-
autoRepay: autoWithdrawal,
|
|
211
|
-
pinCode: pinCode,
|
|
212
|
-
rate: 0.1
|
|
295
|
+
accountId: targetAccountId,
|
|
296
|
+
amount: parseFloat(amount),
|
|
297
|
+
termMonths: parseInt(paymentsCount, 10),
|
|
298
|
+
autoRepay: autoWithdrawal,
|
|
299
|
+
pinCode: pinCode,
|
|
300
|
+
rate: 0.1
|
|
213
301
|
})
|
|
214
302
|
});
|
|
215
|
-
|
|
216
303
|
const data = await res.json();
|
|
217
|
-
|
|
218
|
-
// 3. Обработка ответа от сервера
|
|
219
|
-
if(data.success || data.status) { // Проверяем оба флага для надежности
|
|
220
|
-
// ИСПРАВЛЕНО: 'sucess' изменено на валидное 'success' (теперь окно сработает и не упадет в ошибку)
|
|
304
|
+
if(data.success || data.status) {
|
|
221
305
|
await Swal.fire({
|
|
222
306
|
title: 'Кредит',
|
|
223
307
|
text: "Кредит одобрен! Деньги зачислены на счет #" + (data.creditId || data.creditAccountId),
|
|
@@ -232,7 +316,7 @@ async function applyForCredit() {
|
|
|
232
316
|
style: { background: "rgb(58, 245, 11)" }
|
|
233
317
|
}).showToast();
|
|
234
318
|
|
|
235
|
-
if (typeof loadData === 'function') loadData();
|
|
319
|
+
if (typeof loadData === 'function') loadData();
|
|
236
320
|
} else {
|
|
237
321
|
await Swal.fire({
|
|
238
322
|
title: 'Кредит',
|
|
@@ -245,8 +329,6 @@ async function applyForCredit() {
|
|
|
245
329
|
console.error("Ошибка: " + (data.error || data.message));
|
|
246
330
|
}
|
|
247
331
|
}
|
|
248
|
-
|
|
249
|
-
// Обработчик кнопки выхода из системы
|
|
250
332
|
document.getElementById("logoutBtn").addEventListener("click", async () => {
|
|
251
333
|
const logOut = await Swal.fire({
|
|
252
334
|
title: 'Выход',
|
|
@@ -269,8 +351,6 @@ document.getElementById("logoutBtn").addEventListener("click", async () => {
|
|
|
269
351
|
} catch (e) {
|
|
270
352
|
console.error('Ошибка сети при логауте:', e.message);
|
|
271
353
|
}
|
|
272
|
-
|
|
273
|
-
// ИСПРАВЛЕНО: перенаправление на чистый роут без расширения .html
|
|
274
354
|
window.location.href = '/home.html';
|
|
275
355
|
});
|
|
276
356
|
|
package/public/profile.html
CHANGED
|
@@ -4,26 +4,27 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>City-Bank | Профиль</title>
|
|
6
6
|
<link rel="stylesheet" href="/css/style.css">
|
|
7
|
+
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/>
|
|
7
8
|
</head>
|
|
8
9
|
<body>
|
|
9
10
|
<div class="main-container">
|
|
10
11
|
<div class="sidebar">
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
<div style="text-align: center; margin-bottom: 15px;">
|
|
13
|
+
<img id="user-avatar" src="/uploads/avatars/default.png" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid #1abc9c;">
|
|
14
|
+
</div>
|
|
15
|
+
<h2 id="user-display">Загрузка...</h2>
|
|
16
|
+
<p style="text-align: center; color: #bbb;">Всего средств: <span id="total-manny" style="font-weight: bold; color: #1abc9c;">0.00</span> руб.</p>
|
|
17
|
+
<hr style="border-color: #34495e;">
|
|
18
|
+
<a href="/general.html" class="nav-item"><button class="menu-btn" id="general">Главная</button></a>
|
|
19
|
+
<a href="/accounts.html" class="nav-item"><button class="menu-btn" id="acccount">Мои Счета</button></a>
|
|
20
|
+
<a href="/transfer.html" class="nav-item"><button class="menu-btn" id="transfer">Перевод средств</button></a>
|
|
21
|
+
<a href="/history.html" class="nav-item"><button class="menu-btn" id="history">История транзакций</button></a>
|
|
22
|
+
<a href="/credit.html" class="nav-item"><button class="menu-btn" id="credit">Оформить Кредит</button></a>
|
|
23
|
+
<a class="nav-item"><button class="menu-btn active" id="profile">Управление профилем</button></a>
|
|
23
24
|
<button class="menu-btn" onclick="location.href='/admin.html'" id="admin-nav" style="display: none; color: #ffc107;">Админ-панель</button>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</div>
|
|
25
|
+
<br><br>
|
|
26
|
+
<button class="menu-btn btn-danger" id="logoutBtn" style="text-align: center;">Выйти из системы</button>
|
|
27
|
+
</div>
|
|
27
28
|
|
|
28
29
|
<div class="container">
|
|
29
30
|
<div class="container-center">
|
|
@@ -73,6 +74,8 @@
|
|
|
73
74
|
</div>
|
|
74
75
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"></script>
|
|
75
76
|
<script src="/js/sweetalert2.js"></script>
|
|
77
|
+
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js"></script>
|
|
78
|
+
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js"></script>
|
|
76
79
|
<script src="/js/js.js"></script>
|
|
77
80
|
</body>
|
|
78
81
|
</html>
|
package/public/transfer.html
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>City-Bank | Переводы</title>
|
|
6
6
|
<link rel="stylesheet" href="/css/style.css">
|
|
7
|
+
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/>
|
|
7
8
|
</head>
|
|
8
9
|
<body>
|
|
9
10
|
<div class="main-container">
|
|
@@ -14,13 +15,13 @@
|
|
|
14
15
|
<h2 id="user-display">Загрузка...</h2>
|
|
15
16
|
<p style="text-align: center; color: #bbb;">Всего средств: <span id="total-manny" style="font-weight: bold; color: #1abc9c;">0.00</span> руб.</p>
|
|
16
17
|
<hr style="border-color: #34495e;">
|
|
17
|
-
<a href="/general.html" class="nav-item"><button class="menu-btn">Главная</button></a>
|
|
18
|
-
<a href="/accounts.html" class="nav-item"><button class="menu-btn">Мои Счета</button></a>
|
|
19
|
-
<a
|
|
20
|
-
<a href="/history.html" class="nav-item"><button class="menu-btn">История транзакций</button></a>
|
|
21
|
-
<a href="/credit.html" class="nav-item"><button class="menu-btn">Оформить Кредит</button></a>
|
|
22
|
-
<a href="/profile.html" class="nav-item"><button class="menu-btn">Управление профилем</button></a>
|
|
23
|
-
|
|
18
|
+
<a href="/general.html" class="nav-item"><button class="menu-btn" id="general">Главная</button></a>
|
|
19
|
+
<a href="/accounts.html" class="nav-item"><button class="menu-btn" id="acccount">Мои Счета</button></a>
|
|
20
|
+
<a class="nav-item"><button class="menu-btn active" id="transfer">Перевод средств</button></a>
|
|
21
|
+
<a href="/history.html" class="nav-item"><button class="menu-btn" id="history">История транзакций</button></a>
|
|
22
|
+
<a href="/credit.html" class="nav-item"><button class="menu-btn" id="credit">Оформить Кредит</button></a>
|
|
23
|
+
<a href="/profile.html" class="nav-item"><button class="menu-btn" id="profile">Управление профилем</button></a>
|
|
24
|
+
<button class="menu-btn" onclick="location.href='/admin.html'" id="admin-nav" style="display: none; color: #ffc107;">Админ-панель</button>
|
|
24
25
|
<br><br>
|
|
25
26
|
<button class="menu-btn btn-danger" id="logoutBtn" style="text-align: center;">Выйти из системы</button>
|
|
26
27
|
</div>
|
|
@@ -54,6 +55,8 @@
|
|
|
54
55
|
</div>
|
|
55
56
|
</div>
|
|
56
57
|
<script src="/js/sweetalert2.js"></script>
|
|
58
|
+
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js"></script>
|
|
59
|
+
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js"></script>
|
|
57
60
|
<script src="/js/js.js"></script>
|
|
58
61
|
</body>
|
|
59
62
|
</html>
|
|
Binary file
|
|
Binary file
|
package/server/server.js
CHANGED
|
@@ -210,9 +210,22 @@ module.exports = function registerRoutes(app) {
|
|
|
210
210
|
const result = await accountsHub.getLogs(req.user.name);
|
|
211
211
|
return res.json(result);
|
|
212
212
|
});
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
app.post('/api/terminal/login', async(req, res)=>{
|
|
214
|
+
if(!req.body) return res.sendStatus(400)
|
|
215
|
+
const id = req.body.id;
|
|
216
|
+
const pincode = req.body.pincode;
|
|
217
|
+
const card = req.body.card;
|
|
218
|
+
const result = await accountsHub.linkACard(card, id, pincode)
|
|
219
|
+
if(!result.status) return res.sendStatus(422)
|
|
220
|
+
return res.sendStatus(200);
|
|
221
|
+
});
|
|
222
|
+
app.post('/api/terminal/transfer', async(req, res)=>{
|
|
223
|
+
const card = req.body.card;
|
|
224
|
+
const to = req.body.to;
|
|
225
|
+
const pincode = req.body.pincode;
|
|
226
|
+
const manny = req.body.pinCode;
|
|
227
|
+
const result = await accountsHub.cardTransfer(card, to, manny, pincode)
|
|
228
|
+
});
|
|
216
229
|
return app;
|
|
217
230
|
};
|
|
218
231
|
module.exports.verifySession = verifySession;
|