diff --git a/.gitIgnore b/.gitIgnore
index e69de29..bb32ee7 100644
--- a/.gitIgnore
+++ b/.gitIgnore
@@ -0,0 +1,2 @@
+Model/.env
+.env
\ No newline at end of file
diff --git a/.idea/Managed-Server.iml b/.idea/Managed-Server.iml
index 5e764c4..d356d82 100644
--- a/.idea/Managed-Server.iml
+++ b/.idea/Managed-Server.iml
@@ -1,9 +1,17 @@
+
+
+
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..69a1ce5
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..0dbbef0
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..c5f4aea 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/Core/AgentManager.go b/Core/AgentManager.go
deleted file mode 100644
index 6101c34..0000000
--- a/Core/AgentManager.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package Core
-
-import "github.com/your/repo/Model"
-
-/*
- Agent Model = Managing + model
-*/
-
-type AgentManager struct {
-}
-
-func (self *AgentManager) createAgent(uuid string) error {
-
- return nil
-}
-
-/*
-agent 의 상태 Status 는 총 3가지로 나뉜다.
-
-Running : 동작중인 상태
-waiting : 대기중인 상태
-Stopping : 정지후 사라지기 전에 상태
-*/
-func (self *AgentManager) checkAgent(uuid string) bool {
-
- return false
-}
-
-func (self *AgentManager) updateAgentStatus(uuid string, status bool) bool {
- agtStat := &Model.NewAgentStatusDB()
- record := &Model.AgentStatusRecord{
- UUID: uuid,
- Status: status,
- }
- agtStat.UpdateRecord()
-}
-
-func (self *AgentManager) deleteAgent(uuid string) bool {
-
-}
diff --git a/Core/CommandDispatcher.go b/Core/CommandDispatcher.go
new file mode 100644
index 0000000..0da2d35
--- /dev/null
+++ b/Core/CommandDispatcher.go
@@ -0,0 +1,273 @@
+package Core
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/HTTPs-omma/HTTPsBAS-HSProtocol/HSProtocol"
+ "github.com/your/repo/Model"
+)
+
+// https://github.com/HTTPs-omma/HSProtocol
+type CommandDispatcher struct {
+}
+
+// Command 상수를 정의
+
+func (cd *CommandDispatcher) Action(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+ // hsMgr := HSProtocol.NewHSProtocolManager()
+
+ switch hs.Command {
+ case HSProtocol.UPDATE_AGENT_PROTOCOL:
+ return UPDATE_AGENT_PROTOCOL(hs)
+ case HSProtocol.UPDATE_AGENT_STATUS:
+ return UPDATE_AGENT_STATUS(hs)
+ case HSProtocol.SEND_AGENT_SYS_INFO:
+ return SEND_AGENT_SYS_INFO(hs)
+ case HSProtocol.ERROR_ACK:
+ break // 예약
+ case HSProtocol.SEND_AGENT_APP_INFO:
+ return SEND_AGENT_APP_INFO(hs)
+ case HSProtocol.FETCH_INSTRUCTION:
+ return FETCH_INSTRUCTION(hs)
+ case HSProtocol.SEND_PROCEDURE_LOG:
+ return SEND_PROCEDURE_LOG(hs)
+ }
+
+ return nil, fmt.Errorf("Invalid Command")
+}
+
+// Command: 1 (0b0000000001)
+func UPDATE_AGENT_PROTOCOL(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+ agsmd, err := Model.NewAgentStatusDB()
+ if err != nil {
+ return nil, err
+ }
+ rst, err := agsmd.ExistRecord()
+ if err != nil {
+ return nil, err
+ }
+ if rst {
+ return nil, fmt.Errorf("Agent Status DB : no Records")
+ }
+
+ records, err := agsmd.SelectAllRecords()
+ if err != nil {
+ return nil, err
+ }
+
+ hs_uuid := HSProtocol.ByteArrayToHexString(hs.UUID)
+
+ flag := false
+ for _, record := range records {
+ if record.UUID == hs_uuid {
+ flag = true
+ }
+ }
+
+ if flag == true {
+ agsmd.UpdateRecord(&Model.AgentStatusRecord{
+ UUID: hs_uuid,
+ Status: Model.BinaryToAgentStatus(hs.HealthStatus),
+ })
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+ } else if (flag == false) && (hs.HealthStatus == uint8(HSProtocol.WAIT)) {
+ agsmd.InsertRecord(&Model.AgentStatusRecord{
+ UUID: hs_uuid,
+ Status: Model.BinaryToAgentStatus(hs.HealthStatus),
+ })
+
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+ }
+
+ return nil, fmt.Errorf("incorrect AgentStatusRecords")
+}
+
+// Command: 2 (0b0000000010)
+func UPDATE_AGENT_STATUS(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+
+ // protocolID := binary.BigEndian.Uint32(hs.Data)
+ agsDb, err := Model.NewAgentStatusDB()
+ if err != nil {
+ return nil, err
+ }
+
+ agsDb.InsertRecord(&Model.AgentStatusRecord{
+ ID: 0,
+ UUID: HSProtocol.ByteArrayToHexString(hs.UUID),
+ Protocol: Model.BinaryToProtocol(hs.ProtocolID),
+ Status: Model.BinaryToAgentStatus(hs.HealthStatus),
+ })
+ err = agsDb.InsertRecord(&Model.AgentStatusRecord{})
+ if err != nil {
+ return nil, err
+ }
+
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+}
+
+// Command: 3 (0b0000000011)
+func SEND_AGENT_SYS_INFO(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+
+ sysDB, err := Model.NewSystemInfoDB()
+ if err != nil {
+ return nil, err
+ }
+ sysinfo := Model.DsystemInfoDB{}
+ err = json.Unmarshal(hs.Data, &sysinfo)
+ if err != nil {
+ return nil, err
+ }
+
+ err = sysDB.InsertRecord(&sysinfo)
+ if err != nil {
+ return nil, err
+ }
+
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+}
+
+// Command: 5 (0b0000000101)
+func SEND_AGENT_APP_INFO(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+
+ appDB, err := Model.NewApplicationDB()
+ if err != nil {
+ return nil, err
+ }
+ applist, err := appDB.FromJSON(hs.Data)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, Dapp := range applist {
+ err = appDB.InsertRecord(&Dapp)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+}
+
+// Command: 6 (0b0000000110)
+func FETCH_INSTRUCTION(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+ agentUuid := HSProtocol.ByteArrayToHexString(hs.UUID)
+ fmt.Println("agent uuid : " + agentUuid)
+ jobdb, err := Model.NewJobDB()
+ if err != nil {
+ return nil, err
+ }
+ job, err, exist := jobdb.PopbyAgentUUID(agentUuid)
+
+ if err != nil {
+ return nil, err
+ }
+
+ //fmt.Println("debug === : " + job.ProcedureID)
+ if exist == true { // job 이 있다면
+ cmdMgr, err := NewInstructionManager()
+ if err != nil {
+ return nil, err
+ }
+
+ cmdData, issuccess := cmdMgr.GetByID(job.ProcedureID) // 프로시저를 불러와야함.
+ if issuccess != true {
+ return nil, fmt.Errorf("job procedure not found")
+ }
+ bData, err := cmdData.ToBytes()
+ if err != nil {
+ return nil, err
+ }
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: bData,
+ }, nil
+ }
+
+ // false
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+
+}
+
+// Command: 7 (0b0000000111)
+func SEND_PROCEDURE_LOG(hs *HSProtocol.HS) (*HSProtocol.HS, error) {
+
+ //hs_uuid := HSProtocol.ByteArrayToHexString(hs.UUID)
+
+ logdb, err := Model.NewOperationLogDB()
+ if err != nil {
+ return nil, err
+ }
+ log := &Model.OperationLogDocument{}
+ err = json.Unmarshal(hs.Data, &log)
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = logdb.InsertDocument(log)
+ if err != nil {
+ return nil, err
+ }
+
+ return &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }, nil
+}
diff --git a/Core/InstructionManager.go b/Core/InstructionManager.go
new file mode 100644
index 0000000..5387195
--- /dev/null
+++ b/Core/InstructionManager.go
@@ -0,0 +1,143 @@
+package Core
+
+import (
+ "fmt"
+ "gopkg.in/yaml.v2"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+)
+
+/**
+ChatGpt 로 생성한 코드임
+*/
+
+// InstructionData는 주어진 YAML 데이터를 저장할 구조체입니다.
+type InstructionData struct {
+ ID string `yaml:"id"`
+ MITREID string `yaml:"MITRE_ID"`
+ Description string `yaml:"Description"`
+ Tool string `yaml:"tool"`
+ RequisiteCommand string `yaml:"requisite_command"`
+ Command string `yaml:"command"`
+ Cleanup string `yaml:"cleanup"`
+}
+
+// ToBytes는 InstructionData 구조체를 YAML 바이트 슬라이스로 변환하는 함수입니다.
+func (cd *InstructionData) ToBytes() ([]byte, error) {
+ // YAML로 직렬화
+ data, err := yaml.Marshal(cd)
+ if err != nil {
+ return nil, err
+ }
+ return data, nil
+}
+
+// InstructionManager는 모든 InstructionData를 관리하는 구조체입니다.
+type InstructionManager struct {
+ commands map[string]InstructionData
+}
+
+// NewInstructionManager는 InstructionManager를 초기화하고 YAML 파일들을 읽어들입니다.
+func NewInstructionManager() (*InstructionManager, error) {
+ cm := &InstructionManager{commands: make(map[string]InstructionData)}
+
+ err := cm.loadCommands()
+ if err != nil {
+ return nil, err
+ }
+
+ return cm, nil
+}
+
+// loadCommands는 주어진 경로에서 모든 YAML 파일을 읽어들여 InstructionData로 변환합니다.
+func (cm *InstructionManager) loadCommands() error {
+ // 디렉토리 내의 모든 YAML 파일을 찾습니다.
+ files, err := filepath.Glob(filepath.Join("../HTTPsBAS-Procedures/", "*.yaml"))
+ if err != nil {
+ return fmt.Errorf("failed to read directory: %w", err)
+ }
+
+ // 각 파일을 읽고 InstructionData로 변환
+ for _, file := range files {
+ err := cm.loadCommandFile(file)
+ if err != nil {
+ log.Printf("failed to load file %s: %v\n", file, err)
+ }
+ }
+
+ return nil
+}
+
+// loadCommandFile은 하나의 YAML 파일을 읽어 InstructionData로 변환하고 저장합니다.
+func (cm *InstructionManager) loadCommandFile(filepath string) error {
+ file, err := os.Open(filepath)
+ if err != nil {
+ return fmt.Errorf("failed to open file: %w", err)
+ }
+ defer file.Close()
+
+ // 파일 내용 읽기
+ data, err := ioutil.ReadAll(file)
+ if err != nil {
+ return fmt.Errorf("failed to read file: %w", err)
+ }
+
+ // YAML 데이터를 InstructionData 구조체로 변환
+ var command InstructionData
+ err = yaml.Unmarshal(data, &command)
+ if err != nil {
+ return fmt.Errorf("failed to unmarshal yaml: %w", err)
+ }
+
+ // ID를 키로 맵에 저장
+ cm.commands[command.ID] = command
+
+ return nil
+}
+
+// GetByID는 주어진 ID에 해당하는 InstructionData를 반환합니다.
+func (cm *InstructionManager) GetByID(id string) (*InstructionData, bool) {
+ command, exists := cm.commands[id]
+ if !exists {
+ return nil, false
+ }
+ return &command, true
+}
+
+/** 이전에 쓰고 현재는 사용하지 않는 코드라서 주석처리했습니다.
+해당 코드를 지우기전에 허남정 연구원에게 연락주시길 바랍니다.
+
+
+//// Insert는 새로운 InstructionData를 삽입하는 함수입니다.
+//// 이미 동일한 ID가 존재하면 false를 반환하고, 성공적으로 삽입되면 true를 반환합니다.
+//func (cm *InstructionManager) Insert(command InstructionData) bool {
+// // ID가 이미 존재하는지 확인
+// if _, exists := cm.commands[command.ID]; exists {
+// return false // 이미 존재하면 삽입하지 않고 false 반환
+// }
+//
+// // 맵에 새 InstructionData 삽입
+// cm.commands[command.ID] = command
+// return true
+//}
+
+//func main() {
+// // ../CommandDB/ 디렉토리에 있는 모든 YAML 파일을 읽어 InstructionManager를 초기화합니다.
+// InstructionManager, err := NewInstructionManager("../CommandDB/")
+// if err != nil {
+// log.Fatalf("Failed to initialize command manager: %v", err)
+// }
+//
+// // ID로 데이터를 가져오기 (예시)
+// id := "P_Collection_Kimsuky_001"
+// command, exists := InstructionManager.GetByID(id)
+// if exists {
+// fmt.Printf("Command found: %+v\n", command)
+// } else {
+// fmt.Printf("Command with ID %s not found\n", id)
+// }
+//}
+
+*/
diff --git a/Core/InstructionManager_test.go b/Core/InstructionManager_test.go
new file mode 100644
index 0000000..2e8654f
--- /dev/null
+++ b/Core/InstructionManager_test.go
@@ -0,0 +1,23 @@
+package Core
+
+import (
+ "fmt"
+ "testing"
+)
+
+// InstructionManager의 기본 동작을 테스트
+func TestInstructionManager_LoadAndGetByID(t *testing.T) {
+
+ cm, err := NewInstructionManager()
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ // ID로 InstructionData 가져오기
+ id := "P_Collection_Kimsuky_001"
+ command, exists := cm.GetByID(id)
+ if !exists {
+ t.Fatalf("Expected command with ID %s not found", id)
+ }
+
+ fmt.Println(command)
+}
diff --git a/Model/AgentStatus.go b/Model/AgentStatus.go
new file mode 100644
index 0000000..a1efbe9
--- /dev/null
+++ b/Model/AgentStatus.go
@@ -0,0 +1,266 @@
+package Model
+
+import (
+ "database/sql"
+ "fmt"
+ "github.com/HTTPs-omma/HTTPsBAS-HSProtocol/HSProtocol"
+ "time"
+)
+
+// Binary 값을 AgentStatus로 변환하는 메서드를 구현합니다.
+func BinaryToAgentStatus(i uint8) AgentStatus {
+ switch i {
+ case 0b00:
+ return HSProtocol.NEW
+ case 0b01:
+ return HSProtocol.WAIT
+ case 0b10:
+ return HSProtocol.RUN
+ case 0b11:
+ return HSProtocol.DELETED
+ default:
+ return HSProtocol.UNKNOWN
+ }
+}
+
+// Binary 값을 AgentStatus로 변환하는 메서드를 구현합니다.
+func BinaryToProtocol(i uint8) Protocol {
+ switch i {
+ case 0b0001:
+ return HSProtocol.TCP
+ case 0b0010:
+ return HSProtocol.UDP
+ case 0b0011:
+ return HSProtocol.HTTP
+ case 0b0100:
+ return HSProtocol.HTTPS
+ default:
+ return HSProtocol.UNKNOWN
+ }
+}
+
+// Protocol 유형을 정의합니다.
+type Protocol uint8
+
+// // AgentStatus 유형을 정의합니다.
+type AgentStatus int
+
+type AgentStatusDB struct {
+ dbName string
+}
+
+type AgentStatusRecord struct {
+ ID int
+ UUID string
+ Status AgentStatus
+ Protocol Protocol
+ CreatedAt time.Time
+ UpdatedAt time.Time
+}
+
+// NewAgentStatusDB creates a new instance of AgentStatusDB with the default table name.
+func NewAgentStatusDB() (*AgentStatusDB, error) {
+ db := &AgentStatusDB{dbName: "AgentStatus"}
+ err := db.CreateTable()
+ if err != nil {
+ return nil, err
+ }
+ return db, nil
+}
+
+// CreateTable creates the AgentStatus table if it does not exist.
+func (s *AgentStatusDB) CreateTable() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ sqlStmt := `
+ CREATE TABLE IF NOT EXISTS %s (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ uuid TEXT NOT NULL UNIQUE,
+ status int,
+ protocol int Default 0,
+ createAt DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updateAt DATETIME DEFAULT CURRENT_TIMESTAMP
+ );
+ `
+
+ sqlStmt = fmt.Sprintf(sqlStmt, s.dbName)
+
+ _, err = db.Exec(sqlStmt)
+ if err != nil {
+ return err
+ }
+
+ sqlTrigger := fmt.Sprintf(`
+ CREATE TRIGGER IF NOT EXISTS update_ModificationTime
+ AFTER UPDATE ON %s
+ FOR EACH ROW
+ BEGIN
+ UPDATE %s SET
+ updateAt = CURRENT_TIMESTAMP
+ WHERE id = NEW.id;
+ END;
+ `, s.dbName, s.dbName)
+
+ _, err = db.Exec(sqlTrigger)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// InsertRecord inserts a new record into the AgentStatus table.
+func (s *AgentStatusDB) InsertRecord(data *AgentStatusRecord) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ checkQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE uuid = ?`, s.dbName)
+ var count int
+ err = db.QueryRow(checkQuery, data.UUID).Scan(&count)
+ if err != nil {
+ return err
+ }
+ if count > 0 {
+ // 중복된 항목이 있으면 업데이트
+ return s.UpdateRecord(data)
+ }
+
+ query := fmt.Sprintf(`INSERT INTO %s (uuid, status, protocol) VALUES (?, ?, ?)`, s.dbName)
+ stmt, err := db.Prepare(query)
+ if err != nil {
+ return err
+ }
+ defer stmt.Close()
+
+ _, err = stmt.Exec(data.UUID, data.Status, data.Protocol)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *AgentStatusDB) SelectAllRecords() ([]AgentStatusRecord, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT id, uuid, status, protocol, createAt, updateAt FROM %s`, s.dbName)
+ rows, err := db.Query(query)
+ defer rows.Close()
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ records := []AgentStatusRecord{}
+ for rows.Next() {
+ var record AgentStatusRecord
+ err := rows.Scan(&record.ID, &record.UUID, &record.Status, &record.Protocol, &record.CreatedAt, &record.UpdatedAt)
+ if err != nil {
+ return nil, err
+ }
+ records = append(records, record)
+ }
+
+ return records, nil
+}
+
+func (s *AgentStatusDB) SelectRecordByUUID(uuid string) ([]AgentStatusRecord, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT id, uuid, status, protocol, createAt, updateAt FROM %s WHERE uuid = ?`, s.dbName)
+ row := db.QueryRow(query, uuid)
+
+ var records []AgentStatusRecord
+ var record AgentStatusRecord
+ err = row.Scan(&record.ID, &record.UUID, &record.Status, &record.Protocol, &record.CreatedAt, &record.UpdatedAt)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return nil, nil // Return nil if no record is found
+ }
+ return nil, err
+ }
+
+ return append(records, record), nil
+}
+
+// UpdateRecord updates the status and protocol of a record identified by its UUID.
+func (s *AgentStatusDB) UpdateRecord(data *AgentStatusRecord) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`UPDATE %s SET status = ? WHERE uuid = ?`, s.dbName)
+ _, err = db.Exec(query, data.Status, data.UUID)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// DeleteRecord deletes a record from the AgentStatus table based on its UUID.
+func (s *AgentStatusDB) DeleteRecord(uuid string) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s WHERE uuid = ?`, s.dbName)
+ _, err = db.Exec(query, uuid)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *AgentStatusDB) DeleteAllRecord() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s`)
+ _, err = db.Exec(query)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *AgentStatusDB) ExistRecord() (bool, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return false, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT EXISTS(SELECT 1 FROM %s)`, s.dbName)
+ var exists bool
+ err = db.QueryRow(query).Scan(&exists)
+ if err != nil {
+ return false, err
+ }
+
+ return exists, nil
+}
diff --git a/Model/AgentStatus_test.go b/Model/AgentStatus_test.go
new file mode 100644
index 0000000..b3621bc
--- /dev/null
+++ b/Model/AgentStatus_test.go
@@ -0,0 +1,84 @@
+package Model
+
+import (
+ "testing"
+ "time"
+)
+
+func TestAgentStatusDB(t *testing.T) {
+ // 새로운 DB 인스턴스 생성
+ db := NewAgentStatusDB()
+
+ // 테이블 생성 테스트
+ if err := db.CreateTable(); err != nil {
+ t.Fatalf("Failed to create table: %v", err)
+ }
+
+ // 테스트 데이터 생성
+ record := &AgentStatusRecord{
+ UUID: "test-uuid",
+ Status: Running,
+ CreatedAt: time.Now(),
+ UpdatedAt: time.Now(),
+ }
+
+ // InsertRecord 테스트
+ if err := db.InsertRecord(record); err != nil {
+ t.Fatalf("Failed to insert record: %v", err)
+ }
+
+ // SelectRecords 테스트 - 삽입 후 조회
+ records, err := db.SelectRecords()
+ if err != nil {
+ t.Fatalf("Failed to select records: %v", err)
+ }
+
+ if len(records) != 1 {
+ t.Fatalf("Expected 1 record, got %d", len(records))
+ }
+
+ if records[0].UUID != record.UUID || records[0].Status != record.Status {
+ t.Fatalf("Record mismatch: expected %v, got %v", record, records[0])
+ }
+
+ // UpdateRecord 테스트 - 상태 변경
+ record.Status = Stopping
+ if err := db.UpdateRecord(record); err != nil {
+ t.Fatalf("Failed to update record: %v", err)
+ }
+
+ // 업데이트 후 다시 조회
+ updatedRecords, err := db.SelectRecords()
+ if err != nil {
+ t.Fatalf("Failed to select records after update: %v", err)
+ }
+
+ if updatedRecords[0].Status != Stopping {
+ t.Fatalf("Expected status 'inactive', got '%s'", updatedRecords[0].Status)
+ }
+
+ // DeleteRecord 테스트
+ if err := db.DeleteRecord(record.UUID); err != nil {
+ t.Fatalf("Failed to delete record: %v", err)
+ }
+
+ // 삭제 후 조회하여 레코드가 없는지 확인
+ finalRecords, err := db.SelectRecords()
+ if err != nil {
+ t.Fatalf("Failed to select records after delete: %v", err)
+ }
+
+ if len(finalRecords) != 0 {
+ t.Fatalf("Expected 0 records, got %d", len(finalRecords))
+ }
+
+ // ExistRecord 테스트 - 데이터가 없는 상태에서 확인
+ exists, err := db.ExistRecord()
+ if err != nil {
+ t.Fatalf("Failed to check if record exists: %v", err)
+ }
+
+ if exists {
+ t.Fatalf("Expected no records to exist, but some do")
+ }
+}
diff --git a/Model/ApplicationDB.go b/Model/ApplicationDB.go
new file mode 100644
index 0000000..2ac8c6e
--- /dev/null
+++ b/Model/ApplicationDB.go
@@ -0,0 +1,368 @@
+package Model
+
+import (
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type ApplicationDB struct {
+ dbName string
+}
+
+func NewApplicationDB() (*ApplicationDB, error) {
+ appDB := &ApplicationDB{"Application"}
+ err := appDB.createTable()
+ if err != nil {
+ return nil, err
+ }
+ return appDB, nil
+}
+
+type DapplicationDB struct {
+ ID int `json:"id"`
+ AgentUUID string `json:"agent_uuid"`
+ Name string `json:"name"`
+ Version string `json:"version"`
+ Language string `json:"language"`
+ Vendor string `json:"vendor"`
+ InstallDate2 string `json:"install_date"`
+ InstallLocation string `json:"install_location"`
+ InstallSource string `json:"install_source"`
+ PackageName string `json:"package_name"`
+ PackageCode string `json:"package_code"`
+ RegCompany string `json:"reg_company"`
+ RegOwner string `json:"reg_owner"`
+ URLInfoAbout string `json:"url_info_about"`
+ Description string `json:"description"`
+ IsDeleted bool `json:"is_deleted"`
+ CreateAt time.Time `json:"create_at"`
+ UpdateAt time.Time `json:"update_at"`
+ DeletedAt time.Time `json:"deleted_at"`
+}
+
+func (a *ApplicationDB) createTable() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ sqlStmt := `
+ CREATE TABLE IF NOT EXISTS %s (
+ id INTEGER PRIMARY KEY AUTOINCREMENT, -- 내부 ID, 자동 증가
+ AgentUUID VARCHAR(255),
+ Name VARCHAR(255), -- 제품 이름
+ Version VARCHAR(50), -- 제품 버전
+ Language VARCHAR(10), -- 제품의 언어
+ Vendor VARCHAR(255), -- 제품 공급자
+ InstallDate2 VARCHAR(20), -- 설치 날짜
+ InstallLocation TEXT, -- 패키지 설치 위치
+ InstallSource TEXT, -- 설치 소스 위치
+ PackageName VARCHAR(255), -- 원래 패키지 이름
+ PackageCode VARCHAR(255) UNIQUE NOT NULL, -- 패키지 식별자 UUID
+ RegCompany VARCHAR(255), -- 제품을 사용하는 것으로 등록된 회사 이름
+ RegOwner VARCHAR(255), -- 제품을 사용하는 것으로 등록된 사용자 이름
+ URLInfoAbout TEXT, -- 제품에 대한 정보가 제공되는 URL
+ Description TEXT, -- 제품 설명
+ isDeleted bool DEFAULT FALSE, -- apllication 제거 여부를 파악함
+ createAt DATETIME DEFAULT CURRENT_TIMESTAMP, -- 레코드 생성 시간
+ updateAt DATETIME DEFAULT CURRENT_TIMESTAMP, -- 레코드 업데이트 시간
+ deletedAt DATETIME DEFAULT CURRENT_TIMESTAMP -- 제거된 시간
+ );
+ `
+ sqlStmt = fmt.Sprintf(sqlStmt, a.dbName)
+
+ _, err = db.Exec(sqlStmt)
+ if err != nil {
+ return err
+ }
+
+ sqlModifyTrigger := fmt.Sprintf(`
+ CREATE TRIGGER IF NOT EXISTS update_ModificationTime
+ AFTER UPDATE ON %s
+ FOR EACH ROW
+ BEGIN
+ UPDATE %s SET
+ updateAt = CURRENT_TIMESTAMP
+ WHERE id = NEW.id;
+ END;
+ `, a.dbName, a.dbName)
+
+ _, err = db.Exec(sqlModifyTrigger)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+/*
+refer : https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa394378(v=vs.85)
+class Win32_Product : CIM_Product
+
+ {
+ uint16 AssignmentType;
+ string Caption;
+ string Description;
+ string IdentifyingNumber;
+ string InstallDate;
+ datetime InstallDate2;
+ string InstallLocation;
+ sint16 InstallState;
+ string HelpLink;
+ string HelpTelephone;
+ string InstallSource;
+ string Language;
+ string LocalPackage;
+ string Name;
+ string PackageCache;
+ string PackageCode;
+ string PackageName;
+ string ProductID;
+ string RegOwner;
+ string RegCompany;
+ string SKUNumber;
+ string Transforms;
+ string URLInfoAbout;
+ string URLUpdateInfo;
+ string Vendor;
+ uint32 WordCount;
+ string Version;
+ };
+*/
+type Win32_Product struct {
+ Name string // 제품 이름
+ Version string // 제품 버전
+ Language string // 제품의 언어
+ Vendor string // 제품 공급자
+ InstallDate2 string // 설치 날짜
+ InstallLocation string // 패키지 설치 위치
+ InstallSource string // 설치 소스 위치
+ PackageName string // 원래 패키지 이름
+ PackageCode string // 패키지 식별자
+ RegCompany string // 제품을 사용하는 것으로 등록된 회사 이름
+ RegOwner string // 제품을 사용하는 것으로 등록된 사용자 이름
+ URLInfoAbout string // 제품에 대한 정보가 제공되는 URL
+ Description string // 제품 설명
+}
+
+func (a *ApplicationDB) InsertRecord(data *DapplicationDB) error {
+ // 데이터베이스 연결
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ // PackageCode 중복 확인 쿼리
+ checkQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE PackageCode = ? AND AgentUUID = ?`, a.dbName)
+ var count int
+ err = db.QueryRow(checkQuery, data.PackageCode, data.AgentUUID).Scan(&count)
+ if err != nil {
+ return err
+ }
+
+ if count > 0 {
+ // 중복된 항목이 있으면 업데이트
+ return a.UpdateByPackageCode(data)
+ }
+ //fmt.Println("dedbug")
+
+ // 중복된 항목이 없으면 삽입
+ query := fmt.Sprintf(`INSERT INTO %s (AgentUUID, Name, Version, Language, Vendor,
+ InstallDate2, InstallLocation, InstallSource, PackageName, PackageCode, RegCompany,
+ RegOwner, URLInfoAbout, Description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, a.dbName)
+
+ stmt, err := db.Prepare(query)
+ if err != nil {
+ return err
+ }
+ defer stmt.Close()
+
+ _, err = stmt.Exec(data.AgentUUID, data.Name, data.Version, data.Language, data.Vendor,
+ data.InstallDate2, data.InstallLocation, data.InstallSource, data.PackageName,
+ data.PackageCode, data.RegCompany, data.RegOwner, data.URLInfoAbout, data.Description)
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (a *ApplicationDB) UpdateByPackageCode(data *DapplicationDB) error {
+ // 데이터베이스 연결
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`UPDATE %s SET Name = ?, AgentUUID = ?, Version = ?, Language = ?, Vendor = ?,
+ InstallDate2 = ?, InstallLocation = ?, InstallSource = ?, PackageName = ?, RegCompany = ?,
+ RegOwner = ?, URLInfoAbout = ?, Description = ? WHERE PackageCode = ?`, a.dbName)
+
+ _, err = db.Exec(query, data.Name, data.AgentUUID, data.Version, data.Language, data.Vendor,
+ data.InstallDate2, data.InstallLocation, data.InstallSource, data.PackageName,
+ data.RegCompany, data.RegOwner, data.URLInfoAbout, data.Description, data.PackageCode)
+
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (s *ApplicationDB) SelectByPackageCode(packageCode string) (*DapplicationDB, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT * FROM %s WHERE PackageCode = '%s' LIMIT 1`, s.dbName, packageCode)
+ row, err := db.Query(query)
+ defer row.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ var data DapplicationDB
+
+ if row.Next() == false {
+ return &DapplicationDB{PackageCode: "-1"}, nil
+ }
+ err = row.Scan(&data.ID, &data.AgentUUID, &data.Name, &data.Version, &data.Language, &data.Vendor,
+ &data.InstallDate2, &data.InstallLocation, &data.InstallSource, &data.PackageName,
+ &data.PackageCode, &data.RegCompany, &data.RegOwner, &data.URLInfoAbout, &data.Description,
+ &data.IsDeleted, &data.CreateAt, &data.UpdateAt, &data.DeletedAt)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return &data, nil
+}
+
+func (s *ApplicationDB) DeleteByPackageCode(packageCode string) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s WHERE PackageCode = ?`, s.dbName)
+ _, err = db.Exec(query, packageCode)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *ApplicationDB) DeleteByAgentUUID(agentUUID string) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s WHERE AgentUUID = ?`, s.dbName)
+ _, err = db.Exec(query, agentUUID)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *ApplicationDB) DeleteAllRecords() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s WHERE`, s.dbName)
+ _, err = db.Exec(query)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *ApplicationDB) SelectAllRecords() ([]DapplicationDB, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT * FROM %s `, s.dbName)
+ row, err := db.Query(query)
+ defer row.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ rows := []DapplicationDB{}
+
+ for row.Next() {
+ var data DapplicationDB
+
+ err = row.Scan(&data.ID, &data.AgentUUID, &data.Name, &data.Version, &data.Language, &data.Vendor,
+ &data.InstallDate2, &data.InstallLocation, &data.InstallSource, &data.PackageName,
+ &data.PackageCode, &data.RegCompany, &data.RegOwner, &data.URLInfoAbout, &data.Description,
+ &data.IsDeleted, &data.CreateAt, &data.UpdateAt, &data.DeletedAt)
+ if err != nil {
+ return nil, err
+ }
+ rows = append(rows, data)
+ }
+
+ return rows, nil
+}
+
+// SelectRecordByUUID retrieves a record from the ApplicationDB table by UUID.
+func (s *ApplicationDB) SelectRecordByUUID(uuid string) ([]DapplicationDB, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT * FROM %s WHERE AgentUUID = ?`, s.dbName)
+ rows, err := db.Query(query, uuid)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ results := []DapplicationDB{}
+ for rows.Next() {
+ var data DapplicationDB
+ err = rows.Scan(&data.ID, &data.AgentUUID, &data.Name, &data.Version, &data.Language, &data.Vendor,
+ &data.InstallDate2, &data.InstallLocation, &data.InstallSource, &data.PackageName,
+ &data.PackageCode, &data.RegCompany, &data.RegOwner, &data.URLInfoAbout, &data.Description,
+ &data.IsDeleted, &data.CreateAt, &data.UpdateAt, &data.DeletedAt)
+ if err != nil {
+ return nil, err
+ }
+ results = append(results, data)
+ }
+
+ return results, nil
+}
+
+// ToJSON: 구조체를 JSON 바이트로 마샬링
+func (s *ApplicationDB) ToJSON(data []DapplicationDB) ([]byte, error) {
+ return json.Marshal(data)
+}
+
+// FromJSON: JSON 바이트를 구조체로 언마샬링
+func (s *ApplicationDB) FromJSON(data []byte) ([]DapplicationDB, error) {
+ var result []DapplicationDB
+ err := json.Unmarshal(data, &result)
+ return result, err
+}
diff --git a/Model/ApplicationDB_test.go b/Model/ApplicationDB_test.go
new file mode 100644
index 0000000..ad1cbde
--- /dev/null
+++ b/Model/ApplicationDB_test.go
@@ -0,0 +1,104 @@
+package Model
+
+import (
+ "fmt"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestApplicationDB_createTable(t1 *testing.T) {
+ type fields struct {
+ dbName string
+ }
+ tests := []struct {
+ name string
+ fields fields
+ }{
+ {name: "Test case 1"},
+ }
+
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t *testing.T) {
+ appdb := NewApplicationDB()
+ err := appdb.createTable()
+ if err != nil {
+ t1.Fatalf("Error creating table: %v", err)
+ }
+
+ // ========== 검증 =============
+ dbPtr, err := getDBPtr()
+ if err != nil {
+ t1.Fatalf(appdb.dbName + " : DB 포인터를 가져올 수 없습니다. getDBPtr() 함수 오류\n" + err.Error())
+ }
+
+ query := fmt.Sprintf("select * from sqlite_master where name = '%s'", appdb.dbName)
+
+ dsys := &sqlite_master{}
+
+ rst := dbPtr.QueryRow(query).Scan(&dsys.Type, &dsys.name, &dsys.tbl_name, &dsys.rootpage, &dsys.sql)
+ if rst != nil {
+ t1.Fatalf(appdb.dbName + " : 생성된 테이블이 존재하지 않습니다.")
+ }
+ assert.Equal(t1, dsys.name, appdb.dbName)
+ })
+ }
+}
+
+func TestApplicationDB_CRUD(t1 *testing.T) {
+ type fields struct {
+ dbName string
+ }
+ tests := []struct {
+ name string
+ fields fields
+ }{
+ {name: "Test case 1"},
+ }
+
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t *testing.T) {
+ })
+ }
+}
+
+//func TestApplicationDB_CreateAll(t1 *testing.T) {
+// type fields struct {
+// dbName string
+// }
+// tests := []struct {
+// name string
+// fields fields
+// }{
+// {name: "Test case 1"},
+// }
+// for _, tt := range tests {
+// t1.Run(tt.name, func(t *testing.T) {
+// // ============ Create 테스트 ================
+// appdb := NewApplicationDB()
+// appdb.createTable()
+//
+// wind32 := getApplicationList()
+// for _, wind := range wind32 {
+// data := DapplicationDB{}
+// data.Name = wind.Name
+// data.Description = wind.Description
+// data.Version = wind.Version
+// data.Vendor = wind.Vendor
+// data.InstallDate2 = wind.InstallDate2
+// data.InstallLocation = wind.InstallLocation
+// data.InstallSource = wind.InstallSource
+// data.Language = wind.Language
+// data.PackageCode = wind.PackageCode
+// data.PackageName = wind.PackageName
+// data.RegCompany = wind.RegCompany
+// data.RegOwner = wind.RegOwner
+// data.URLInfoAbout = wind.URLInfoAbout
+//
+// err := appdb.insertRecord(data)
+// if err != nil {
+// t.Fatalf(appdb.dbName + " : insert 에러\n" + err.Error())
+// }
+// }
+// })
+// }
+//}
diff --git a/Model/FileMetaDB.go b/Model/FileMetaDB.go
deleted file mode 100644
index 537f47c..0000000
--- a/Model/FileMetaDB.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package Model
-
-//
-//import (
-// "log"
-//)
-//
-//import (
-// _ "github.com/mattn/go-sqlite3"
-//)
-//
-//type FileMetaDB struct {
-// dbPath string
-//}
-//
-//func NewFileMetaDB() (metaTable *FileMetaDB) {
-//
-// metaTable = &FileMetaDB{
-// dbPath: "file:db.db?cache=shared",
-// }
-//
-// metaTable.createTable()
-//
-// return metaTable
-//}
-//
-///*
-//refer : https://github.com/steffenfritz/FileTrove?tab=readme-ov-file
-//action : 인덱싱을 위한 데이터 테이블을 생성합니다.
-//- 인덱싱 테이블을 만들 때,
-//
-//단일 바이너리 애플리케이션이 디렉터리 트리를 탐색하고 Siegfried를 사용하여 모든 일반 파일을 형식별로 식별합니다.
-//이때 다음 정보를 제공합니다 :
-//1. MIME type
-//- 파일의 인터넷 미디어 타입을 나타내며, 파일의 형식을 식별합니다.
-//- ex. 이미지 파일은 image/jpeg,
-//2. PRONOM identifier
-//3. Format version
-//4. Identification proof and note
-//5. filename extension
-//
-//os.Stat() is giving you the
-//6. File size
-//7. File creation time
-//8. File modification time
-//9. File access time
-//
-//and the same for directories
-//Furthermore it creates and calculates
-//
-//10. UUIDv4s as unique identifiers (not stable across sessions)
-//11. hash sums (md5, sha1, sha256, sha512 and blake2b-512)
-//12. the entropy of each file (up to 1GB)
-//13. and it extracts some EXIF metadata and
-//14. you can add your own DublinCore Elements metadata to scans.
-//15. A very powerful feature is FileTrove's ability to consume YARA-X rule files.
-//16. FileTrove also checks if the file is in the NSRL.
-//*/
-//func (t *FileMetaDB) createTable() {
-// sqlStmt := `
-// CREATE TABLE IF NOT EXISTS FileMetadata (
-// id INTEGER PRIMARY KEY AUTOINCREMENT, -- 내부 ID, 자동 증가
-// uuid TEXT NOT NULL unique, -- UUIDv4
-// path TEXT NOT NULL, -- 파일 경로
-// name TEXT NOT NULL, -- 파일명
-// type TEXT NOT NULL, -- 파일 유형 (파일 또는 디렉터리)
-// mime_type TEXT, -- MIME 타입
-// pronom_id TEXT, -- PRONOM 식별자
-// format_version TEXT, -- 포맷 버전
-// identification_proof TEXT, -- 식별 증거 및 노트
-// file_extension TEXT, -- 파일 확장자
-// file_size INTEGER, -- 파일 크기 (바이트)
-// creation_time DATETIME, -- 파일 생성 시간
-// modification_time DATETIME, -- 파일 수정 시간
-// access_time DATETIME, -- 파일 접근 시간
-// md5 TEXT, -- MD5 해시
-// sha256 TEXT, -- SHA-256 해시
-// entropy REAL, -- 엔트로피 (최대 1GB 파일)
-// exif_metadata TEXT, -- EXIF 메타데이터
-// dublin_core TEXT, -- Dublin Core 메타데이터
-// yara_x_result TEXT, -- YARA-X 룰 결과
-// nsrl_check BOOLEAN, -- NSRL 체크 여부
-// scan_date DATETIME DEFAULT CURRENT_TIMESTAMP -- 스캔 날짜
-// );
-// `
-//
-// _, err := t.db.Exec(sqlStmt)
-// if err != nil {
-// log.Fatal(err)
-// }
-//}
diff --git a/Model/JobData.go b/Model/JobData.go
new file mode 100644
index 0000000..07200d0
--- /dev/null
+++ b/Model/JobData.go
@@ -0,0 +1,227 @@
+package Model
+
+import (
+ "database/sql"
+ "fmt"
+ "time"
+)
+
+type JobData struct {
+ Id int `json:"id"`
+ ProcedureID string `json:"procedureID"`
+ AgentUUID string `json:"agentUUID"`
+ MessageUUID string `json:"messageUUID"`
+ CreateAt time.Time `json:"createAt"`
+}
+
+/**
+Chatgpt 이용해서 생성
+*/
+
+type JobDB struct {
+ dbName string
+}
+
+// NewJobDB: SQLite DB를 초기화하고 테이블을 생성하는 함수
+func NewJobDB() (*JobDB, error) {
+ jd := &JobDB{dbName: "jobs"}
+ err := jd.createTableIfNotExists()
+ if err != nil {
+ return nil, err
+ }
+ return jd, nil
+}
+
+// createTableIfNotExists: jobs 테이블이 없으면 생성
+func (jd *JobDB) createTableIfNotExists() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ createTableSQL := `
+ CREATE TABLE IF NOT EXISTS jobs (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ ProcedureID TEXT,
+ AgentUUID TEXT,
+ MessageUUID TEXT,
+ CreateAt DATETIME
+ );`
+
+ _, err = db.Exec(createTableSQL)
+ if err != nil {
+ return fmt.Errorf("create table failed: %w", err)
+ }
+ return nil
+}
+
+func (jd *JobDB) InsertJobData(jobData *JobData) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+ jobData.CreateAt = time.Now()
+ insertSQL := `INSERT INTO jobs (ProcedureID, AgentUUID, MessageUUID, CreateAt)
+ VALUES (?, ?, ?, ?)`
+ _, err = db.Exec(insertSQL, jobData.ProcedureID, jobData.AgentUUID, jobData.MessageUUID, jobData.CreateAt)
+ fmt.Println(jobData)
+ if err != nil {
+ return fmt.Errorf("insert job failed: %w", err)
+ }
+ return nil
+}
+
+// GetJobDataByAgentUUID: AgentUUID 기반으로 JobData 조회
+func (jd *JobDB) SelectJobDataByAgentUUID(agentUUID string) (*JobData, error, bool) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err, false
+ }
+ defer db.Close()
+
+ selectSQL := `SELECT id, ProcedureID, AgentUUID, MessageUUID, CreateAt FROM jobs WHERE AgentUUID = ?`
+ rows, err := db.Query(selectSQL, agentUUID)
+ if err != nil {
+ return nil, err, false
+ }
+ defer rows.Close()
+ if rows.Next() == false {
+ // 결과가 없다면,
+ return &JobData{}, nil, false
+ }
+
+ var job *JobData = &JobData{}
+ err = rows.Scan(&job.ProcedureID, &job.Id, &job.AgentUUID, &job.MessageUUID, &job.CreateAt) // 첫 행에만 적용
+ if err != nil {
+ return nil, err, true
+ }
+
+ return job, nil, true
+}
+
+func (jd *JobDB) SelectAllJobData() ([]JobData, error) {
+
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ selectSQL := `SELECT id, ProcedureID, AgentUUID, MessageUUID, CreateAt FROM jobs`
+
+ rows, err := db.Query(selectSQL)
+ defer rows.Close()
+ if err != nil {
+ return nil, err
+ }
+ if rows.Next() == false {
+ return []JobData{}, nil
+ }
+
+ jobs := []JobData{}
+
+ var job_init *JobData = &JobData{}
+ err = rows.Scan(&job_init.Id, &job_init.ProcedureID, &job_init.AgentUUID, &job_init.MessageUUID, &job_init.CreateAt) // 첫 행에만 적용
+ if err != nil {
+ return nil, err
+ }
+ jobs = append(jobs, *job_init)
+
+ for rows.Next() == true {
+ var job *JobData = &JobData{}
+ err = rows.Scan(&job.Id, &job.ProcedureID, &job.AgentUUID, &job.MessageUUID, &job.CreateAt) // 첫 행에만 적용
+ if err != nil {
+ return nil, err
+ }
+ jobs = append(jobs, *job)
+ }
+
+ return jobs, nil
+}
+
+func (jd *JobDB) PopbyAgentUUID(agentUUID string) (*JobData, error, bool) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err, false
+ }
+ defer db.Close()
+
+ // 쿼리문 수정: WHERE 절을 추가하고 ORDER BY를 사용하여 CreateAt을 기준으로 내림차순 정렬
+ selectSQL := `
+ SELECT id, ProcedureID, AgentUUID, MessageUUID, CreateAt
+ FROM jobs
+ WHERE AgentUUID = ?
+ ORDER BY CreateAt DESC
+ LIMIT 1
+ `
+
+ // QueryRow를 사용하여 한 행만 가져옵니다.
+ row := db.QueryRow(selectSQL, agentUUID)
+
+ var job JobData
+ err = row.Scan(&job.Id, &job.ProcedureID, &job.AgentUUID, &job.MessageUUID, &job.CreateAt)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ // 일치하는 행이 없는 경우
+ return &JobData{}, nil, false
+ }
+ return nil, err, false
+ }
+
+ // 해당 JobData를 삭제
+ err = jd.DeleteJobDataById(job.Id)
+ if err != nil {
+ return nil, err, false
+ }
+
+ return &job, nil, true
+}
+
+// DeleteJobDataByMessageUUID: MessageUUID 기반으로 JobData 삭제
+func (jd *JobDB) DeleteJobDataByMessageUUID(messageUUID string) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ deleteSQL := `DELETE FROM jobs WHERE MessageUUID = ?`
+ _, err = db.Exec(deleteSQL, messageUUID)
+ if err != nil {
+ return fmt.Errorf("delete job failed: %w", err)
+ }
+ return nil
+}
+
+func (jd *JobDB) DeleteJobDataById(id int) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ deleteSQL := `DELETE FROM jobs WHERE id = ?`
+ _, err = db.Exec(deleteSQL, id)
+ if err != nil {
+ return fmt.Errorf("delete job failed: %w", err)
+ }
+ return nil
+}
+
+// DeleteJobDataByMessageUUID: MessageUUID 기반으로 JobData 삭제
+func (jd *JobDB) DeleteAllJobData() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ deleteSQL := `DELETE FROM jobs`
+ _, err = db.Exec(deleteSQL)
+ if err != nil {
+ return fmt.Errorf("delete job failed: %w", err)
+ }
+ return nil
+}
diff --git a/Model/OperationLog.go b/Model/OperationLog.go
new file mode 100644
index 0000000..aebc74f
--- /dev/null
+++ b/Model/OperationLog.go
@@ -0,0 +1,147 @@
+package Model
+
+import (
+ "context"
+ "fmt"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+ "go.mongodb.org/mongo-driver/mongo"
+ "time"
+)
+
+/*
+빠른 개발을 위해 chatgpt 를 사용한 개발 코드입니다.
+검토자 : 허남정
+*/
+
+// OperationLogDocument 구조체 정의
+type OperationLogDocument struct {
+ ID primitive.ObjectID `bson:"_id,omitempty"`
+ AgentUUID string `bson:"agentUUID"`
+ ProcedureID string `bson:"procedureID"`
+ MessageUUID string `bson:"messageUUID"`
+ ConductAt time.Time `bson:"conductAt"`
+ ExitCode int `bson:"exitCode"`
+ Log string `bson:"log"`
+ Command string `bson:"command"` // Command 필드로 변경
+}
+
+const (
+ EXIT_SUCCESS = 1
+ EXIT_Unknown = 0
+ EXIT_FAIL = -1
+)
+
+type OperationLogDB struct {
+ DBNAME string
+}
+
+func NewOperationLogDB() (*OperationLogDB, error) {
+ return &OperationLogDB{DBNAME: "execLog"}, nil
+}
+
+func (repo *OperationLogDB) InsertDocument(log *OperationLogDocument) (*mongo.InsertOneResult, error) {
+ db, err := getCollectionPtr()
+ if err != nil {
+ return nil, err
+ }
+ ptrdb := db.Collection(repo.DBNAME)
+ // Command 필드를 기본값으로 설정 (필요에 따라 변경)
+ result, err := ptrdb.InsertOne(context.TODO(), log)
+ fmt.Println(log)
+ if err != nil {
+ return nil, err
+ }
+
+ fmt.Println("Inserted document with ID:", result.InsertedID)
+ return result, nil
+}
+
+func (repo *OperationLogDB) SelectDocumentById(id string) (*OperationLogDocument, error) {
+ db, err := getCollectionPtr()
+ if err != nil {
+ return nil, err
+ }
+ ptrdb := db.Collection(repo.DBNAME)
+
+ var OperationLogDocument OperationLogDocument
+ filter := bson.M{"messageUUID": id}
+
+ err = ptrdb.FindOne(context.TODO(), filter).Decode(&OperationLogDocument)
+ if err != nil {
+ return nil, err
+ }
+
+ return &OperationLogDocument, nil
+}
+
+func (repo *OperationLogDB) SelectAllDocuments() ([]OperationLogDocument, error) {
+ documents := []OperationLogDocument{}
+ db, err := getCollectionPtr()
+ if err != nil {
+ return documents, err
+ }
+ ptrdb := db.Collection(repo.DBNAME)
+
+ filter := bson.M{}
+
+ cursor, err := ptrdb.Find(context.TODO(), filter)
+ if err != nil {
+ return documents, err
+ }
+
+ defer cursor.Close(context.TODO())
+
+ for cursor.Next(context.TODO()) {
+ var doc OperationLogDocument
+ if err := cursor.Decode(&doc); err != nil {
+ return nil, err
+ }
+ documents = append(documents, doc)
+ }
+
+ if err := cursor.Err(); err != nil {
+ return documents, err
+ }
+
+ return documents, nil
+}
+
+func (repo *OperationLogDB) UpdateDocumentByInstID(id string, updateData bson.M) (*mongo.UpdateResult, error) {
+ db, err := getCollectionPtr()
+ if err != nil {
+ return nil, err
+ }
+ ptrdb := db.Collection(repo.DBNAME)
+
+ filter := bson.M{"messageUUID": id}
+ update := bson.M{
+ "$set": updateData,
+ }
+
+ result, err := ptrdb.UpdateOne(context.TODO(), filter, update)
+ if err != nil {
+ return nil, err
+ }
+
+ fmt.Println("Updated document count:", result.ModifiedCount)
+ return result, nil
+}
+
+func (repo *OperationLogDB) DeleteAllDocument() (*mongo.DeleteResult, error) {
+ db, err := getCollectionPtr()
+ if err != nil {
+ return nil, err
+ }
+ ptrdb := db.Collection(repo.DBNAME)
+
+ filter := bson.M{}
+
+ result, err := ptrdb.DeleteMany(context.TODO(), filter)
+ if err != nil {
+ return nil, err
+ }
+
+ fmt.Println("Deleted document count:", result.DeletedCount)
+ return result, nil
+}
diff --git a/Model/ProgrameNameDB.go b/Model/ProgrameNameDB.go
new file mode 100644
index 0000000..7e13a47
--- /dev/null
+++ b/Model/ProgrameNameDB.go
@@ -0,0 +1,211 @@
+package Model
+
+import (
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type ProgramsDB struct {
+ dbName string
+}
+
+func NewProgramsDB() (*ProgramsDB, error) {
+ db := &ProgramsDB{dbName: "Programs"}
+ err := db.CreateTable()
+ if err != nil {
+ return nil, err
+ }
+ return db, nil
+}
+
+type ProgramsRecord struct {
+ ID int `json:"id"`
+ AgentUUID string `json:"agent_uuid"`
+ FileName string `json:"file_name"`
+ CreateAt time.Time `json:"create_at"`
+ UpdateAt time.Time `json:"update_at"`
+ DeletedAt time.Time `json:"deleted_at"`
+}
+
+func (a *ProgramsDB) CreateTable() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ sqlStmt := `
+ CREATE TABLE IF NOT EXISTS %s (
+ id INTEGER PRIMARY KEY AUTOINCREMENT, -- 내부 ID, 자동 증가
+ AgentUUID VARCHAR(255),
+ FileName VARCHAR(255),
+ createAt DATETIME DEFAULT CURRENT_TIMESTAMP, -- 레코드 생성 시간
+ updateAt DATETIME DEFAULT CURRENT_TIMESTAMP, -- 레코드 업데이트 시간
+ deletedAt DATETIME DEFAULT CURRENT_TIMESTAMP -- 제거된 시간
+ );
+ `
+ sqlStmt = fmt.Sprintf(sqlStmt, a.dbName)
+
+ _, err = db.Exec(sqlStmt)
+ if err != nil {
+ return err
+ }
+
+ sqlModifyTrigger := fmt.Sprintf(`
+ CREATE TRIGGER IF NOT EXISTS update_ModificationTime
+ AFTER UPDATE ON %s
+ FOR EACH ROW
+ BEGIN
+ UPDATE %s SET
+ updateAt = CURRENT_TIMESTAMP
+ WHERE id = NEW.id;
+ END;
+ `, a.dbName, a.dbName)
+
+ _, err = db.Exec(sqlModifyTrigger)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// InsertRecord: 레코드 삽입
+func (a *ProgramsDB) InsertRecord(agentUUID string, fileName string) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`INSERT INTO %s (AgentUUID, FileName) VALUES (?, ?)`, a.dbName)
+ _, err = db.Exec(query, agentUUID, fileName)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// SelectAllRecords: 모든 레코드를 선택
+func (a *ProgramsDB) SelectAllRecords() ([]ProgramsRecord, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT id, AgentUUID, FileName, createAt, updateAt, deletedAt FROM %s`, a.dbName)
+ rows, err := db.Query(query)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var records []ProgramsRecord
+ for rows.Next() {
+ var record ProgramsRecord
+ err = rows.Scan(&record.ID, &record.AgentUUID, &record.FileName, &record.CreateAt, &record.UpdateAt, &record.DeletedAt)
+ if err != nil {
+ return nil, err
+ }
+ records = append(records, record)
+ }
+
+ return records, nil
+}
+
+// SelectRecordsByUUID: 특정 AgentUUID에 따른 레코드를 선택
+func (a *ProgramsDB) SelectRecordsByUUID(agentUUID string) ([]ProgramsRecord, error) {
+ db, err := getDBPtr() // 데이터베이스 연결
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ // 쿼리문 작성 (AgentUUID에 따라 필터링)
+ query := fmt.Sprintf(`SELECT id, AgentUUID, FileName, createAt, updateAt, deletedAt FROM %s WHERE AgentUUID = ?`, a.dbName)
+ rows, err := db.Query(query, agentUUID)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var records []ProgramsRecord
+ for rows.Next() {
+ var record ProgramsRecord
+ // 각 필드의 값을 스캔하여 구조체에 저장
+ err = rows.Scan(&record.ID, &record.AgentUUID, &record.FileName, &record.CreateAt, &record.UpdateAt, &record.DeletedAt)
+ if err != nil {
+ return nil, err
+ }
+ records = append(records, record)
+ }
+
+ return records, nil
+}
+
+// UpdateRecordByID: ID를 기준으로 레코드 업데이트
+func (a *ProgramsDB) UpdateRecordByID(id int, newFileName string) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`UPDATE %s SET FileName = ?, updateAt = ? WHERE id = ?`, a.dbName)
+ _, err = db.Exec(query, newFileName, time.Now(), id)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// DeleteRecordByID: ID를 기준으로 레코드 삭제
+func (a *ProgramsDB) DeleteRecordByID(id int) error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s WHERE id = ?`, a.dbName)
+ _, err = db.Exec(query, id)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (a *ProgramsDB) DeleteAllRecords() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s`, a.dbName)
+ _, err = db.Exec(query)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// ToJSON: ProgramNameDB 레코드 리스트를 JSON 바이트로 변환
+func (s *ProgramsDB) ToJSON(data []ProgramsRecord) ([]byte, error) {
+ // JSON 마샬링하여 []byte로 반환
+ return json.Marshal(data)
+}
+
+// FromJSON: JSON 바이트를 ProgramNameDB 레코드 리스트로 변환
+func (s *ProgramsDB) FromJSON(data []byte) ([]ProgramsRecord, error) {
+ var result []ProgramsRecord
+ // JSON 언마샬링하여 구조체로 변환
+ err := json.Unmarshal(data, &result)
+ return result, err
+}
diff --git a/Model/SystemInfoDB.go b/Model/SystemInfoDB.go
index 1205243..8fd63a8 100644
--- a/Model/SystemInfoDB.go
+++ b/Model/SystemInfoDB.go
@@ -1,6 +1,7 @@
package Model
import (
+ "encoding/json"
"errors"
"fmt"
"time"
@@ -11,25 +12,31 @@ type SystemInfoDB struct {
}
type DsystemInfoDB struct {
- id int
- Uuid string
- HostName string
- OsName string
- OsVersion string
- Family string
- Architecture string
- KernelVersion string
- BootTime time.Time
- createAt time.Time
- updateAt time.Time
+ ID int `json:"id"`
+ Uuid string `json:"uuid"`
+ HostName string `json:"host_name"`
+ OsName string `json:"os_name"`
+ OsVersion string `json:"os_version"`
+ Family string `json:"family"`
+ Architecture string `json:"architecture"`
+ KernelVersion string `json:"kernel_version"`
+ BootTime time.Time `json:"boot_time"`
+ IP string `json:"ip"` // IP 추가
+ MAC string `json:"mac"` // MAC 추가
+ CreatedAt time.Time `json:"created_at"`
+ UpdatedAt time.Time `json:"updated_at"`
}
-func NewSystemInfoDB() *SystemInfoDB {
+func NewSystemInfoDB() (*SystemInfoDB, error) {
sysDB := &SystemInfoDB{"SystemInfo"}
- return sysDB
+ err := sysDB.CreateTable()
+ if err != nil {
+ return nil, err
+ }
+ return sysDB, nil
}
-func (s *SystemInfoDB) createTable() error {
+func (s *SystemInfoDB) CreateTable() error {
db, err := getDBPtr()
if err != nil {
return err
@@ -40,7 +47,6 @@ func (s *SystemInfoDB) createTable() error {
CREATE TABLE IF NOT EXISTS %s (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 내부 ID, 자동 증가
uuid TEXT NOT NULL unique, -- UUIDv4
- AgentUUID VARCHAR(255),
HostName string,
OsName string,
OsVersion string,
@@ -48,6 +54,8 @@ func (s *SystemInfoDB) createTable() error {
Architecture string,
KernelVersion string,
BootTime DATETIME,
+ IP string, -- IP 추가
+ MAC string, -- MAC 추가
createAt DATETIME DEFAULT CURRENT_TIMESTAMP,
updateAt DATETIME DEFAULT CURRENT_TIMESTAMP
);
@@ -78,14 +86,14 @@ func (s *SystemInfoDB) createTable() error {
return nil
}
-func (s *SystemInfoDB) insertRecord(data *DsystemInfoDB) error {
+func (s *SystemInfoDB) InsertRecord(data *DsystemInfoDB) error {
// 데이터 베이스에는 단 하나의 Row 만을 보장해야함
- isExist, err := s.existRecord()
+ isExist, err := s.ExistRecord()
if err != nil {
return err
}
if isExist == true {
- err = s.updateRecord(data)
+ err = s.UpdateRecord(data)
if err != nil {
return err
}
@@ -98,21 +106,16 @@ func (s *SystemInfoDB) insertRecord(data *DsystemInfoDB) error {
}
defer db.Close()
- query := fmt.Sprintf(`INSERT INTO %s (uuid, HostName,
- OsName, OsVersion, Family, Architecture, KernelVersion,
- BootTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, s.dbName)
+ query := fmt.Sprintf(`INSERT INTO %s (uuid, HostName, OsName, OsVersion, Family, Architecture, KernelVersion, BootTime, IP, MAC)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, s.dbName)
stmt, err := db.Prepare(query)
- fmt.Println(query)
defer stmt.Close()
+
if err != nil {
return err
}
- _, err = stmt.Exec(data.Uuid, data.HostName, data.OsName,
- data.OsVersion, data.Family, data.Architecture,
- data.KernelVersion, data.BootTime)
- //fmt.Println(rst.LastInsertId())
- //fmt.Println("debug=-===============")
+ _, err = stmt.Exec(data.Uuid, data.HostName, data.OsName, data.OsVersion, data.Family, data.Architecture, data.KernelVersion, data.BootTime, data.IP, data.MAC)
if err != nil {
return err
@@ -121,18 +124,14 @@ func (s *SystemInfoDB) insertRecord(data *DsystemInfoDB) error {
return nil
}
-/*
-selectRecords()를 통해 반환된 DsystemInfoDB 객체의 값을 수정한 후,
-수정된 객체를 updateRecord 함수의 매개변수로 전달합시오
-*/
-func (s *SystemInfoDB) updateRecord(data *DsystemInfoDB) error {
+func (s *SystemInfoDB) UpdateRecord(data *DsystemInfoDB) error {
db, err := getDBPtr()
if err != nil {
return err
}
defer db.Close()
- rows, err := s.selectRecords()
+ rows, err := s.SelectAllRecords()
if err != nil {
return err
}
@@ -142,8 +141,8 @@ func (s *SystemInfoDB) updateRecord(data *DsystemInfoDB) error {
row := rows[0]
data.Uuid = row.Uuid
- query := fmt.Sprintf(`UPDATE %s SET HostName = ?, OsName = ?, OsVersion = ?, Family = ?, Architecture = ?, KernelVersion = ?, BootTime = ?`, s.dbName)
- _, err = db.Exec(query, data.HostName, data.OsName, data.OsVersion, data.Family, data.Architecture, data.KernelVersion, data.BootTime)
+ query := fmt.Sprintf(`UPDATE %s SET HostName = ?, OsName = ?, OsVersion = ?, Family = ?, Architecture = ?, KernelVersion = ?, BootTime = ?, IP = ?, MAC = ?`, s.dbName)
+ _, err = db.Exec(query, data.HostName, data.OsName, data.OsVersion, data.Family, data.Architecture, data.KernelVersion, data.BootTime, data.IP, data.MAC)
if err != nil {
return err
}
@@ -151,7 +150,7 @@ func (s *SystemInfoDB) updateRecord(data *DsystemInfoDB) error {
return nil
}
-func (s *SystemInfoDB) deleteRecord(uuid string) error {
+func (s *SystemInfoDB) DeleteRecordByUUID(uuid string) error {
db, err := getDBPtr()
if err != nil {
return err
@@ -167,7 +166,23 @@ func (s *SystemInfoDB) deleteRecord(uuid string) error {
return nil
}
-func (s *SystemInfoDB) selectRecords() ([]DsystemInfoDB, error) {
+func (s *SystemInfoDB) DeleteAllRecord() error {
+ db, err := getDBPtr()
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`DELETE FROM %s`, s.dbName)
+ _, err = db.Exec(query)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *SystemInfoDB) SelectAllRecords() ([]DsystemInfoDB, error) {
db, err := getDBPtr()
if err != nil {
return nil, err
@@ -176,18 +191,17 @@ func (s *SystemInfoDB) selectRecords() ([]DsystemInfoDB, error) {
query := fmt.Sprintf(`SELECT * FROM %s`, s.dbName)
row, err := db.Query(query)
+ defer row.Close()
if err != nil {
return nil, err
}
- var rows []DsystemInfoDB
+ rows := []DsystemInfoDB{}
for row.Next() {
var data DsystemInfoDB
- err = row.Scan(&data.id, &data.Uuid, &data.HostName, &data.OsName,
- &data.OsVersion, &data.Family, &data.Architecture, &data.KernelVersion,
- &data.BootTime, &data.createAt, &data.updateAt)
+ err = row.Scan(&data.ID, &data.Uuid, &data.HostName, &data.OsName, &data.OsVersion, &data.Family, &data.Architecture, &data.KernelVersion, &data.BootTime, &data.IP, &data.MAC, &data.CreatedAt, &data.UpdatedAt)
if err != nil {
return nil, err
}
@@ -197,11 +211,34 @@ func (s *SystemInfoDB) selectRecords() ([]DsystemInfoDB, error) {
return rows, nil
}
-/*
-*
-하나 이상의 row 행이 있는지 검사한다.
-*/
-func (s *SystemInfoDB) existRecord() (bool, error) {
+func (s *SystemInfoDB) SelectRecordByUUID(uuid string) ([]DsystemInfoDB, error) {
+ db, err := getDBPtr()
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+
+ query := fmt.Sprintf(`SELECT * FROM %s WHERE uuid = ?`, s.dbName)
+ rows, err := db.Query(query, uuid)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ results := []DsystemInfoDB{}
+ for rows.Next() {
+ data := DsystemInfoDB{}
+ err = rows.Scan(&data.ID, &data.Uuid, &data.HostName, &data.OsName, &data.OsVersion, &data.Family, &data.Architecture, &data.KernelVersion, &data.BootTime, &data.IP, &data.MAC, &data.CreatedAt, &data.UpdatedAt)
+ if err != nil {
+ return nil, err
+ }
+ results = append(results, data)
+ }
+
+ return results, nil
+}
+
+func (s *SystemInfoDB) ExistRecord() (bool, error) {
db, err := getDBPtr()
if err != nil {
return false, err
@@ -217,3 +254,20 @@ func (s *SystemInfoDB) existRecord() (bool, error) {
return exists, nil
}
+
+func (s *SystemInfoDB) Unmarshal(data []byte) (*DsystemInfoDB, error) {
+
+ var DsysInfo DsystemInfoDB
+ err := json.Unmarshal(data, &DsysInfo)
+ if err != nil {
+ fmt.Println("Error unmarshaling JSON:", err)
+ return &DsysInfo, err
+ }
+
+ err = s.InsertRecord(&DsysInfo)
+ if err != nil {
+ return &DsysInfo, err
+ }
+
+ return &DsysInfo, err
+}
diff --git a/Model/SystemInfoDB_test.go b/Model/SystemInfoDB_test.go
deleted file mode 100644
index 4aee3df..0000000
--- a/Model/SystemInfoDB_test.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package Model
-
-import (
- "fmt"
- "github.com/stretchr/testify/assert"
- "testing"
-)
-
-type sqlite_master struct {
- Type string
- name string
- tbl_name string
- rootpage string
- sql string
-}
-
-func TestSystemInfoDB_createTable(t *testing.T) {
- tests := []struct {
- name string
- wantErr bool
- }{
- {name: "create DB test"},
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- var err error
- s := NewSystemInfoDB()
- s.createTable()
- if err != nil {
- t.Fatalf(s.dbName + " : DB를 생성할 수 없습니다. \n" + err.Error())
- }
-
- // ========== 검증 =============
- dbPtr, err := getDBPtr()
- if err != nil {
- t.Fatalf(s.dbName + " : DB 포인터를 가져올 수 없습니다. getDBPtr() 함수 오류\n" + err.Error())
- }
-
- query := fmt.Sprintf("select * from sqlite_master where name = '%s'", s.dbName)
-
- dsys := &sqlite_master{}
-
- rst := dbPtr.QueryRow(query).Scan(&dsys.Type, &dsys.name, &dsys.tbl_name, &dsys.rootpage, &dsys.sql)
- if rst != nil {
- t.Fatalf(s.dbName + " : 생성된 테이블이 존재하지 않습니다.")
- }
- assert.Equal(t, dsys.name, s.dbName)
-
- })
- }
-}
-
-func TestNewSystemInfoDB_selectRecord(t *testing.T) {
- type fields struct {
- dbName string
- }
- tests := []struct {
- name string
- fields fields
- wantErr bool
- }{
- {name: "Select Record in DB"},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- var err error
- s := NewSystemInfoDB()
-
- data, err := s.selectRecords()
-
- if err != nil {
- t.Fatalf(s.dbName + " : select 오류. Query 재 확인 \n" + err.Error())
- }
-
- assert.Equal(t, 1, len(data), "Row를 하나 이상 채우고 재시도를 하시오")
- fmt.Println("sql select result : \n", data)
-
- })
- }
-}
diff --git a/Model/db.go b/Model/db.go
index 1d33863..002e54b 100644
--- a/Model/db.go
+++ b/Model/db.go
@@ -3,6 +3,7 @@ package Model
import (
"database/sql"
"errors"
+ _ "modernc.org/sqlite"
"time"
)
@@ -15,6 +16,7 @@ db파일 : https://medium.com/@SlackBeck/golang-database-sql-패키지-삽질기
*/
func getDBPtr() (*sql.DB, error) {
dbPath := "file:db.db?cache=shared"
+ //dbPath := "db.db"
db, err := sql.Open("sqlite", dbPath)
if err != nil {
diff --git a/Model/nosqldb.go b/Model/nosqldb.go
new file mode 100644
index 0000000..aa77437
--- /dev/null
+++ b/Model/nosqldb.go
@@ -0,0 +1,55 @@
+package Model
+
+import (
+ "context"
+ "fmt"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "log"
+ "os"
+ "time"
+)
+
+// Chatgpt 이용함.
+/*
+MongoDB는 100개의 커넥션 풀을 지원한다.
+- 최대 풀 크기 50, 최소 풀 크기 10으로 설정.
+- 커넥션 최대 유휴 시간을 30초로 설정.
+*/
+func getCollectionPtr() (*mongo.Database, error) {
+ MONGOID := os.Getenv("MONGODBID")
+ MONGOPW := os.Getenv("MONGODBPW")
+ clientOptions := options.Client().
+ ApplyURI("mongodb://" + MONGOID + ":" + MONGOPW + "@uskawjdu.iptime.org:17017/"). // MongoDB URI
+ SetMaxPoolSize(50). // 최대 풀 크기
+ SetMinPoolSize(10). // 최소 풀 크기
+ SetMaxConnIdleTime(60 * time.Second) // 최대 유휴 시간
+ //fmt.Println("mongodb://" + MONGOID + ":" + MONGOPW + "@uskawjdu.iptime.org:17017/")
+ // 클라이언트 생성
+ client, err := mongo.NewClient(clientOptions)
+ if err != nil {
+ log.Fatal("Error creating MongoDB client: ", err)
+ return nil, err
+ }
+
+ // 연결 설정
+ ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
+ defer cancel()
+
+ // MongoDB에 연결
+ err = client.Connect(ctx)
+ if err != nil {
+ log.Fatal("Error connecting to MongoDB: ", err)
+ return nil, err
+ }
+
+ database := client.Database("httpsAgent")
+
+ err = client.Ping(context.TODO(), nil)
+ if err != nil {
+ return nil, fmt.Errorf("failed to connect to MongoDB: %v", err)
+ }
+
+ // 클라이언트 연결 반환
+ return database, nil
+}
diff --git a/Model/test.py b/Model/test.py
new file mode 100644
index 0000000..c973b34
--- /dev/null
+++ b/Model/test.py
@@ -0,0 +1,26 @@
+import requests
+import json
+
+# 요청할 URL
+url = 'http://127.0.0.1/postInstruction'
+
+# 전송할 데이터
+data = {
+ "agentUUID": "12342",
+ "procedureID": "P_Collection_Kimsuky_001",
+ "messageUUID": "f5556669-ffbe-4d24-b833-fc9888fdeaef"
+}
+
+# 헤더 설정
+headers = {
+ 'Content-Type': 'application/json'
+}
+
+# POST 요청 전송
+response = requests.post(url, headers=headers, data=json.dumps(data))
+
+# 응답 출력
+if response.status_code == 200:
+ print("Request succeeded:", response.json())
+else:
+ print(f"Request failed with status code {response.status_code}: {response.text}")
diff --git a/app.go b/app.go
deleted file mode 100644
index 31dfb69..0000000
--- a/app.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package main
-
-import (
- "github.com/gofiber/fiber/v3"
- "github.com/joho/godotenv"
- "log"
-)
-
-func main() {
- err := godotenv.Load()
- if err != nil {
- panic("Error loading .env file")
- }
-
- // Initialize a new Fiber app
- app := fiber.New()
-
- // Define a route for the GET method on the root path '/'
- app.Get("/", func(c fiber.Ctx) error {
- // Send a string response to the client
- return c.SendString("Hello, World 👋!")
- })
-
- // Start the server on port 3000
- log.Fatal(app.Listen(":3000"))
-
-}
diff --git a/db.db b/db.db
new file mode 100644
index 0000000..524d8d2
Binary files /dev/null and b/db.db differ
diff --git a/docs/docs.go b/docs/docs.go
new file mode 100644
index 0000000..d77a6a3
--- /dev/null
+++ b/docs/docs.go
@@ -0,0 +1,89 @@
+// Package docs Code generated by swaggo/swag. DO NOT EDIT
+package docs
+
+import "github.com/swaggo/swag"
+
+const docTemplate = `{
+ "schemes": {{ marshal .Schemes }},
+ "swagger": "2.0",
+ "info": {
+ "description": "{{escape .Description}}",
+ "title": "{{.Title}}",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "name": "API Support",
+ "url": "http://www.swagger.io/support",
+ "email": "support@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "version": "{{.Version}}"
+ },
+ "host": "{{.Host}}",
+ "basePath": "{{.BasePath}}",
+ "paths": {
+ "/api/postInst": {
+ "post": {
+ "description": "get struct array by ID",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "operationId": "get-struct-array2-by-string",
+ "parameters": [
+ {
+ "description": "request job",
+ "name": "loginUserRequest",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/router.InstructionD"
+ }
+ }
+ ],
+ "responses": {}
+ }
+ }
+ },
+ "definitions": {
+ "router.InstructionD": {
+ "type": "object",
+ "properties": {
+ "agentUUID": {
+ "type": "string",
+ "default": "09a4e53c7a1c4b4e9a519f36df29d8a2"
+ },
+ "messageUUID": {
+ "type": "string",
+ "default": "32a2833486414af9bc4596caef585538"
+ },
+ "procedureID": {
+ "type": "string",
+ "default": "P_DefenseEvasion_Kimsuky_001"
+ }
+ }
+ }
+ }
+}`
+
+// SwaggerInfo holds exported Swagger Info so clients can modify it
+var SwaggerInfo = &swag.Spec{
+ Version: "1.0",
+ Host: "localhost",
+ BasePath: "/",
+ Schemes: []string{},
+ Title: "Swagger Example API",
+ Description: "This is a sample server Petstore server.",
+ InfoInstanceName: "swagger",
+ SwaggerTemplate: docTemplate,
+ LeftDelim: "{{",
+ RightDelim: "}}",
+}
+
+func init() {
+ swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
+}
diff --git a/docs/swagger.json b/docs/swagger.json
new file mode 100644
index 0000000..a242eed
--- /dev/null
+++ b/docs/swagger.json
@@ -0,0 +1,65 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "description": "This is a sample server Petstore server.",
+ "title": "Swagger Example API",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "name": "API Support",
+ "url": "http://www.swagger.io/support",
+ "email": "support@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "version": "1.0"
+ },
+ "host": "localhost",
+ "basePath": "/",
+ "paths": {
+ "/api/postInst": {
+ "post": {
+ "description": "get struct array by ID",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "operationId": "get-struct-array2-by-string",
+ "parameters": [
+ {
+ "description": "request job",
+ "name": "loginUserRequest",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/router.InstructionD"
+ }
+ }
+ ],
+ "responses": {}
+ }
+ }
+ },
+ "definitions": {
+ "router.InstructionD": {
+ "type": "object",
+ "properties": {
+ "agentUUID": {
+ "type": "string",
+ "default": "09a4e53c7a1c4b4e9a519f36df29d8a2"
+ },
+ "messageUUID": {
+ "type": "string",
+ "default": "32a2833486414af9bc4596caef585538"
+ },
+ "procedureID": {
+ "type": "string",
+ "default": "P_DefenseEvasion_Kimsuky_001"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
new file mode 100644
index 0000000..c4627bb
--- /dev/null
+++ b/docs/swagger.yaml
@@ -0,0 +1,45 @@
+basePath: /
+definitions:
+ router.InstructionD:
+ properties:
+ agentUUID:
+ default: 09a4e53c7a1c4b4e9a519f36df29d8a2
+ type: string
+ messageUUID:
+ default: 32a2833486414af9bc4596caef585538
+ type: string
+ procedureID:
+ default: P_DefenseEvasion_Kimsuky_001
+ type: string
+ type: object
+host: localhost
+info:
+ contact:
+ email: support@swagger.io
+ name: API Support
+ url: http://www.swagger.io/support
+ description: This is a sample server Petstore server.
+ license:
+ name: Apache 2.0
+ url: http://www.apache.org/licenses/LICENSE-2.0.html
+ termsOfService: http://swagger.io/terms/
+ title: Swagger Example API
+ version: "1.0"
+paths:
+ /api/postInst:
+ post:
+ consumes:
+ - application/json
+ description: get struct array by ID
+ operationId: get-struct-array2-by-string
+ parameters:
+ - description: request job
+ in: body
+ name: loginUserRequest
+ required: true
+ schema:
+ $ref: '#/definitions/router.InstructionD'
+ produces:
+ - application/json
+ responses: {}
+swagger: "2.0"
diff --git a/go.mod b/go.mod
index 3ef6576..ea7746f 100644
--- a/go.mod
+++ b/go.mod
@@ -3,32 +3,61 @@ module github.com/your/repo
go 1.23.0
require (
+ github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.12
+ github.com/gin-gonic/gin v1.10.0
+ github.com/gofiber/fiber/v3 v3.0.0-beta.3
+ github.com/joho/godotenv v1.5.1
github.com/stretchr/testify v1.9.0
- github.com/yusufpapurcu/wmi v1.2.4
+ github.com/swaggo/files v1.0.1
+ github.com/swaggo/gin-swagger v1.6.0
+ github.com/swaggo/swag v1.16.3
+ go.mongodb.org/mongo-driver v1.16.1
+ gopkg.in/yaml.v2 v2.4.0
+ modernc.org/sqlite v1.33.0
)
require (
+ github.com/KyleBanks/depth v1.2.1 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/bytedance/sonic v1.12.2 // indirect
+ github.com/bytedance/sonic/loader v0.2.0 // indirect
+ github.com/cloudwego/base64x v0.1.4 // indirect
+ github.com/cloudwego/iasm v0.2.0 // indirect
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
- github.com/elastic/go-sysinfo v1.14.1 // indirect
- github.com/elastic/go-windows v1.0.0 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
- github.com/gofiber/fiber/v3 v3.0.0-beta.3 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.5 // indirect
+ github.com/gin-contrib/cors v1.3.0 // indirect
+ github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/go-openapi/jsonpointer v0.21.0 // indirect
+ github.com/go-openapi/jsonreference v0.21.0 // indirect
+ github.com/go-openapi/spec v0.21.0 // indirect
+ github.com/go-openapi/swag v0.23.0 // indirect
+ github.com/go-playground/locales v0.14.1 // indirect
+ github.com/go-playground/universal-translator v0.18.1 // indirect
+ github.com/go-playground/validator/v10 v10.22.1 // indirect
+ github.com/goccy/go-json v0.10.3 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.6 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
- github.com/joho/godotenv v1.5.1 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.9 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.8 // indirect
+ github.com/leodido/go-urn v1.4.0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
- github.com/pkg/errors v0.9.1 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.3 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+ github.com/rogpeppe/go-internal v1.12.0 // indirect
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+ github.com/ugorji/go/codec v1.2.12 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.55.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
@@ -36,18 +65,18 @@ require (
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
- go.mongodb.org/mongo-driver v1.16.1 // indirect
- golang.org/x/crypto v0.24.0 // indirect
- golang.org/x/sync v0.7.0 // indirect
- golang.org/x/sys v0.24.0 // indirect
- golang.org/x/text v0.16.0 // indirect
+ golang.org/x/arch v0.10.0 // indirect
+ golang.org/x/crypto v0.27.0 // indirect
+ golang.org/x/net v0.29.0 // indirect
+ golang.org/x/sync v0.8.0 // indirect
+ golang.org/x/sys v0.25.0 // indirect
+ golang.org/x/text v0.18.0 // indirect
+ golang.org/x/tools v0.25.0 // indirect
+ google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
- modernc.org/libc v1.55.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
- modernc.org/sqlite v1.32.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)
diff --git a/go.sum b/go.sum
index 11f3f48..52d77b5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,56 +1,146 @@
+github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.9 h1:LmGvK4r5RyPb3QaJ//3eqmmufu3W/aikssoWsmQLHhw=
+github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.9/go.mod h1:7Kv1PDaclTyg/VJ3xPahHfJiYF1GqXIWsbYlGKlUV2c=
+github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.11 h1:vHgJG5BhEyxfbNZzXw1DXyQh6x9OU5jIsSHcVRXH+cA=
+github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.11/go.mod h1:7Kv1PDaclTyg/VJ3xPahHfJiYF1GqXIWsbYlGKlUV2c=
+github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.12 h1:6PXYMZk1DCBQnbiasXXNj2My5p827wFyvP0QZX438Vw=
+github.com/HTTPs-omma/HTTPsBAS-HSProtocol v1.0.12/go.mod h1:7Kv1PDaclTyg/VJ3xPahHfJiYF1GqXIWsbYlGKlUV2c=
+github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
+github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
+github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=
+github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
+github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
+github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/elastic/go-sysinfo v1.14.1 h1:BpY/Utfz75oKSpsQnbAJmmlnT3gBV9WFsopBEYgjhZY=
-github.com/elastic/go-sysinfo v1.14.1/go.mod h1:FKUXnZWhnYI0ueO7jhsGV3uQJ5hiz8OqM5b3oGyaRr8=
-github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY=
-github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU=
-github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
-github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
+github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
+github.com/gin-contrib/cors v1.3.0 h1:PolezCc89peu+NgkIWt9OB01Kbzt6IP0J/JvkG6xxlg=
+github.com/gin-contrib/cors v1.3.0/go.mod h1:artPvLlhkF7oG06nK8v3U8TNz6IeX+w1uzCSEId5/Vc=
+github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw=
+github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
+github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
+github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
+github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
+github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
+github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
+github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
+github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
+github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg=
github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY=
github.com/gofiber/utils/v2 v2.0.0-beta.6 h1:ED62bOmpRXdgviPlfTmf0Q+AXzhaTUAFtdWjgx+XkYI=
github.com/gofiber/utils/v2 v2.0.0-beta.6/go.mod h1:3Kz8Px3jInKFvqxDzDeoSygwEOO+3uyubTmUa6PqY+0=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
+github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
+github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
+github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
-github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
+github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
+github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
+github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
+github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
+github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
@@ -66,64 +156,82 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
-github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8=
go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw=
+golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=
+golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
-golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
+golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
+golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
+golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
-golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
+golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
-golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
+golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
+golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
+gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
-howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
+modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
+modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
-modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
-modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
-modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s=
-modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA=
+modernc.org/sqlite v1.33.0 h1:WWkA/T2G17okiLGgKAj4/RMIvgyMT19yQ038160IeYk=
+modernc.org/sqlite v1.33.0/go.mod h1:9uQ9hF/pCZoYZK73D/ud5Z7cIRIILSZI8NdIemVMTX8=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..d6c1c6b
--- /dev/null
+++ b/main.go
@@ -0,0 +1,181 @@
+package main
+
+import (
+ "fmt"
+ "github.com/HTTPs-omma/HTTPsBAS-HSProtocol/HSProtocol"
+ cors2 "github.com/gin-contrib/cors"
+ "github.com/gin-gonic/gin"
+ "github.com/gofiber/fiber/v3"
+ "github.com/gofiber/fiber/v3/middleware/cors"
+ "github.com/joho/godotenv"
+ swaggerFiles "github.com/swaggo/files"
+ ginSwagger "github.com/swaggo/gin-swagger"
+ "github.com/your/repo/Core"
+ _ "github.com/your/repo/docs"
+ "github.com/your/repo/router"
+ "net"
+ "os"
+)
+
+// @title Swagger Example API
+// @version 1.0
+// @description This is a sample server Petstore server.
+// @termsOfService http://swagger.io/terms/
+// @contact.name API Support
+// @contact.url http://www.swagger.io/support
+// @contact.email support@swagger.io
+// @license.name Apache 2.0
+// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
+// @host localhost
+// @BasePath /
+// @Path api
+var testCommand string = "dir /"
+
+func main() {
+ err := godotenv.Load()
+ if err != nil {
+ panic("Error loading .env file")
+ }
+
+ if err != nil {
+ panic("큐 생성 에러")
+ }
+
+ // tcp
+ go TCPServer()
+
+ // Swagger
+ go Swagger()
+
+ // HTTP
+ HTTPServer()
+
+}
+
+// https://zzihyeon.tistory.com/76
+func Swagger() {
+ r := gin.Default()
+
+ // Swagger 엔드포인트
+ r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
+ r.Use(cors2.New(cors2.Config{
+ AllowOrigins: []string{"*"}, // 모든 도메인 허용, 보안 상 필요한 경우 특정 도메인만 허용해야 함
+ AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, // 허용할 HTTP 메서드
+ AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization", "Access-Control-Allow-Origin", "Connection", "Accept-Encoding"},
+ ExposeHeaders: []string{"Content-Length"},
+ AllowCredentials: true,
+ }))
+ r.Run("localhost:8000")
+
+}
+
+func TCPServer() {
+ listener, err := net.Listen("tcp", "localhost:8080")
+ if err != nil {
+ fmt.Println("Error starting TCP server:", err)
+ return
+ }
+ defer listener.Close()
+
+ fmt.Println("TCP server listening on port 8080")
+
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ fmt.Println("Error accepting connection:", err)
+ continue
+ }
+
+ go handleTCPConnection(conn)
+ }
+
+}
+
+func handleTCPConnection(conn net.Conn) {
+ defer conn.Close() // 함수 호출 종료 후 Close
+
+ buffer := make([]byte, 1024*1024)
+ for {
+ n, err := conn.Read(buffer)
+ if err != nil {
+ fmt.Println("Error reading from connection:", err)
+ break
+ }
+ if n < 1 {
+ continue
+ }
+
+ HSMgr := HSProtocol.NewHSProtocolManager()
+ hs, err := HSMgr.Parsing(buffer)
+ if err != nil {
+ fmt.Println("Error parsing:", err)
+ ack := &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ERROR_ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }
+ rstb, _ := HSMgr.ToBytes(ack)
+ conn.Write(rstb)
+ return
+ }
+
+ //fmt.Println("hs.uuid : ", hs.UUID)
+ dipt := Core.CommandDispatcher{}
+ ack, err := dipt.Action(hs)
+ if err != nil {
+ ack := &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ERROR_ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }
+ rstb, _ := HSMgr.ToBytes(ack)
+ fmt.Println(err)
+ conn.Write(rstb)
+ return
+ }
+ rstb, err := HSMgr.ToBytes(ack)
+ conn.Write(rstb)
+ return
+ }
+}
+
+func HTTPServer() {
+ app := fiber.New()
+ app.Get("/view/db", func(c fiber.Ctx) error {
+ // HTML 파일을 읽어서 응답으로 반환
+ htmlData, err := os.ReadFile("./view/html/viewdata.html")
+ if err != nil {
+ return c.Status(500).SendString("Error loading page")
+ }
+ c.Set("Content-Type", "text/html")
+ return c.Send(htmlData)
+ })
+
+ // 효과적인 Cors 에러 해결
+ //app.Use(cors.New(cors.Config{
+ // AllowCredentials: true,
+ // AllowOriginsFunc: func(origin string) bool { return true },
+ //}))
+ app.Use(cors.New(cors.Config{
+ AllowOrigins: []string{"*", "http://localhost/*"},
+ AllowHeaders: []string{"Origin", "Content-Type", "Accept"},
+ }))
+
+ router.SetupAPIRoutes(app)
+ router.SetupViewRoutes(app)
+
+ fmt.Println("HTTP server listening on port 80")
+ err := app.Listen(":80")
+ if err != nil {
+ fmt.Println("Error starting HTTP server:", err)
+ }
+
+}
diff --git a/router/api.go b/router/api.go
new file mode 100644
index 0000000..5d28433
--- /dev/null
+++ b/router/api.go
@@ -0,0 +1,109 @@
+package router
+
+import (
+ "fmt"
+ "github.com/HTTPs-omma/HTTPsBAS-HSProtocol/HSProtocol"
+ "github.com/gofiber/fiber/v3"
+ "github.com/your/repo/Core"
+ "github.com/your/repo/Model"
+ _ "github.com/your/repo/docs"
+ "time"
+)
+
+// swagger:parameters Request
+type InstructionD struct {
+ ProcedureID string `json:"procedureID" default:"P_DefenseEvasion_Kimsuky_001"`
+ AgentUUID string `json:"agentUUID" default:"09a4e53c7a1c4b4e9a519f36df29d8a2"`
+ MessageUUID string `json:"messageUUID" default:"32a2833486414af9bc4596caef585538"`
+}
+
+// @title ManagingServer API
+// @version 1.0
+// @description This is a sample server for the ManagingServer project.
+// @termsOfService http://managingserver.io/terms/
+// @contact.name ManagingServer API Support
+// @contact.url http://managingserver.io/support
+// @contact.email support@managingserver.io
+// @license.name Apache 2.0
+// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
+// @host localhost:80
+// @BasePath /
+// @Path /api
+func SetupAPIRoutes(app *fiber.App) {
+
+ app.Post("/api/checkInstReq", checkInstReq)
+ app.Post("/api/postInst", postInst)
+}
+
+func checkInstReq(ctx fiber.Ctx) error {
+ req := ctx.Body()
+ HSMgr := HSProtocol.NewHSProtocolManager()
+ hs, err := HSMgr.Parsing(req)
+ if err != nil {
+ fmt.Println(err)
+ ctx.Status(404)
+ return fmt.Errorf("Error parsing:", err)
+ }
+
+ //fmt.Println("hs.uuid : ", hs.UUID)
+ dipt := Core.CommandDispatcher{}
+ ack, err := dipt.Action(hs)
+ if err != nil {
+ ack := &HSProtocol.HS{ // HSProtocol.ACK
+ ProtocolID: hs.ProtocolID,
+ Command: HSProtocol.ERROR_ACK,
+ UUID: hs.UUID,
+ HealthStatus: hs.HealthStatus,
+ Identification: hs.Identification,
+ TotalLength: hs.TotalLength,
+ Data: []byte{},
+ }
+ rstb, _ := HSMgr.ToBytes(ack)
+ fmt.Println(err)
+ return ctx.Send(rstb)
+ }
+
+ rstb, err := HSMgr.ToBytes(ack)
+ return ctx.Send(rstb)
+}
+
+// postInst example
+//
+// @Description get struct array by ID
+// @ID get-struct-array2-by-string
+// @Accept json
+// @Produce json
+// @Param loginUserRequest body InstructionD true "request job"
+// @Router /api/postInst [post]
+func postInst(ctx fiber.Ctx) error {
+ // https://github.com/gofiber/fiber/issues/2958
+ InstD := new(InstructionD)
+ err := ctx.Bind().JSON(InstD)
+ if err != nil {
+ fmt.Println("Error marshaling to JSON:", err)
+ ctx.Status(404)
+ return ctx.Send([]byte(err.Error()))
+ }
+ jobdb, err := Model.NewJobDB()
+ if err != nil {
+ return ctx.Send([]byte(err.Error()))
+ }
+ //fmt.Println("test : ", InstD.ProcedureID, InstD.AgentUUID, InstD.MessageUUID)
+
+ err = jobdb.InsertJobData(&Model.JobData{
+ 0,
+ InstD.ProcedureID,
+ InstD.AgentUUID,
+ InstD.MessageUUID,
+ time.Now(),
+ })
+ if err != nil {
+ fmt.Println("Error inserting data:", err)
+ return fmt.Errorf("Error inserting data into job manager: %v", err)
+ }
+
+ ctx.Status(200)
+ return ctx.JSON(fiber.Map{
+ "status": true,
+ })
+}
diff --git a/router/view.go b/router/view.go
new file mode 100644
index 0000000..9550f4c
--- /dev/null
+++ b/router/view.go
@@ -0,0 +1,248 @@
+package router
+
+import (
+ "fmt"
+ "github.com/gofiber/fiber/v3"
+ "github.com/your/repo/Model"
+)
+
+// 통합 구조체 정의
+type CombinedData struct {
+ OperationLog []Model.OperationLogDocument `json:"operation_log"`
+ AgentStatus []Model.AgentStatusRecord `json:"agent_status"`
+ Application []Model.DapplicationDB `json:"application"`
+ JobData []Model.JobData `json:"job_data"`
+ SystemInfo []Model.DsystemInfoDB `json:"system_info"`
+}
+
+func SetupViewRoutes(app *fiber.App) {
+ app.Get("/combined-data", func(ctx fiber.Ctx) error {
+ dbOperationLog, err := Model.NewOperationLogDB()
+ if err != nil {
+ return ctx.Status(404).SendString("Error : " + err.Error())
+ }
+ // 모든 문서 조회
+ var dataOL []Model.OperationLogDocument
+ dataOL, err = dbOperationLog.SelectAllDocuments()
+ if err != nil {
+ //dataOL = make([]Model.OperationLogDocument, 0)
+ //fmt.Println("SelectAllDocuments Error : " + err.Error())
+ //return ctx.Status(404).SendString("Error : " + err.Error())
+ }
+
+ dbAgentStatus, err := Model.NewAgentStatusDB()
+ if err != nil {
+ return ctx.Status(404).SendString("Error : " + err.Error())
+ }
+ dataAS, err := dbAgentStatus.SelectAllRecords()
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ return ctx.Status(404).SendString("Error : " + err.Error())
+ }
+
+ appdb, err := Model.NewApplicationDB()
+ if err != nil {
+ return err
+ }
+ dataAPP, err := appdb.SelectAllRecords()
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ ctx.Status(404)
+ return ctx.SendString("Error : " + err.Error())
+ }
+
+ dbJob, err := Model.NewJobDB()
+ if err != nil {
+ return err
+ }
+ dataJD, err := dbJob.SelectAllJobData()
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ ctx.Status(404)
+ return ctx.SendString("Error : " + err.Error())
+ }
+
+ dbSysInfo, err := Model.NewSystemInfoDB()
+ if err != nil {
+ return err
+ }
+ dataSys, err := dbSysInfo.SelectAllRecords()
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ ctx.Status(404)
+ return ctx.SendString("Error : " + err.Error())
+ }
+
+ combined := CombinedData{
+ OperationLog: dataOL,
+ AgentStatus: dataAS,
+ Application: dataAPP,
+ JobData: dataJD,
+ SystemInfo: dataSys,
+ }
+
+ return ctx.JSON(combined)
+ })
+
+ // /view/OperationLogDB 라우트 정의
+ app.Get("/view/OperationLogDB", func(ctx fiber.Ctx) error {
+ db, err := Model.NewOperationLogDB()
+ if err != nil {
+ ctx.Status(500)
+ return ctx.SendString("Failed to connect to the database")
+ }
+
+ // 모든 문서 조회
+ datas, err := db.SelectAllDocuments()
+ if err != nil {
+ return ctx.Status(404).JSON(datas)
+ }
+
+ return ctx.Status(200).JSON(datas)
+ })
+
+ app.Get("/view/agentStatus", func(ctx fiber.Ctx) error {
+ db, err := Model.NewAgentStatusDB()
+ uuid := ctx.Params("uuid")
+ var datas []Model.AgentStatusRecord
+ if uuid != "" {
+ datas, err = db.SelectRecordByUUID(uuid)
+ } else {
+ datas, err = db.SelectAllRecords()
+ }
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ ctx.Status(404)
+ return ctx.Status(404).SendString("Error : " + err.Error())
+ }
+
+ return ctx.Status(200).JSON(datas)
+ })
+
+ app.Get("/view/ApplicationDB", func(ctx fiber.Ctx) error {
+ fmt.Println("ApplicationDB loging")
+ db, err := Model.NewApplicationDB()
+ if err != nil {
+ return err
+ }
+
+ uuid := ctx.Query("uuid")
+ var datas []Model.DapplicationDB
+ fmt.Println(uuid)
+ if uuid != "" {
+ datas, err = db.SelectRecordByUUID(uuid)
+ } else {
+ datas, err = db.SelectAllRecords()
+ }
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ return ctx.Status(404).JSON(datas)
+ }
+ return ctx.Status(200).JSON(datas)
+ })
+
+ app.Get("/view/SystemInfoDB", func(ctx fiber.Ctx) error {
+ //data := ctx.Body()
+ db, err := Model.NewSystemInfoDB()
+ if err != nil {
+ return err
+ }
+
+ uuid := ctx.Query("uuid")
+ var datas []Model.DsystemInfoDB
+ if uuid != "" {
+ datas, err = db.SelectRecordByUUID(uuid)
+ } else {
+ datas, err = db.SelectAllRecords()
+ }
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ return ctx.Status(404).JSON(datas)
+ }
+ return ctx.Status(200).JSON(datas)
+ })
+
+ app.Get("/view/JobDataDB", func(ctx fiber.Ctx) error {
+ db, err := Model.NewJobDB()
+ if err != nil {
+ return err
+ }
+ datas, err := db.SelectAllJobData()
+ if err != nil {
+ fmt.Println("Error selecting records:", err)
+ return ctx.Status(404).JSON(datas)
+ }
+ ctx.Status(200)
+ return ctx.JSON(datas)
+ })
+
+ app.Get("/deleted/JobDataDB", func(ctx fiber.Ctx) error {
+ db, err := Model.NewJobDB()
+ if err != nil {
+ return err
+ }
+ err = db.DeleteAllJobData()
+ if err != nil {
+ fmt.Println("Error Deleted records:", err)
+ ctx.Status(404)
+ return nil
+ }
+ return nil
+ })
+
+ app.Get("/deleted/OperationLog", func(ctx fiber.Ctx) error {
+ db, err := Model.NewOperationLogDB()
+ if err != nil {
+ return err
+ }
+ _, err = db.DeleteAllDocument()
+ if err != nil {
+ fmt.Println("Error Deleted records:", err)
+ ctx.Status(404)
+ return nil
+ }
+ return nil
+ })
+
+ app.Get("/deleted/SystemInfoDB", func(ctx fiber.Ctx) error {
+ db, err := Model.NewSystemInfoDB()
+ if err != nil {
+ return err
+ }
+ err = db.DeleteAllRecord()
+ if err != nil {
+ fmt.Println("Error Deleted records:", err)
+ ctx.Status(404)
+ return nil
+ }
+ return nil
+ })
+
+ app.Get("/deleted/ApplicationDB", func(ctx fiber.Ctx) error {
+ db, err := Model.NewApplicationDB()
+ if err != nil {
+ return err
+ }
+ err = db.DeleteAllRecords()
+ if err != nil {
+ fmt.Println("Error Deleted records:", err)
+ ctx.Status(404)
+ return nil
+ }
+ return nil
+ })
+
+ app.Get("/deleted/AgentStatusDB", func(ctx fiber.Ctx) error {
+ db, err := Model.NewAgentStatusDB()
+ if err != nil {
+ return err
+ }
+ err = db.DeleteAllRecord()
+ if err != nil {
+ fmt.Println("Error Deleted records:", err)
+ ctx.Status(404)
+ return nil
+ }
+ return nil
+ })
+}
diff --git a/view/html/viewdata.html b/view/html/viewdata.html
new file mode 100644
index 0000000..3543dba
--- /dev/null
+++ b/view/html/viewdata.html
@@ -0,0 +1,319 @@
+
+
+
+
+
+ Combined Data
+
+
+
+
+Combined Data Tables
+
+
+
+
Operation Log
+
+
+
+
+ | ID |
+ AgentUUID |
+ ProcedureID |
+ MessageUUID |
+ ConductAt |
+ ExitCode |
+ Log |
+ Command |
+
+
+
+
+
+
+
+
+
+
+
Agent Status
+
+
+
+
+ | ID |
+ UUID |
+ Status |
+ Protocol |
+ CreatedAt |
+ UpdatedAt |
+
+
+
+
+
+
+
+
+
+
+
Application
+
+
+
+
+ | ID |
+ AgentUUID |
+ Name |
+ Version |
+ Language |
+ Vendor |
+ InstallDate |
+ InstallLocation |
+ InstallSource |
+ PackageName |
+ PackageCode |
+ RegCompany |
+ RegOwner |
+ URLInfoAbout |
+ Description |
+ IsDeleted |
+ CreateAt |
+ UpdateAt |
+ DeletedAt |
+
+
+
+
+
+
+
+
+
+
+
Job Data
+
+
+
+
+ | ID |
+ ProcedureID |
+ AgentUUID |
+ MessageUUID |
+ CreatedAt |
+
+
+
+
+
+
+
+
+
+
+
System Info
+
+
+
+
+ | ID |
+ UUID |
+ HostName |
+ OsName |
+ OsVersion |
+ Family |
+ Architecture |
+ KernelVersion |
+ BootTime |
+ CreatedAt |
+ UpdatedAt |
+
+
+
+
+
+
+
+
+
+
+
+