260217:1607 20260217 fix permission
All checks were successful
Build and Deploy / deploy (push) Successful in 3m11s
All checks were successful
Build and Deploy / deploy (push) Successful in 3m11s
This commit is contained in:
100
_backend_logs.txt
Normal file
100
_backend_logs.txt
Normal file
@@ -0,0 +1,100 @@
|
||||
at Readable.push (node:internal/streams/readable:392:5) {
|
||||
|
||||
query: 'DELETE FROM `notifications` WHERE (`is_read` = ? AND `createdAt` < ?)',
|
||||
|
||||
parameters: [
|
||||
|
||||
true,
|
||||
|
||||
2026-01-17T17:00:00.024Z
|
||||
|
||||
],
|
||||
|
||||
driverError: Error: Unknown column 'createdAt' in 'WHERE'
|
||||
|
||||
at Packet.asError (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/packets/packet.js:740:17)
|
||||
|
||||
at Query.execute (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/commands/command.js:29:26)
|
||||
|
||||
at PoolConnection.handlePacket (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/base/connection.js:477:34)
|
||||
|
||||
at PacketParser.onPacket (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/base/connection.js:93:12)
|
||||
|
||||
at PacketParser.executeStart (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/packet_parser.js:75:16)
|
||||
|
||||
at Socket.<anonymous> (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/base/connection.js:100:25)
|
||||
|
||||
at Socket.emit (node:events:519:28)
|
||||
|
||||
at addChunk (node:internal/streams/readable:561:12)
|
||||
|
||||
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
|
||||
|
||||
at Readable.push (node:internal/streams/readable:392:5) {
|
||||
|
||||
code: 'ER_BAD_FIELD_ERROR',
|
||||
|
||||
errno: 1054,
|
||||
|
||||
sqlState: '42S22',
|
||||
|
||||
sqlMessage: "Unknown column 'createdAt' in 'WHERE'",
|
||||
|
||||
sql: "DELETE FROM `notifications` WHERE (`is_read` = true AND `createdAt` < '2026-01-18 00:00:00.024')"
|
||||
|
||||
},
|
||||
|
||||
code: 'ER_BAD_FIELD_ERROR',
|
||||
|
||||
errno: 1054,
|
||||
|
||||
sqlState: '42S22',
|
||||
|
||||
sqlMessage: "Unknown column 'createdAt' in 'WHERE'",
|
||||
|
||||
sql: "DELETE FROM `notifications` WHERE (`is_read` = true AND `createdAt` < '2026-01-18 00:00:00.024')"
|
||||
|
||||
}
|
||||
|
||||
[Nest] 1 - 02/17/2026, 12:00:00 AM LOG [FileCleanupService] No expired files found.
|
||||
|
||||
[Nest] 1 - 02/17/2026, 12:00:00 AM ERROR [NotificationCleanupService] Failed to cleanup notifications
|
||||
|
||||
[Nest] 1 - 02/17/2026, 12:00:00 AM ERROR [NotificationCleanupService] QueryFailedError: Unknown column 'createdAt' in 'WHERE'
|
||||
|
||||
at Query.onResult (/app/node_modules/.pnpm/typeorm@0.3.27_ioredis@5.8.2_mysql2@3.15.3_redis@4.7.1_reflect-metadata@0.2.2_ts-node@1_cb81dfd56f1203fe00eb0fec5dfcce08/node_modules/typeorm/driver/mysql/MysqlQueryRunner.js:168:37)
|
||||
|
||||
at Query.execute (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/commands/command.js:36:14)
|
||||
|
||||
at PoolConnection.handlePacket (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/base/connection.js:477:34)
|
||||
|
||||
at PacketParser.onPacket (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/base/connection.js:93:12)
|
||||
|
||||
at PacketParser.executeStart (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/packet_parser.js:75:16)
|
||||
|
||||
at Socket.<anonymous> (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/base/connection.js:100:25)
|
||||
|
||||
at Socket.emit (node:events:519:28)
|
||||
|
||||
at addChunk (node:internal/streams/readable:561:12)
|
||||
|
||||
at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
|
||||
|
||||
at Readable.push (node:internal/streams/readable:392:5) {
|
||||
|
||||
query: 'DELETE FROM `notifications` WHERE (`is_read` = ? AND `createdAt` < ?)',
|
||||
|
||||
parameters: [
|
||||
|
||||
true,
|
||||
|
||||
2026-01-17T17:00:00.038Z
|
||||
|
||||
],
|
||||
|
||||
driverError: Error: Unknown column 'createdAt' in 'WHERE'
|
||||
|
||||
at Packet.asError (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/packets/packet.js:740:17)
|
||||
|
||||
at Query.execute (/app/node_modules/.pnpm/mysql2@3.15.3/node_modules/mysql2/lib/commands/command.js:29:26)
|
||||
|
||||
@@ -10,7 +10,7 @@ export class NotificationCleanupService {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(Notification)
|
||||
private notificationRepo: Repository<Notification>,
|
||||
private notificationRepo: Repository<Notification>
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -26,10 +26,14 @@ export class NotificationCleanupService {
|
||||
dateThreshold.setDate(dateThreshold.getDate() - daysAgo);
|
||||
|
||||
try {
|
||||
const result = await this.notificationRepo.delete({
|
||||
isRead: true,
|
||||
createdAt: LessThan(dateThreshold),
|
||||
});
|
||||
const result = await this.notificationRepo
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(Notification)
|
||||
.where('is_read = :isRead', { isRead: true })
|
||||
// Use column name 'created_at' explicitly
|
||||
.andWhere('created_at < :dateThreshold', { dateThreshold })
|
||||
.execute();
|
||||
|
||||
this.logger.log(`Deleted ${result.affected} old read notifications.`);
|
||||
} catch (error) {
|
||||
|
||||
29
specs/07-database/fix-project-permissions.sql
Normal file
29
specs/07-database/fix-project-permissions.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- Fix Project Permissions
|
||||
-- File: specs/07-database/fix-project-permissions.sql
|
||||
-- 1. Ensure project.view permission exists
|
||||
INSERT IGNORE INTO permissions (
|
||||
permission_id,
|
||||
permission_name,
|
||||
description,
|
||||
module,
|
||||
is_active
|
||||
)
|
||||
VALUES (
|
||||
202,
|
||||
'project.view',
|
||||
'ดูรายการโครงการ',
|
||||
'project',
|
||||
1
|
||||
);
|
||||
-- 2. Grant project.view to Superadmin (Role 1)
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (1, 202);
|
||||
-- 3. Grant project.view to Organization Admin (Role 2)
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (2, 202);
|
||||
-- 4. Grant project.view to Project Manager (Role 6)
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (6, 202);
|
||||
-- 5. Grant project.view to Viewer (Role 5)
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (5, 202);
|
||||
@@ -297,6 +297,9 @@ services:
|
||||
<<: [*restart_policy, *default_logging]
|
||||
image: gcr.io/cadvisor/cadvisor:v0.47.2
|
||||
container_name: cadvisor
|
||||
privileged: true
|
||||
devices:
|
||||
- /dev/kmsg
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
@@ -313,6 +316,7 @@ services:
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/healthz"]
|
||||
interval: 30s
|
||||
@@ -421,6 +425,20 @@ services:
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:ro
|
||||
|
||||
mysqld-exporter:
|
||||
image: prom/mysqld-exporter:v0.15.0
|
||||
container_name: mysqld-exporter
|
||||
restart: unless-stopped
|
||||
user: root
|
||||
command:
|
||||
- '--config.my-cnf=/etc/mysql/my.cnf'
|
||||
ports:
|
||||
- "9104:9104"
|
||||
networks:
|
||||
- lcbp3
|
||||
volumes:
|
||||
- "/share/np-dms/monitoring/mysqld-exporter/.my.cnf:/etc/mysql/my.cnf:ro"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -484,12 +502,12 @@ scrape_configs:
|
||||
host: 'qnap'
|
||||
metrics_path: '/metrics'
|
||||
|
||||
# MariaDB Exporter (optional - QNAP)
|
||||
# - job_name: 'mariadb'
|
||||
# static_configs:
|
||||
# - targets: ['192.168.10.8:9104']
|
||||
# labels:
|
||||
# host: 'qnap'
|
||||
# MariaDB Exporter (QNAP)
|
||||
- job_name: 'mariadb'
|
||||
static_configs:
|
||||
- targets: ['192.168.10.8:9104']
|
||||
labels:
|
||||
host: 'qnap'
|
||||
```
|
||||
|
||||
---
|
||||
@@ -518,15 +536,16 @@ scrape_configs:
|
||||
|
||||
### Recommended Dashboards to Import
|
||||
|
||||
| Dashboard ID | Name | Purpose |
|
||||
| :----------- | :--------------------------- | :------------------ |
|
||||
| 1860 | Node Exporter Full | Host system metrics | ป |
|
||||
| 14282 | cAdvisor exporter | Container metrics | ป |
|
||||
| 11074 | Node Exporter for Prometheus | Node overview |
|
||||
| 893 | Docker and Container | Docker overview |
|
||||
| 7362 | MySQL | MySQL view |
|
||||
| 1214 | Redis | Redis view |
|
||||
| 14204 | Elasticsearch | Elasticsearch view |
|
||||
| Dashboard ID | Name | Purpose |
|
||||
| :----------- | :--------------------------- | :----------------------------- |
|
||||
| 1860 | Node Exporter Full | Host system metrics |
|
||||
| 14282 | cAdvisor exporter | Container metrics |
|
||||
| 11074 | Node Exporter for Prometheus | Node overview |
|
||||
| 893 | Docker and Container | Docker overview |
|
||||
| 7362 | MySQL | MySQL view |
|
||||
| 1214 | Redis | Redis view |
|
||||
| 14204 | Elasticsearch | Elasticsearch view |
|
||||
| 13106 | MySQL/MariaDB Overview | Detailed MySQL/MariaDB metrics |
|
||||
|
||||
|
||||
### Import Dashboard via Grafana UI
|
||||
@@ -546,7 +565,7 @@ scrape_configs:
|
||||
| :--- | :------------------------------------------------------------------------------------------------- | :----- |
|
||||
| 1 | SSH เข้า ASUSTOR ได้ (`ssh admin@192.168.10.9`) | ✅ |
|
||||
| 2 | Docker Network `lcbp3` สร้างแล้ว (ดูหัวข้อ [สร้าง Docker Network](#-สร้าง-docker-network-ทำครั้งแรกครั้งเดียว)) | ✅ |
|
||||
| 3 | สร้าง Directories และกำหนดสิทธิ์แล้ว (ดูหัวข้อ [กำหนดสิทธิ](#กำหนดสิทธิ-บน-asustor)) | ✅ |
|
||||
| 3 | สร้าง Directories และกำหนดสิทธิ์แล้ว (ดูหัวข้อ [กำหนดสิทธิ](#กำหนดสิทธิ-บน-asustor)) | ✅ |
|
||||
| 4 | สร้าง `prometheus.yml` แล้ว (ดูหัวข้อ [Prometheus Configuration](#prometheus-configuration)) | ✅ |
|
||||
| 5 | สร้าง `promtail-config.yml` แล้ว (ดูหัวข้อ [Step 1.2](#step-12-สร้าง-promtail-configyml)) | ✅ |
|
||||
|
||||
@@ -635,6 +654,41 @@ scrape_configs:
|
||||
target_label: 'stream'
|
||||
EOF
|
||||
|
||||
# ขั้นตอนการเตรียมระบบที่ QNAP (ก่อน Deploy Stack)
|
||||
|
||||
### 1. สร้าง Monitoring User ใน MariaDB
|
||||
รันคำสั่ง SQL นี้ผ่าน **phpMyAdmin** หรือ `docker exec`:
|
||||
```sql
|
||||
CREATE USER 'exporter'@'%' IDENTIFIED BY 'Center2025' WITH MAX_USER_CONNECTIONS 3;
|
||||
GRANT PROCESS, REPLICATION CLIENT, SELECT, SLAVE MONITOR ON *.* TO 'exporter'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
### 2. สร้างไฟล์คอนฟิก .my.cnf บน QNAP
|
||||
เพื่อให้ `mysqld-exporter` อ่านรหัสผ่านที่มีตัวอักษรพิเศษได้ถูกต้อง:
|
||||
|
||||
1. **SSH เข้า QNAP** (หรือใช้ File Station สร้าง Folder):
|
||||
```bash
|
||||
ssh admin@192.168.10.8
|
||||
```
|
||||
2. **สร้าง Directory สำหรับเก็บ Config**:
|
||||
```bash
|
||||
mkdir -p /share/np-dms/monitoring/mysqld-exporter
|
||||
```
|
||||
3. **สร้างไฟล์ .my.cnf**:
|
||||
```bash
|
||||
cat > /share/np-dms/monitoring/mysqld-exporter/.my.cnf << 'EOF'
|
||||
[client]
|
||||
user=exporter
|
||||
password=Center2025
|
||||
host=mariadb
|
||||
EOF
|
||||
```
|
||||
4. **กำหนดสิทธิ์ไฟล์** (เพื่อให้ Container อ่านไฟล์ได้):
|
||||
```bash
|
||||
chmod 644 /share/np-dms/monitoring/mysqld-exporter/.my.cnf
|
||||
```
|
||||
|
||||
# ตรวจสอบ
|
||||
cat /volume1/np-dms/monitoring/promtail/config/promtail-config.yml
|
||||
```
|
||||
|
||||
@@ -51,6 +51,11 @@ docker exec -it mariadb mysql -u root -p
|
||||
CREATE USER 'gitea'@'%' IDENTIFIED BY 'Center#2025';
|
||||
GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
docker exec -it mariadb mysql -u root -p
|
||||
CREATE USER 'exporter'@'%' IDENTIFIED BY 'Center#2025' WITH MAX_USER_CONNECTIONS 3;
|
||||
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
## Docker file
|
||||
|
||||
Reference in New Issue
Block a user