auto commit
This commit is contained in:
parent
6320be5717
commit
ef73aae117
20
.gitignore
vendored
20
.gitignore
vendored
@ -1,13 +1,21 @@
|
||||
# Env files
|
||||
.env*
|
||||
!.env.example
|
||||
backups/
|
||||
logs/
|
||||
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
config/
|
||||
|
||||
# Data directories
|
||||
backups/
|
||||
init-scripts/
|
||||
logs/
|
||||
shared/
|
||||
fems-mqtt/log/mosquitto.log
|
||||
fems-mqtt/data/
|
||||
|
||||
# Mosquitto specific
|
||||
fems-mqtt/config/
|
||||
!fems-mqtt/log/
|
||||
!fems-mqtt/log/mosquitto.log
|
||||
!fems-mqtt/data/
|
||||
!fems-mqtt/data/mosquitto.db
|
208
fems-app/src/config/permissions.ts
Normal file
208
fems-app/src/config/permissions.ts
Normal file
@ -0,0 +1,208 @@
|
||||
// src/config/permissions.ts
|
||||
|
||||
// 기본 권한 정의
|
||||
export const PERMISSIONS = {
|
||||
// 회사 관련 권한
|
||||
COMPANY_VIEW: "company:view",
|
||||
COMPANY_EDIT: "company:edit",
|
||||
COMPANY_DELETE: "company:delete",
|
||||
|
||||
// 지점/공장 관련 권한
|
||||
BRANCH_VIEW: "branch:view",
|
||||
BRANCH_CREATE: "branch:create",
|
||||
BRANCH_EDIT: "branch:edit",
|
||||
BRANCH_DELETE: "branch:delete",
|
||||
|
||||
// 사용자 관련 권한
|
||||
USER_VIEW: "user:view",
|
||||
USER_CREATE: "user:create",
|
||||
USER_EDIT: "user:edit",
|
||||
USER_DELETE: "user:delete",
|
||||
|
||||
// 부서 관련 권한
|
||||
DEPARTMENT_VIEW: "department:view",
|
||||
DEPARTMENT_CREATE: "department:create",
|
||||
DEPARTMENT_EDIT: "department:edit",
|
||||
DEPARTMENT_DELETE: "department:delete",
|
||||
|
||||
// 설비 관련 권한
|
||||
EQUIPMENT_VIEW: "equipment:view",
|
||||
EQUIPMENT_CREATE: "equipment:create",
|
||||
EQUIPMENT_EDIT: "equipment:edit",
|
||||
EQUIPMENT_DELETE: "equipment:delete",
|
||||
|
||||
// 에너지 모니터링 권한
|
||||
ENERGY_VIEW: "energy:view",
|
||||
ENERGY_ANALYZE: "energy:analyze",
|
||||
|
||||
// 알람 관련 권한
|
||||
ALARM_VIEW: "alarm:view",
|
||||
ALARM_CREATE: "alarm:create",
|
||||
ALARM_EDIT: "alarm:edit",
|
||||
ALARM_DELETE: "alarm:delete",
|
||||
|
||||
// 보고서 관련 권한
|
||||
REPORT_VIEW: "report:view",
|
||||
REPORT_CREATE: "report:create",
|
||||
REPORT_EDIT: "report:edit",
|
||||
REPORT_DELETE: "report:delete",
|
||||
|
||||
// 설정 관련 권한
|
||||
SETTINGS_VIEW: "settings:view",
|
||||
SETTINGS_EDIT: "settings:edit",
|
||||
} as const;
|
||||
|
||||
// 경로별 필요 권한 정의
|
||||
export const PATH_PERMISSIONS: Record<string, string[]> = {
|
||||
// 대시보드
|
||||
"/dashboard": [PERMISSIONS.ENERGY_VIEW],
|
||||
"/dashboard/overview": [PERMISSIONS.ENERGY_VIEW],
|
||||
"/dashboard/kpi": [PERMISSIONS.ENERGY_VIEW],
|
||||
"/dashboard/costs": [PERMISSIONS.ENERGY_VIEW],
|
||||
|
||||
// 에너지 모니터링
|
||||
"/monitoring/electricity": [PERMISSIONS.ENERGY_VIEW],
|
||||
"/monitoring/gas": [PERMISSIONS.ENERGY_VIEW],
|
||||
"/monitoring/water": [PERMISSIONS.ENERGY_VIEW],
|
||||
"/monitoring/steam": [PERMISSIONS.ENERGY_VIEW],
|
||||
|
||||
// 설비 관리
|
||||
"/equipment": [PERMISSIONS.EQUIPMENT_VIEW],
|
||||
"/equipment/inventory": [PERMISSIONS.EQUIPMENT_VIEW],
|
||||
"/equipment/monitoring": [PERMISSIONS.EQUIPMENT_VIEW],
|
||||
"/equipment/maintenance": [PERMISSIONS.EQUIPMENT_VIEW],
|
||||
"/equipment/create": [PERMISSIONS.EQUIPMENT_CREATE],
|
||||
"/equipment/edit": [PERMISSIONS.EQUIPMENT_EDIT],
|
||||
|
||||
// 분석/리포트
|
||||
"/analysis": [PERMISSIONS.ENERGY_ANALYZE],
|
||||
"/analysis/energy": [PERMISSIONS.ENERGY_ANALYZE],
|
||||
"/analysis/efficiency": [PERMISSIONS.ENERGY_ANALYZE],
|
||||
"/analysis/reports": [PERMISSIONS.REPORT_VIEW],
|
||||
"/analysis/reports/create": [PERMISSIONS.REPORT_CREATE],
|
||||
"/analysis/reports/edit": [PERMISSIONS.REPORT_EDIT],
|
||||
|
||||
// 알람/이벤트
|
||||
"/alarm": [PERMISSIONS.ALARM_VIEW],
|
||||
"/alarm/realtime": [PERMISSIONS.ALARM_VIEW],
|
||||
"/alarm/history": [PERMISSIONS.ALARM_VIEW],
|
||||
"/alarm/settings": [PERMISSIONS.ALARM_EDIT],
|
||||
|
||||
// 관리자 설정
|
||||
"/admin/company": [PERMISSIONS.COMPANY_VIEW],
|
||||
"/admin/company/profile": [PERMISSIONS.COMPANY_EDIT],
|
||||
"/admin/company/branches": [PERMISSIONS.BRANCH_VIEW],
|
||||
"/admin/company/billing": [PERMISSIONS.COMPANY_VIEW],
|
||||
|
||||
// 사용자 관리
|
||||
"/admin/user": [PERMISSIONS.USER_VIEW],
|
||||
"/admin/user/departments": [PERMISSIONS.DEPARTMENT_VIEW],
|
||||
"/admin/user/roles": [PERMISSIONS.USER_VIEW],
|
||||
"/admin/user/accounts": [PERMISSIONS.USER_VIEW],
|
||||
"/admin/user/create": [PERMISSIONS.USER_CREATE],
|
||||
"/admin/user/edit": [PERMISSIONS.USER_EDIT],
|
||||
|
||||
// 시스템 설정
|
||||
"/admin/system": [PERMISSIONS.SETTINGS_VIEW],
|
||||
"/admin/system/general": [PERMISSIONS.SETTINGS_EDIT],
|
||||
"/admin/system/integration": [PERMISSIONS.SETTINGS_EDIT],
|
||||
"/admin/system/backup": [PERMISSIONS.SETTINGS_EDIT],
|
||||
};
|
||||
|
||||
// 역할별 기본 권한 정의
|
||||
export const ROLE_PERMISSIONS: Record<string, string[]> = {
|
||||
super_admin: Object.values(PERMISSIONS),
|
||||
|
||||
company_admin: [
|
||||
PERMISSIONS.COMPANY_VIEW,
|
||||
PERMISSIONS.COMPANY_EDIT,
|
||||
PERMISSIONS.BRANCH_VIEW,
|
||||
PERMISSIONS.BRANCH_CREATE,
|
||||
PERMISSIONS.BRANCH_EDIT,
|
||||
PERMISSIONS.USER_VIEW,
|
||||
PERMISSIONS.USER_CREATE,
|
||||
PERMISSIONS.USER_EDIT,
|
||||
PERMISSIONS.DEPARTMENT_VIEW,
|
||||
PERMISSIONS.DEPARTMENT_CREATE,
|
||||
PERMISSIONS.DEPARTMENT_EDIT,
|
||||
PERMISSIONS.EQUIPMENT_VIEW,
|
||||
PERMISSIONS.EQUIPMENT_CREATE,
|
||||
PERMISSIONS.EQUIPMENT_EDIT,
|
||||
PERMISSIONS.ENERGY_VIEW,
|
||||
PERMISSIONS.ENERGY_ANALYZE,
|
||||
PERMISSIONS.ALARM_VIEW,
|
||||
PERMISSIONS.ALARM_CREATE,
|
||||
PERMISSIONS.ALARM_EDIT,
|
||||
PERMISSIONS.REPORT_VIEW,
|
||||
PERMISSIONS.REPORT_CREATE,
|
||||
PERMISSIONS.SETTINGS_VIEW,
|
||||
PERMISSIONS.SETTINGS_EDIT,
|
||||
],
|
||||
|
||||
branch_admin: [
|
||||
PERMISSIONS.BRANCH_VIEW,
|
||||
PERMISSIONS.USER_VIEW,
|
||||
PERMISSIONS.USER_CREATE,
|
||||
PERMISSIONS.EQUIPMENT_VIEW,
|
||||
PERMISSIONS.EQUIPMENT_CREATE,
|
||||
PERMISSIONS.ENERGY_VIEW,
|
||||
PERMISSIONS.ENERGY_ANALYZE,
|
||||
PERMISSIONS.ALARM_VIEW,
|
||||
PERMISSIONS.ALARM_CREATE,
|
||||
PERMISSIONS.REPORT_VIEW,
|
||||
PERMISSIONS.REPORT_CREATE,
|
||||
],
|
||||
|
||||
user: [
|
||||
PERMISSIONS.ENERGY_VIEW,
|
||||
PERMISSIONS.EQUIPMENT_VIEW,
|
||||
PERMISSIONS.ALARM_VIEW,
|
||||
PERMISSIONS.REPORT_VIEW,
|
||||
],
|
||||
};
|
||||
|
||||
// 권한 그룹 정의
|
||||
export const PERMISSION_GROUPS = {
|
||||
COMPANY_MANAGEMENT: [
|
||||
PERMISSIONS.COMPANY_VIEW,
|
||||
PERMISSIONS.COMPANY_EDIT,
|
||||
PERMISSIONS.COMPANY_DELETE,
|
||||
],
|
||||
|
||||
BRANCH_MANAGEMENT: [
|
||||
PERMISSIONS.BRANCH_VIEW,
|
||||
PERMISSIONS.BRANCH_CREATE,
|
||||
PERMISSIONS.BRANCH_EDIT,
|
||||
PERMISSIONS.BRANCH_DELETE,
|
||||
],
|
||||
|
||||
USER_MANAGEMENT: [
|
||||
PERMISSIONS.USER_VIEW,
|
||||
PERMISSIONS.USER_CREATE,
|
||||
PERMISSIONS.USER_EDIT,
|
||||
PERMISSIONS.USER_DELETE,
|
||||
],
|
||||
|
||||
EQUIPMENT_MANAGEMENT: [
|
||||
PERMISSIONS.EQUIPMENT_VIEW,
|
||||
PERMISSIONS.EQUIPMENT_CREATE,
|
||||
PERMISSIONS.EQUIPMENT_EDIT,
|
||||
PERMISSIONS.EQUIPMENT_DELETE,
|
||||
],
|
||||
|
||||
ENERGY_MONITORING: [PERMISSIONS.ENERGY_VIEW, PERMISSIONS.ENERGY_ANALYZE],
|
||||
|
||||
ALARM_MANAGEMENT: [
|
||||
PERMISSIONS.ALARM_VIEW,
|
||||
PERMISSIONS.ALARM_CREATE,
|
||||
PERMISSIONS.ALARM_EDIT,
|
||||
PERMISSIONS.ALARM_DELETE,
|
||||
],
|
||||
|
||||
REPORT_MANAGEMENT: [
|
||||
PERMISSIONS.REPORT_VIEW,
|
||||
PERMISSIONS.REPORT_CREATE,
|
||||
PERMISSIONS.REPORT_EDIT,
|
||||
PERMISSIONS.REPORT_DELETE,
|
||||
],
|
||||
} as const;
|
BIN
fems-mqtt/data/mosquitto.db
Normal file
BIN
fems-mqtt/data/mosquitto.db
Normal file
Binary file not shown.
2
fems-mqtt/data/passwd
Normal file
2
fems-mqtt/data/passwd
Normal file
@ -0,0 +1,2 @@
|
||||
fems:$7$101$p+0HKWVdeWzlO1o4$+GB5GrYz2g6TO75UHWzMDZH+eC8w/ZA4u3qk/0tMBoeSVnqTaInIdANM7trDQsEnT+G2wOr9G6ND+5YOySqxYQ==
|
||||
nodered_user:$7$101$bnRKi1qgGP06mJIZ$ksMvwVPG9Dp7+gWHKZnEXkgTV1W+Md9HHuOKSh4yFylwyZ2yEsRYOb/7oQ58Xxeu1YZNNrICiRCjnb9iDz0dpQ==
|
@ -16152,3 +16152,106 @@ To fix this, use `chmod 0700 /mosquitto/config/passwd`.
|
||||
1732490536: New connection from ::1:43836 on port 1883.
|
||||
1732490536: New client connected from ::1:43836 as auto-7B9071EC-9348-5AC2-2FE5-3F75319EAB71 (p2, c1, k60, u'fems').
|
||||
1732490536: Client auto-7B9071EC-9348-5AC2-2FE5-3F75319EAB71 closed its connection.
|
||||
1732490687: mosquitto version 2.0.20 starting
|
||||
1732490687: Config loaded from /mosquitto/config/mosquitto.conf.
|
||||
1732490687: Opening ipv4 listen socket on port 1883.
|
||||
1732490687: Opening ipv6 listen socket on port 1883.
|
||||
1732490687: mosquitto version 2.0.20 running
|
||||
1732490691: New connection from 172.19.0.9:33118 on port 1883.
|
||||
1732490691: New client connected from 172.19.0.9:33118 as fems_realtime_40 (p2, c1, k60, u'fems').
|
||||
1732490718: New connection from ::1:54086 on port 1883.
|
||||
1732490718: New client connected from ::1:54086 as auto-2D4F3C8B-9D04-17FC-D813-CB77A364BAE6 (p2, c1, k60, u'fems').
|
||||
1732490718: Client auto-2D4F3C8B-9D04-17FC-D813-CB77A364BAE6 closed its connection.
|
||||
1732490748: New connection from ::1:55062 on port 1883.
|
||||
1732490748: New client connected from ::1:55062 as auto-92F8F9BC-0250-47AB-F726-9AC0F1894772 (p2, c1, k60, u'fems').
|
||||
1732490748: Client auto-92F8F9BC-0250-47AB-F726-9AC0F1894772 closed its connection.
|
||||
1732490778: New connection from ::1:51410 on port 1883.
|
||||
1732490778: New client connected from ::1:51410 as auto-73A6A1E9-3235-19AB-1C6A-78810845C0EF (p2, c1, k60, u'fems').
|
||||
1732490778: Client auto-73A6A1E9-3235-19AB-1C6A-78810845C0EF closed its connection.
|
||||
1732490808: New connection from ::1:60058 on port 1883.
|
||||
1732490808: New client connected from ::1:60058 as auto-0D81837A-5F32-0F2A-5A84-F1CD500A34BB (p2, c1, k60, u'fems').
|
||||
1732490808: Client auto-0D81837A-5F32-0F2A-5A84-F1CD500A34BB closed its connection.
|
||||
1732490838: New connection from ::1:40688 on port 1883.
|
||||
1732490838: New client connected from ::1:40688 as auto-C92A19DE-7AFF-91B8-D9B7-E783E566B0AE (p2, c1, k60, u'fems').
|
||||
1732490838: Client auto-C92A19DE-7AFF-91B8-D9B7-E783E566B0AE closed its connection.
|
||||
1732490868: New connection from ::1:51326 on port 1883.
|
||||
1732490868: New client connected from ::1:51326 as auto-77597FD6-78CB-5036-3503-424EC4E59336 (p2, c1, k60, u'fems').
|
||||
1732490868: Client auto-77597FD6-78CB-5036-3503-424EC4E59336 closed its connection.
|
||||
1732490898: New connection from ::1:36716 on port 1883.
|
||||
1732490898: New client connected from ::1:36716 as auto-71130DEF-B28B-83D2-7860-DB3A1ED0BBF5 (p2, c1, k60, u'fems').
|
||||
1732490898: Client auto-71130DEF-B28B-83D2-7860-DB3A1ED0BBF5 closed its connection.
|
||||
1732490928: New connection from ::1:46640 on port 1883.
|
||||
1732490928: New client connected from ::1:46640 as auto-ABA29341-7728-9CA0-CC93-0B941290691D (p2, c1, k60, u'fems').
|
||||
1732490928: Client auto-ABA29341-7728-9CA0-CC93-0B941290691D closed its connection.
|
||||
1732490958: New connection from ::1:42752 on port 1883.
|
||||
1732490958: New client connected from ::1:42752 as auto-243B1078-D0D2-ED05-A6C8-F0BF776AEB6B (p2, c1, k60, u'fems').
|
||||
1732490959: Client auto-243B1078-D0D2-ED05-A6C8-F0BF776AEB6B closed its connection.
|
||||
1732490989: New connection from ::1:41906 on port 1883.
|
||||
1732490989: New client connected from ::1:41906 as auto-9C33A78D-8294-B6C1-58C3-FF516DD1E0B8 (p2, c1, k60, u'fems').
|
||||
1732490989: Client auto-9C33A78D-8294-B6C1-58C3-FF516DD1E0B8 closed its connection.
|
||||
1732491019: New connection from ::1:41178 on port 1883.
|
||||
1732491019: New client connected from ::1:41178 as auto-A139E080-C259-3D39-0329-7E7A1573E190 (p2, c1, k60, u'fems').
|
||||
1732491019: Client auto-A139E080-C259-3D39-0329-7E7A1573E190 closed its connection.
|
||||
1732491049: New connection from ::1:38994 on port 1883.
|
||||
1732491049: New client connected from ::1:38994 as auto-AF07BC5F-6663-3268-0FA1-3DE70038B9B8 (p2, c1, k60, u'fems').
|
||||
1732491049: Client auto-AF07BC5F-6663-3268-0FA1-3DE70038B9B8 closed its connection.
|
||||
1732491079: New connection from ::1:48114 on port 1883.
|
||||
1732491079: New client connected from ::1:48114 as auto-7D97DF2B-7E14-B971-9639-EFA16634D860 (p2, c1, k60, u'fems').
|
||||
1732491079: Client auto-7D97DF2B-7E14-B971-9639-EFA16634D860 closed its connection.
|
||||
1732491109: New connection from ::1:58464 on port 1883.
|
||||
1732491109: New client connected from ::1:58464 as auto-8ADAE7A2-8E93-8DA1-758C-A3F3AE0D4764 (p2, c1, k60, u'fems').
|
||||
1732491109: Client auto-8ADAE7A2-8E93-8DA1-758C-A3F3AE0D4764 closed its connection.
|
||||
1732491139: New connection from ::1:36580 on port 1883.
|
||||
1732491139: New client connected from ::1:36580 as auto-D058BA2D-FDB5-448B-BF4F-3A246A151455 (p2, c1, k60, u'fems').
|
||||
1732491139: Client auto-D058BA2D-FDB5-448B-BF4F-3A246A151455 closed its connection.
|
||||
1732491169: New connection from ::1:36214 on port 1883.
|
||||
1732491169: New client connected from ::1:36214 as auto-7E3A3113-C7D5-E795-8321-61B07DF68BBD (p2, c1, k60, u'fems').
|
||||
1732491169: Client auto-7E3A3113-C7D5-E795-8321-61B07DF68BBD closed its connection.
|
||||
1732491199: New connection from ::1:50750 on port 1883.
|
||||
1732491199: New client connected from ::1:50750 as auto-154D1239-5A81-35AB-1A45-140DC068F894 (p2, c1, k60, u'fems').
|
||||
1732491199: Client auto-154D1239-5A81-35AB-1A45-140DC068F894 closed its connection.
|
||||
1732491229: New connection from ::1:60768 on port 1883.
|
||||
1732491229: New client connected from ::1:60768 as auto-278B5CC2-EE66-DDDC-FDFD-0328223CD5F5 (p2, c1, k60, u'fems').
|
||||
1732491229: Client auto-278B5CC2-EE66-DDDC-FDFD-0328223CD5F5 closed its connection.
|
||||
1732491259: New connection from ::1:44754 on port 1883.
|
||||
1732491259: New client connected from ::1:44754 as auto-7E2B7353-2DA6-5780-6E11-4D95D3FA7C1D (p2, c1, k60, u'fems').
|
||||
1732491259: Client auto-7E2B7353-2DA6-5780-6E11-4D95D3FA7C1D closed its connection.
|
||||
1732491289: New connection from ::1:33370 on port 1883.
|
||||
1732491289: New client connected from ::1:33370 as auto-4E6B0FAD-1679-EC09-5B7D-7D78E9239449 (p2, c1, k60, u'fems').
|
||||
1732491289: Client auto-4E6B0FAD-1679-EC09-5B7D-7D78E9239449 closed its connection.
|
||||
1732491319: New connection from ::1:43742 on port 1883.
|
||||
1732491319: New client connected from ::1:43742 as auto-4962452D-D915-2E77-3F10-B4210A376198 (p2, c1, k60, u'fems').
|
||||
1732491319: Client auto-4962452D-D915-2E77-3F10-B4210A376198 closed its connection.
|
||||
1732491349: New connection from ::1:38400 on port 1883.
|
||||
1732491349: New client connected from ::1:38400 as auto-E64FFAD5-8EC3-AB42-32AC-9B47A0E869DA (p2, c1, k60, u'fems').
|
||||
1732491350: Client auto-E64FFAD5-8EC3-AB42-32AC-9B47A0E869DA closed its connection.
|
||||
1732491380: New connection from ::1:50554 on port 1883.
|
||||
1732491380: New client connected from ::1:50554 as auto-49A2BA59-20A9-86EC-738E-6C0747EACBC5 (p2, c1, k60, u'fems').
|
||||
1732491380: Client auto-49A2BA59-20A9-86EC-738E-6C0747EACBC5 closed its connection.
|
||||
1732491410: New connection from ::1:51472 on port 1883.
|
||||
1732491410: New client connected from ::1:51472 as auto-926B3BC4-A256-C884-31B3-B769F5D556A5 (p2, c1, k60, u'fems').
|
||||
1732491410: Client auto-926B3BC4-A256-C884-31B3-B769F5D556A5 closed its connection.
|
||||
1732491440: New connection from ::1:38310 on port 1883.
|
||||
1732491440: New client connected from ::1:38310 as auto-008FD4ED-5203-D152-D76E-2F5D9F8DD0A9 (p2, c1, k60, u'fems').
|
||||
1732491440: Client auto-008FD4ED-5203-D152-D76E-2F5D9F8DD0A9 closed its connection.
|
||||
1732491470: New connection from ::1:45430 on port 1883.
|
||||
1732491470: New client connected from ::1:45430 as auto-460F179A-BA65-9CAB-D343-D578EDC0E52A (p2, c1, k60, u'fems').
|
||||
1732491470: Client auto-460F179A-BA65-9CAB-D343-D578EDC0E52A closed its connection.
|
||||
1732491500: New connection from ::1:35036 on port 1883.
|
||||
1732491500: New client connected from ::1:35036 as auto-73657D0E-57B0-E4B4-203D-695B9272A1D2 (p2, c1, k60, u'fems').
|
||||
1732491500: Client auto-73657D0E-57B0-E4B4-203D-695B9272A1D2 closed its connection.
|
||||
1732491530: New connection from ::1:41792 on port 1883.
|
||||
1732491530: New client connected from ::1:41792 as auto-D9A66FCF-9FA2-681C-6219-94E21F9ACC56 (p2, c1, k60, u'fems').
|
||||
1732491530: Client auto-D9A66FCF-9FA2-681C-6219-94E21F9ACC56 closed its connection.
|
||||
1732491560: New connection from ::1:38248 on port 1883.
|
||||
1732491560: New client connected from ::1:38248 as auto-94A398BB-6697-A0FE-51D2-B03938E2A628 (p2, c1, k60, u'fems').
|
||||
1732491560: Client auto-94A398BB-6697-A0FE-51D2-B03938E2A628 closed its connection.
|
||||
1732491590: New connection from ::1:55668 on port 1883.
|
||||
1732491590: New client connected from ::1:55668 as auto-A7E0C188-D363-E61F-6705-41E2F1CF00FC (p2, c1, k60, u'fems').
|
||||
1732491590: Client auto-A7E0C188-D363-E61F-6705-41E2F1CF00FC closed its connection.
|
||||
1732491620: New connection from ::1:41604 on port 1883.
|
||||
1732491620: New client connected from ::1:41604 as auto-EE19F34E-4E04-1D13-CE67-A1FFBA9612D4 (p2, c1, k60, u'fems').
|
||||
1732491620: Client auto-EE19F34E-4E04-1D13-CE67-A1FFBA9612D4 closed its connection.
|
||||
1732491650: New connection from ::1:55334 on port 1883.
|
||||
1732491650: New client connected from ::1:55334 as auto-698C8684-502F-6421-8FBE-C6C6DFC9CBB0 (p2, c1, k60, u'fems').
|
||||
1732491650: Client auto-698C8684-502F-6421-8FBE-C6C6DFC9CBB0 closed its connection.
|
||||
|
45
fems-realtime-api/src/config/config.js
Normal file
45
fems-realtime-api/src/config/config.js
Normal file
@ -0,0 +1,45 @@
|
||||
// src/config/config.js
|
||||
require("dotenv").config({
|
||||
path: `.env.${process.env.NODE_ENV || "development"}`,
|
||||
});
|
||||
|
||||
const config = {
|
||||
port: process.env.REALTIME_API_PORT || 3004,
|
||||
|
||||
timescaledb: {
|
||||
host: process.env.TIMESCALEDB_HOST || "localhost",
|
||||
port: parseInt(process.env.TIMESCALEDB_PORT) || 5433,
|
||||
database: process.env.TIMESCALEDB_DB,
|
||||
user: process.env.TIMESCALEDB_USER,
|
||||
password: process.env.TIMESCALEDB_PASSWORD,
|
||||
},
|
||||
|
||||
redis: {
|
||||
host: process.env.REDIS_HOST || "localhost",
|
||||
port: parseInt(process.env.REDIS_PORT) || 6379,
|
||||
password: process.env.REDIS_PASSWORD,
|
||||
db: parseInt(process.env.REDIS_DB) || 0,
|
||||
retryStrategy: (times) => {
|
||||
return Math.min(times * 50, 2000);
|
||||
},
|
||||
},
|
||||
|
||||
mqtt: {
|
||||
url: process.env.MQTT_BROKER_URL || "mqtt://localhost:1883",
|
||||
options: {
|
||||
username: process.env.MQTT_USERNAME,
|
||||
password: process.env.MQTT_PASSWORD,
|
||||
clientId: `fems_realtime_${process.pid}`,
|
||||
clean: true,
|
||||
reconnectPeriod: 5000,
|
||||
connectTimeout: 30000,
|
||||
},
|
||||
},
|
||||
|
||||
mainBackend: {
|
||||
url: process.env.NEXT_PUBLIC_API_URL || "http://localhost:3000",
|
||||
adminApiKey: process.env.ADMIN_API_KEY,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = config;
|
55
fems-realtime-api/src/config/database.js
Normal file
55
fems-realtime-api/src/config/database.js
Normal file
@ -0,0 +1,55 @@
|
||||
// src/config/database.js
|
||||
const logger = require("./logger");
|
||||
|
||||
module.exports = {
|
||||
development: {
|
||||
host: process.env.POSTGRES_HOST || "fems-timescaledb",
|
||||
port: parseInt(process.env.DB_PORT) || 5442,
|
||||
database: process.env.POSTGRES_DB || "fems_timeseries",
|
||||
username: process.env.POSTGRES_USER || "fems_user",
|
||||
password: process.env.POSTGRES_PASSWORD,
|
||||
dialect: "postgres",
|
||||
logging: (msg) => logger.debug(msg),
|
||||
dialectOptions: {
|
||||
ssl: false,
|
||||
},
|
||||
define: {
|
||||
timestamps: true,
|
||||
underscored: true,
|
||||
},
|
||||
pool: {
|
||||
max: 5,
|
||||
min: 0,
|
||||
acquire: 60000,
|
||||
idle: 10000,
|
||||
},
|
||||
retry: {
|
||||
max: 5,
|
||||
},
|
||||
},
|
||||
production: {
|
||||
host: process.env.POSTGRES_HOST,
|
||||
port: parseInt(process.env.DB_PORT),
|
||||
database: process.env.POSTGRES_DB,
|
||||
username: process.env.POSTGRES_USER,
|
||||
password: process.env.POSTGRES_PASSWORD,
|
||||
dialect: "postgres",
|
||||
logging: false,
|
||||
dialectOptions: {
|
||||
ssl: process.env.DB_SSL === "true",
|
||||
},
|
||||
define: {
|
||||
timestamps: true,
|
||||
underscored: true,
|
||||
},
|
||||
pool: {
|
||||
max: 10,
|
||||
min: 2,
|
||||
acquire: 60000,
|
||||
idle: 10000,
|
||||
},
|
||||
retry: {
|
||||
max: 5,
|
||||
},
|
||||
},
|
||||
};
|
190
fems-realtime-api/src/config/logger.js
Normal file
190
fems-realtime-api/src/config/logger.js
Normal file
@ -0,0 +1,190 @@
|
||||
// src/config/logger.js
|
||||
const winston = require("winston");
|
||||
require("winston-daily-rotate-file");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
class Logger {
|
||||
constructor() {
|
||||
if (Logger.instance) {
|
||||
return Logger.instance;
|
||||
}
|
||||
|
||||
this.initializeDirs();
|
||||
this.createLogger();
|
||||
Logger.instance = this;
|
||||
return this;
|
||||
}
|
||||
|
||||
initializeDirs() {
|
||||
// 로그 디렉토리 설정
|
||||
this.logDir = path.join(__dirname, "../../logs");
|
||||
this.errorLogDir = path.join(this.logDir, "error");
|
||||
this.infoLogDir = path.join(this.logDir, "info");
|
||||
this.systemLogDir = path.join(this.logDir, "system");
|
||||
|
||||
// 로그 디렉토리 생성
|
||||
[this.errorLogDir, this.infoLogDir, this.systemLogDir].forEach((dir) => {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
createLogger() {
|
||||
// 공통 로그 포맷
|
||||
const commonLogFormat = winston.format.combine(
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.splat(),
|
||||
winston.format.json()
|
||||
);
|
||||
|
||||
// 콘솔 출력용 포맷
|
||||
const consoleFormat = winston.format.combine(
|
||||
winston.format.colorize(),
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
||||
winston.format.printf(
|
||||
({ level, message, timestamp, stack, ...metadata }) => {
|
||||
let msg = `${timestamp} [${level}]: ${message}`;
|
||||
if (stack) msg += `\n${stack}`;
|
||||
if (Object.keys(metadata).length > 0) {
|
||||
msg += `\n${JSON.stringify(metadata, null, 2)}`;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// 트랜스포트 설정
|
||||
this.transports = {
|
||||
error: new winston.transports.DailyRotateFile({
|
||||
level: "error",
|
||||
dirname: this.errorLogDir,
|
||||
filename: "error-%DATE%.log",
|
||||
datePattern: "YYYY-MM-DD",
|
||||
zippedArchive: true,
|
||||
maxSize: "20m",
|
||||
maxFiles: "14d",
|
||||
format: commonLogFormat,
|
||||
}),
|
||||
info: new winston.transports.DailyRotateFile({
|
||||
level: "info",
|
||||
dirname: this.infoLogDir,
|
||||
filename: "info-%DATE%.log",
|
||||
datePattern: "YYYY-MM-DD",
|
||||
zippedArchive: true,
|
||||
maxSize: "20m",
|
||||
maxFiles: "14d",
|
||||
format: commonLogFormat,
|
||||
}),
|
||||
system: new winston.transports.DailyRotateFile({
|
||||
dirname: this.systemLogDir,
|
||||
filename: "system-%DATE%.log",
|
||||
datePattern: "YYYY-MM-DD",
|
||||
zippedArchive: true,
|
||||
maxSize: "20m",
|
||||
maxFiles: "14d",
|
||||
format: commonLogFormat,
|
||||
}),
|
||||
};
|
||||
|
||||
// Winston 로거 생성
|
||||
this.logger = winston.createLogger({
|
||||
level: process.env.NODE_ENV === "production" ? "info" : "debug",
|
||||
defaultMeta: {
|
||||
service: "fems-edge",
|
||||
environment: process.env.NODE_ENV || "development",
|
||||
},
|
||||
transports: Object.values(this.transports),
|
||||
// exitOnError: false를 추가하여 에러 발생 시 프로세스가 종료되지 않도록 함
|
||||
exitOnError: false,
|
||||
});
|
||||
|
||||
// 개발 환경에서만 콘솔 출력 추가
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
this.logger.add(
|
||||
new winston.transports.Console({
|
||||
level: "debug",
|
||||
format: consoleFormat,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// 로그 회전 이벤트 핸들러
|
||||
this.setupRotateHandlers();
|
||||
}
|
||||
|
||||
setupRotateHandlers() {
|
||||
this.transports.error.on("rotate", (oldFilename, newFilename) => {
|
||||
this.logger.info("Error log rotated", { oldFilename, newFilename });
|
||||
});
|
||||
|
||||
this.transports.info.on("rotate", (oldFilename, newFilename) => {
|
||||
this.logger.info("Info log rotated", { oldFilename, newFilename });
|
||||
});
|
||||
}
|
||||
|
||||
// 유틸리티 메서드들
|
||||
logHttpRequest(req) {
|
||||
this.logger.info("HTTP Request", {
|
||||
method: req.method,
|
||||
url: req.originalUrl,
|
||||
params: req.params,
|
||||
query: req.query,
|
||||
body: req.body,
|
||||
ip: req.ip,
|
||||
userAgent: req.get("user-agent"),
|
||||
});
|
||||
}
|
||||
|
||||
logMqttMessage(topic, payload) {
|
||||
this.logger.debug("MQTT Message", {
|
||||
topic,
|
||||
payload,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
logPerformance(operation, duration) {
|
||||
this.logger.info("Performance Metric", {
|
||||
operation,
|
||||
duration,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
logQuery(query, duration) {
|
||||
this.logger.debug("Database Query", {
|
||||
query: typeof query === "string" ? query.trim() : query,
|
||||
duration: `${duration}ms`,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// Express 미들웨어용 스트림
|
||||
get stream() {
|
||||
return {
|
||||
write: (message) => {
|
||||
this.logger.info(message.trim());
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 싱글톤 인스턴스 생성
|
||||
const loggerInstance = new Logger();
|
||||
|
||||
// 편의를 위한 메서드 바인딩
|
||||
module.exports = {
|
||||
error: loggerInstance.logger.error.bind(loggerInstance.logger),
|
||||
warn: loggerInstance.logger.warn.bind(loggerInstance.logger),
|
||||
info: loggerInstance.logger.info.bind(loggerInstance.logger),
|
||||
debug: loggerInstance.logger.debug.bind(loggerInstance.logger),
|
||||
logHttpRequest: loggerInstance.logHttpRequest.bind(loggerInstance),
|
||||
logMqttMessage: loggerInstance.logMqttMessage.bind(loggerInstance),
|
||||
logPerformance: loggerInstance.logPerformance.bind(loggerInstance),
|
||||
logQuery: loggerInstance.logQuery.bind(loggerInstance),
|
||||
stream: loggerInstance.stream,
|
||||
logger: loggerInstance.logger,
|
||||
};
|
17
fems-timescaledb/init-scripts/00-init-user.sh
Executable file
17
fems-timescaledb/init-scripts/00-init-user.sh
Executable file
@ -0,0 +1,17 @@
|
||||
# config/postgres/init-scripts/00-init-user.sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
-- TimescaleDB 확장 활성화
|
||||
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
|
||||
|
||||
-- 사용자 권한 설정
|
||||
ALTER USER $POSTGRES_USER WITH PASSWORD '$POSTGRES_PASSWORD';
|
||||
ALTER USER $POSTGRES_USER SET client_encoding TO 'utf8';
|
||||
ALTER USER $POSTGRES_USER SET timezone TO 'UTC';
|
||||
|
||||
-- 데이터베이스 설정
|
||||
ALTER DATABASE $POSTGRES_DB SET timezone TO 'UTC';
|
||||
EOSQL
|
||||
|
Loading…
Reference in New Issue
Block a user