Update
This commit is contained in:
parent
0a0dd559f0
commit
cbc8397ea8
|
|
@ -23,3 +23,5 @@ yarn-error.log
|
|||
|
||||
# Platform specific
|
||||
.DS_Store
|
||||
|
||||
storage/system_logs
|
||||
|
|
|
|||
|
|
@ -4,9 +4,20 @@ import User from '../models/user.js'
|
|||
export default class AuthController {
|
||||
// Đăng ký
|
||||
async register({ request, response }: HttpContext) {
|
||||
const data = request.only(['email', 'password', 'full_name'])
|
||||
const user = await User.create(data)
|
||||
return response.json({ message: 'User created', user })
|
||||
try {
|
||||
const data = request.only(['email', 'password', 'full_name'])
|
||||
|
||||
const user = await User.query().where('email', data.email).first()
|
||||
|
||||
if (user) {
|
||||
return response.status(401).json({ status: false, message: 'Email is exist' })
|
||||
}
|
||||
|
||||
const newUser = await User.create(data)
|
||||
return response.json({ status: true, message: 'User created', user: newUser })
|
||||
} catch (error) {
|
||||
return response.status(401).json({ status: false, message: 'Invalid credentials' })
|
||||
}
|
||||
}
|
||||
|
||||
// Đăng nhập
|
||||
|
|
@ -24,11 +35,9 @@ export default class AuthController {
|
|||
return response.status(401).json({ message: 'Invalid email or password' })
|
||||
}
|
||||
|
||||
// ✅ Nếu dùng token thủ công:
|
||||
const token = Math.random().toString(36).substring(2) // hoặc JWT nếu bạn cài auth
|
||||
return response.json({
|
||||
message: 'Login successful',
|
||||
user: { id: user.id, email: user.email, token },
|
||||
user: { id: user.id, email: user.email, fullName: user.fullName },
|
||||
})
|
||||
} catch {
|
||||
return response.status(401).json({ message: 'Invalid credentials' })
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import Scenario from '#models/scenario'
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
import { searchRequest } from '../utils/hasPaginationRequest.js'
|
||||
import db from '@adonisjs/lucid/services/db'
|
||||
import UserScenarios from '#models/user_scenario'
|
||||
|
||||
export default class ScenariosController {
|
||||
/**
|
||||
|
|
@ -36,7 +34,6 @@ export default class ScenariosController {
|
|||
async create({ request, response, auth }: HttpContext) {
|
||||
try {
|
||||
const payload = await request.all()
|
||||
|
||||
const trx = await db.transaction()
|
||||
try {
|
||||
const scenario = await Scenario.create(
|
||||
|
|
@ -44,7 +41,7 @@ export default class ScenariosController {
|
|||
title: payload.title.trim(),
|
||||
body: JSON.stringify(payload.body),
|
||||
timeout: payload.timeout,
|
||||
isReboot: payload.is_reboot,
|
||||
isReboot: payload.isReboot,
|
||||
},
|
||||
{ client: trx }
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import net from 'node:net'
|
||||
import { cleanData, sleep } from '../ultils/helper.js'
|
||||
import { appendLog, cleanData, sleep } from '../ultils/helper.js'
|
||||
import Scenario from '#models/scenario'
|
||||
|
||||
interface LineConfig {
|
||||
|
|
@ -11,6 +11,14 @@ interface LineConfig {
|
|||
apcName?: string
|
||||
output: string
|
||||
status: string
|
||||
openCLI: boolean
|
||||
userEmailOpenCLI: string
|
||||
userOpenCLI: string
|
||||
}
|
||||
|
||||
interface User {
|
||||
userEmail: string
|
||||
userName: string
|
||||
}
|
||||
|
||||
export default class LineConnection {
|
||||
|
|
@ -77,6 +85,7 @@ export default class LineConnection {
|
|||
lineId: id,
|
||||
data: message,
|
||||
})
|
||||
appendLog(cleanData(message), this.config.stationId, this.config.id)
|
||||
})
|
||||
|
||||
this.client.on('error', (err) => {
|
||||
|
|
@ -149,6 +158,11 @@ export default class LineConnection {
|
|||
}
|
||||
|
||||
this.isRunningScript = true
|
||||
appendLog(
|
||||
`\n\n---start-scenarios---${Date.now()}---\n---scenario---${script?.title}---${Date.now()}---\n`,
|
||||
this.config.stationId,
|
||||
this.config.id
|
||||
)
|
||||
const steps = typeof script?.body === 'string' ? JSON.parse(script?.body) : []
|
||||
let stepIndex = 0
|
||||
|
||||
|
|
@ -156,6 +170,13 @@ export default class LineConnection {
|
|||
const timeoutTimer = setTimeout(() => {
|
||||
this.isRunningScript = false
|
||||
this.outputBuffer = ''
|
||||
this.config.output += 'Timeout run scenario'
|
||||
this.socketIO.emit('line_output', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
data: 'Timeout run scenario',
|
||||
})
|
||||
appendLog(`\n---end-scenarios---${Date.now()}---\n`, this.config.stationId, this.config.id)
|
||||
// reject(new Error('Script timeout'))
|
||||
}, script.timeout || 300000)
|
||||
|
||||
|
|
@ -164,11 +185,21 @@ export default class LineConnection {
|
|||
clearTimeout(timeoutTimer)
|
||||
this.isRunningScript = false
|
||||
this.outputBuffer = ''
|
||||
appendLog(
|
||||
`\n---end-scenarios---${Date.now()}---\n`,
|
||||
this.config.stationId,
|
||||
this.config.id
|
||||
)
|
||||
resolve(true)
|
||||
return
|
||||
}
|
||||
|
||||
const step = steps[index]
|
||||
appendLog(
|
||||
`\n---send-command---"${step?.send ?? ''}"---${Date.now()}---\n`,
|
||||
this.config.stationId,
|
||||
this.config.id
|
||||
)
|
||||
let repeatCount = Number(step.repeat) || 1
|
||||
const sendCommand = () => {
|
||||
if (repeatCount <= 0) {
|
||||
|
|
@ -203,4 +234,27 @@ export default class LineConnection {
|
|||
runStep(stepIndex)
|
||||
})
|
||||
}
|
||||
|
||||
userOpenCLI(user: User) {
|
||||
this.config.openCLI = true
|
||||
this.config.userEmailOpenCLI = user.userEmail
|
||||
this.config.userOpenCLI = user.userName
|
||||
this.socketIO.emit('user_open_cli', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
userEmailOpenCLI: user.userEmail,
|
||||
userOpenCLI: user.userName,
|
||||
})
|
||||
}
|
||||
|
||||
userCloseCLI() {
|
||||
this.config.openCLI = false
|
||||
this.config.userEmailOpenCLI = ''
|
||||
this.config.userOpenCLI = ''
|
||||
this.socketIO.emit('user_close_cli', {
|
||||
stationId: this.config.stationId,
|
||||
lineId: this.config.id,
|
||||
userEmailOpenCLI: '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
/**
|
||||
* Function to clean up unwanted characters from the output data.
|
||||
* @param {string} data - The raw data to be cleaned.
|
||||
|
|
@ -16,3 +19,20 @@ export const cleanData = (data: string) => {
|
|||
export function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
export function appendLog(output: string, stationId: number, lineId: number) {
|
||||
const date = new Date().toISOString().slice(0, 10).replace(/-/g, '') // YYYYMMDD
|
||||
const logDir = path.join('storage', 'system_logs')
|
||||
const logFile = path.join(logDir, `${date}-Station_${stationId}-Line_${lineId}.log`)
|
||||
|
||||
// Ensure folder exists
|
||||
if (!fs.existsSync(logDir)) {
|
||||
fs.mkdirSync(logDir, { recursive: true })
|
||||
}
|
||||
|
||||
fs.appendFile(logFile, output, (err) => {
|
||||
if (err) {
|
||||
console.error('❌ Failed to write log:', err.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default class extends BaseSchema {
|
|||
table.string('title').notNullable()
|
||||
table.text('body').notNullable()
|
||||
table.integer('timeout').notNullable()
|
||||
table.boolean('isReboot').defaultTo(false)
|
||||
table.boolean('is_reboot').defaultTo(false)
|
||||
table.timestamps()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ export class WebSocketIo {
|
|||
stationMap: Map<number, Station> = new Map()
|
||||
lineMap: Map<number, LineConnection> = new Map() // key = lineId
|
||||
lineConnecting: number[] = [] // key = lineId
|
||||
userConnecting: Map<number, { userId: number; userName: string }> = new Map()
|
||||
|
||||
constructor(protected app: ApplicationService) {}
|
||||
|
||||
|
|
@ -70,8 +71,14 @@ export class WebSocketIo {
|
|||
})
|
||||
|
||||
io.on('connection', (socket: CustomSocket) => {
|
||||
const { userId, userName } = socket.handshake.auth
|
||||
console.log('Socket connected:', socket.id)
|
||||
socket.connectionTime = new Date()
|
||||
this.userConnecting.set(userId, { userId, userName })
|
||||
|
||||
setTimeout(() => {
|
||||
io.emit('user_connecting', Array.from(this.userConnecting.values()))
|
||||
}, 200)
|
||||
|
||||
setTimeout(() => {
|
||||
io.to(socket.id).emit(
|
||||
|
|
@ -82,6 +89,10 @@ export class WebSocketIo {
|
|||
|
||||
socket.on('disconnect', () => {
|
||||
console.log(`FE disconnected: ${socket.id}`)
|
||||
this.userConnecting.delete(userId)
|
||||
setTimeout(() => {
|
||||
io.emit('user_connecting', Array.from(this.userConnecting.values()))
|
||||
}, 200)
|
||||
})
|
||||
|
||||
// FE gửi yêu cầu connect lines
|
||||
|
|
@ -94,8 +105,8 @@ export class WebSocketIo {
|
|||
const { lineIds, stationId, command } = data
|
||||
for (const lineId of lineIds) {
|
||||
const line = this.lineMap.get(lineId)
|
||||
if (line) {
|
||||
this.lineConnecting.filter((el) => el !== lineId)
|
||||
if (line && line.config.status === 'connected') {
|
||||
this.lineConnecting = this.lineConnecting.filter((el) => el !== lineId)
|
||||
this.setTimeoutConnect(lineId, line)
|
||||
line.writeCommand(command)
|
||||
} else {
|
||||
|
|
@ -107,7 +118,7 @@ export class WebSocketIo {
|
|||
await this.connectLine(io, [linesData], stationData)
|
||||
const lineReconnect = this.lineMap.get(lineId)
|
||||
if (lineReconnect) {
|
||||
this.lineConnecting.filter((el) => el !== lineId)
|
||||
this.lineConnecting = this.lineConnecting.filter((el) => el !== lineId)
|
||||
this.setTimeoutConnect(lineId, lineReconnect)
|
||||
lineReconnect.writeCommand(command)
|
||||
}
|
||||
|
|
@ -127,7 +138,7 @@ export class WebSocketIo {
|
|||
const lineId = data.id
|
||||
const scenario = data.scenario
|
||||
const line = this.lineMap.get(lineId)
|
||||
if (line) {
|
||||
if (line && line.config.status === 'connected') {
|
||||
this.setTimeoutConnect(
|
||||
lineId,
|
||||
line,
|
||||
|
|
@ -155,9 +166,44 @@ export class WebSocketIo {
|
|||
}
|
||||
})
|
||||
|
||||
// FE yêu cầu ngắt kết nối 1 station
|
||||
socket.on('disconnect_station', (stationId) => {
|
||||
this.disconnectStation(stationId)
|
||||
socket.on('open_cli', async (data) => {
|
||||
const { lineId, userEmail, userName: name, stationId } = data
|
||||
const line = this.lineMap.get(lineId)
|
||||
if (line) {
|
||||
line.userOpenCLI({ userEmail, userName: name })
|
||||
} else {
|
||||
if (this.lineConnecting.includes(lineId)) return
|
||||
const linesData = await Line.findBy('id', lineId)
|
||||
const stationData = await Station.findBy('id', stationId)
|
||||
if (linesData && stationData) {
|
||||
this.lineConnecting.push(lineId)
|
||||
await this.connectLine(io, [linesData], stationData)
|
||||
const lineReconnect = this.lineMap.get(lineId)
|
||||
if (lineReconnect) {
|
||||
lineReconnect.userOpenCLI({ userEmail, userName: name })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('close_cli', async (data) => {
|
||||
const { lineId, stationId } = data
|
||||
const line = this.lineMap.get(lineId)
|
||||
if (line) {
|
||||
line.userCloseCLI()
|
||||
} else {
|
||||
if (this.lineConnecting.includes(lineId)) return
|
||||
const linesData = await Line.findBy('id', lineId)
|
||||
const stationData = await Station.findBy('id', stationId)
|
||||
if (linesData && stationData) {
|
||||
this.lineConnecting.push(lineId)
|
||||
await this.connectLine(io, [linesData], stationData)
|
||||
const lineReconnect = this.lineMap.get(lineId)
|
||||
if (lineReconnect) {
|
||||
lineReconnect.userCloseCLI()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -182,6 +228,9 @@ export class WebSocketIo {
|
|||
apcName: line.apcName,
|
||||
output: '',
|
||||
status: '',
|
||||
openCLI: false,
|
||||
userEmailOpenCLI: '',
|
||||
userOpenCLI: '',
|
||||
},
|
||||
socket
|
||||
)
|
||||
|
|
@ -195,22 +244,6 @@ export class WebSocketIo {
|
|||
}
|
||||
}
|
||||
|
||||
private disconnectStation(stationId: number) {
|
||||
const station = this.stationMap.get(stationId)
|
||||
if (!station) return
|
||||
|
||||
for (const line of station.lines) {
|
||||
const conn = this.lineMap.get(line.id)
|
||||
if (conn) {
|
||||
conn.disconnect()
|
||||
this.lineMap.delete(line.id)
|
||||
}
|
||||
}
|
||||
|
||||
this.stationMap.delete(stationId)
|
||||
console.log(`🔻 Station ${station.name} disconnected`)
|
||||
}
|
||||
|
||||
private setTimeoutConnect = (lineId: number, lineConn: LineConnection, timeout = 120000) => {
|
||||
if (this.intervalMap[`${lineId}`]) {
|
||||
clearInterval(this.intervalMap[`${lineId}`])
|
||||
|
|
@ -218,7 +251,7 @@ export class WebSocketIo {
|
|||
}
|
||||
const interval = setInterval(() => {
|
||||
lineConn.disconnect()
|
||||
this.lineMap.delete(lineId)
|
||||
// this.lineMap.delete(lineId)
|
||||
if (this.intervalMap[`${lineId}`]) {
|
||||
clearInterval(this.intervalMap[`${lineId}`])
|
||||
delete this.intervalMap[`${lineId}`]
|
||||
|
|
|
|||
|
|
@ -67,5 +67,6 @@ router
|
|||
router
|
||||
.group(() => {
|
||||
router.post('/login', '#controllers/auth_controller.login')
|
||||
router.post('/register', '#controllers/auth_controller.register')
|
||||
})
|
||||
.prefix('api/auth')
|
||||
|
|
|
|||
Loading…
Reference in New Issue