From 4bb4b04004f4c16c73984dcd03387d114d351eb4 Mon Sep 17 00:00:00 2001 From: lbenedar Date: Mon, 27 Apr 2026 13:14:17 +0300 Subject: [PATCH] add user and pass for world to env variables --- Makefile | 2 +- cmd/api/main.go | 19 ++++++-- internal/foundry/actions/session.go | 10 +++-- internal/foundry/actions/shutdown.go | 3 +- internal/foundry/foundry.go | 11 ++--- internal/foundry/transport/db.go | 31 +++++++------ internal/foundry/transport/errors.go | 1 + internal/foundry/transport/http.go | 7 +-- internal/foundry/transport/transport.go | 4 +- internal/foundry/transport/websocket.go | 59 ++++++++++++++++++++++++- internal/foundry/types/world.go | 50 +++++++++++++++++++++ 11 files changed, 161 insertions(+), 36 deletions(-) create mode 100644 internal/foundry/types/world.go diff --git a/Makefile b/Makefile index 6bfe3d2..f8f10ba 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -include .env api/run: - go run ./cmd/api -foundry_pass=${FOUNDRY_PASS} -foundry_host=${FOUNDRY_HOST} -port=${LISTEN_PORT} -env=development -log_level=${LOG_LEVEL} -db-dsn=${DB_DSN} -foundry-worlds=${FOUNDRY_WORLDS} + go run ./cmd/api -foundry_pass=${FOUNDRY_PASS} -foundry_host=${FOUNDRY_HOST} -port=${LISTEN_PORT} -env=development -log_level=${LOG_LEVEL} -db-dsn=${DB_DSN} -foundry-worlds=${FOUNDRY_WORLDS} -world-user=${WORLD_USER} -world-pass=${WORLD_PASS} db/migration/new: @echo 'Creating migration files for ${name}...' diff --git a/cmd/api/main.go b/cmd/api/main.go index 31b2465..59ddc8a 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -7,12 +7,12 @@ import ( "log/slog" "net/http/cookiejar" "os" - "strings" "time" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport" + "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "github.com/jmoiron/sqlx" _ "github.com/mattn/go-sqlite3" @@ -95,10 +95,19 @@ func (app *application) parseFlags() *transport.FoundryTransportData { flag.StringVar(&logLevelStr, "log_level", "info", "Password to connect to Foundry(debug|info|warn|error)") var worlds string - flag.StringVar(&worlds, "foundry-worlds", "", "Worlds that initialize in db on startup") + flag.StringVar(&worlds, "foundry-worlds", "", "Worlds that initialize in db on startup (format: \"test\", \"test1,test2,test3\", \"test1,test2,test3\")") + var users string + flag.StringVar(&users, "world-user", "", "Usernames to authenticate the world (format: \"test\", \"test1,test2,test3\", \"testForAll\")") + var passwords string + flag.StringVar(&passwords, "world-pass", "", "Passwords to authenticate the world (format: \"test\", \"test1,test2,test3\", \"testForAll\")") flag.Parse() - foundryTransportData.Worlds = strings.Split(worlds, ",") + worldsData, err := types.CreateWorldDataSlice(worlds, users, passwords) + if err != nil { + app.slogger.Warn("Got err on parsing authentication world data", "err", err) + return nil + } + foundryTransportData.Worlds = worldsData app.cfg.mode = service_mode(mode) @@ -120,6 +129,10 @@ func main() { app := application{foundryApp: &foundry.FoundryApi{}} foundryTransportData := app.parseFlags() + if foundryTransportData == nil { + return + } + jar, err := cookiejar.New(nil) if err != nil { app.slogger.Error("Error", "text", err.Error()) diff --git a/internal/foundry/actions/session.go b/internal/foundry/actions/session.go index 7e727d4..2baf282 100644 --- a/internal/foundry/actions/session.go +++ b/internal/foundry/actions/session.go @@ -22,8 +22,7 @@ func (msg WsSessionMsg) Action(tr *transport.FoundryTransport, status *types.Fou } tr.IsDbInit = true - go tr.FillDBWithFoundryData() - return nil + return tr.FillDBWithFoundryData() } func (msg WsSessionMsg) OnActiveWorld(tr *transport.FoundryTransport) error { @@ -32,7 +31,12 @@ func (msg WsSessionMsg) OnActiveWorld(tr *transport.FoundryTransport) error { return msg.HandleLoggedInUser(tr) } - err := tr.LogInToWorld() + userId, userPass, err := tr.GetUserIdAndPass() + if err != nil { + return err + } + + err = tr.LogInToWorld(userId, userPass) if err != nil { return err } diff --git a/internal/foundry/actions/shutdown.go b/internal/foundry/actions/shutdown.go index 0e63016..51e7585 100644 --- a/internal/foundry/actions/shutdown.go +++ b/internal/foundry/actions/shutdown.go @@ -25,6 +25,5 @@ func (msg WsShutdownMsg) Action(tr *transport.FoundryTransport, status *types.Fo } tr.IsDbInit = true - go tr.FillDBWithFoundryData() - return nil + return tr.FillDBWithFoundryData() } diff --git a/internal/foundry/foundry.go b/internal/foundry/foundry.go index fbc6635..95caf76 100644 --- a/internal/foundry/foundry.go +++ b/internal/foundry/foundry.go @@ -90,11 +90,12 @@ func (foundry *FoundryApi) ServeWebSocket() error { continue } - err = data.Action(foundry.Transport, &foundry.Status) - if err != nil { - wsChannels.Err() <- &types.FoundryError{Direction: types.ReaderCode, Err: err, Type: types.WebSocketCode} - continue - } + go func() { + err = data.Action(foundry.Transport, &foundry.Status) + if err != nil { + wsChannels.Err() <- &types.FoundryError{Direction: types.ReaderCode, Err: err, Type: types.WebSocketCode} + } + }() case types.RespDataCode: foundry.Transport.ExchangeChan.Msgs[message.Id] = make(chan []byte, 1) foundry.Transport.ExchangeChan.Msgs[message.Id] <- []byte(message.MsgJson) diff --git a/internal/foundry/transport/db.go b/internal/foundry/transport/db.go index 7514a37..903a223 100644 --- a/internal/foundry/transport/db.go +++ b/internal/foundry/transport/db.go @@ -10,30 +10,28 @@ import ( "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" ) -func (tr *FoundryTransport) FillDBWithFoundryData() { +func (tr *FoundryTransport) FillDBWithFoundryData() error { now := time.Now() setupExist, err := db.HasSetup(tr.DB) if err != nil { - tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} - return + return err } if !setupExist { err := tr.InsertSetupToDB() if err != nil { - tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} - return + return err } } err = tr.InitWorldsData() if err != nil { - tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} - return + return err } tr.Logger.Info("Initialization has been successful", "elapsed_time", time.Since(now).String()) + return nil } func (tr *FoundryTransport) InsertSetupToDB() error { @@ -66,8 +64,8 @@ func (tr *FoundryTransport) InitWorldsData() error { for i := range tr.InitWorlds { initWorld := tr.InitWorlds[i] - if !slices.Contains(worldNames, initWorld) { - tr.Logger.Warn("World name does not exist in database or have been already inserted. Skip!", "world_name", initWorld) + if !slices.Contains(worldNames, initWorld.Name) { + tr.Logger.Warn("World name does not exist in database or have been already inserted. Skip!", "world_name", initWorld.Name) continue } @@ -84,14 +82,21 @@ func (tr *FoundryTransport) InitWorldsData() error { return nil } -func (tr *FoundryTransport) InitWorldData(worldName string) error { - tr.Logger.Debug("Launching world...", "world_name", worldName) - err := tr.LaunchWorld(worldName) +func (tr *FoundryTransport) InitWorldData(worldData types.WorldData) error { + tr.Logger.Debug("Launching world...", "world_name", worldData.Name) + err := tr.LaunchWorld(worldData.Name) if err != nil { return err } - err = tr.ConnectToWorld() + if worldData.UserId == "" { + worldData.UserId, err = tr.GetUserId(worldData.Username) + if err != nil { + return err + } + } + + err = tr.ConnectToWorld(worldData.UserId, worldData.UserPass) if err != nil { return err } diff --git a/internal/foundry/transport/errors.go b/internal/foundry/transport/errors.go index f7189fe..c94f972 100644 --- a/internal/foundry/transport/errors.go +++ b/internal/foundry/transport/errors.go @@ -10,4 +10,5 @@ var ( ErrorAuthPassWrong = errors.New("Authentication password is wrong") ErrorChannelIsClosed = errors.New("Channel has been closed") ErrorUserIsNotConnected = errors.New("User is not connected") + ErrorUserDoesntExist = errors.New("User does not exist") ) diff --git a/internal/foundry/transport/http.go b/internal/foundry/transport/http.go index 5d0e5ea..251a977 100644 --- a/internal/foundry/transport/http.go +++ b/internal/foundry/transport/http.go @@ -85,7 +85,7 @@ func (tr *FoundryTransport) CheckAuthResponse(body io.Reader, respLength int) er return nil } -func (tr *FoundryTransport) LogInToWorld() error { +func (tr *FoundryTransport) LogInToWorld(userId string, userPass string) error { if tr.Http.SessionID == nil { err := tr.Http.GetSessionId() if err != nil { @@ -93,8 +93,7 @@ func (tr *FoundryTransport) LogInToWorld() error { } } - // TODO: make userid and password from tr object - resp, err := tr.Http.PostJoinWorld("YpMHZge0dxBZS5Cm", "") + resp, err := tr.Http.PostJoinWorld(userId, userPass) if err != nil { return err } @@ -106,8 +105,6 @@ func (tr *FoundryTransport) LogInToWorld() error { } return tr.CheckLoginResponse(resp.Body, contentLen) - - // {"userid":"YpMHZge0dxBZS5Cm","password":"","action":"join"} } func (tr *FoundryTransport) CheckLoginResponse(body io.Reader, respLength int) error { diff --git a/internal/foundry/transport/transport.go b/internal/foundry/transport/transport.go index 00068b3..f63bf41 100644 --- a/internal/foundry/transport/transport.go +++ b/internal/foundry/transport/transport.go @@ -29,7 +29,7 @@ type FoundryTransport struct { // Models *db.Models DB *sqlx.DB IsDbInit bool - InitWorlds []string + InitWorlds []types.WorldData Logger *slog.Logger } @@ -38,7 +38,7 @@ type FoundryTransportData struct { DbConn *sqlx.DB Logger *slog.Logger HttpConfig *requests.FoundryHttpRequest - Worlds []string + Worlds []types.WorldData } func NewFoundryTransport(data *FoundryTransportData) *FoundryTransport { diff --git a/internal/foundry/transport/websocket.go b/internal/foundry/transport/websocket.go index c1950aa..31100b6 100644 --- a/internal/foundry/transport/websocket.go +++ b/internal/foundry/transport/websocket.go @@ -1,11 +1,14 @@ package transport import ( + "encoding/json" "fmt" "net/http" "net/url" + "strings" "time" + json_models "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/json" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "github.com/gorilla/websocket" @@ -105,8 +108,8 @@ func (tr *FoundryTransport) ListenWebSocket() { } } -func (tr *FoundryTransport) ConnectToWorld() error { - err := tr.LogInToWorld() +func (tr *FoundryTransport) ConnectToWorld(userId string, userPass string) error { + err := tr.LogInToWorld(userId, userPass) if err != nil { return err } @@ -126,6 +129,58 @@ func (tr *FoundryTransport) ConnectToWorld() error { return nil } +func (tr *FoundryTransport) GetUserId(username string) (string, error) { + msgJson, err := tr.GetJsonDataByType(requests.JoinPath) + if err != nil { + return "", err + } + + var modelUsers []struct { + Users []json_models.User `json:"users"` + } + + err = json.Unmarshal(msgJson, &modelUsers) + if err != nil { + return "", err + } + + tr.Logger.Debug("User data", "msg in json format", modelUsers) + + users := modelUsers[0].Users + for i := range users { + if strings.EqualFold(users[i].Name, username) { + return users[i].ID, nil + } + } + + return "", ErrorUserDoesntExist +} + +func (tr *FoundryTransport) GetUserIdAndPass() (string, string, error) { + status, err := tr.Http.GetStatus() + if err != nil { + return "", "", err + } + + var worldData *types.WorldData + for i := range tr.InitWorlds { + if strings.EqualFold(tr.InitWorlds[i].Name, status.World) { + worldData = &tr.InitWorlds[i] + break + } + } + + if worldData == nil { + return "", "", err + } + + userId, err := tr.GetUserId(worldData.Username) + if err != nil { + return "", "", err + } + return userId, worldData.UserPass, nil +} + func (tr *FoundryTransport) SendOnlyCodeRequest(code string) error { tr.Logger.Debug("WS: Data has been send\n", "msg", types.CodesRespToReq[code]) diff --git a/internal/foundry/types/world.go b/internal/foundry/types/world.go new file mode 100644 index 0000000..a3fa609 --- /dev/null +++ b/internal/foundry/types/world.go @@ -0,0 +1,50 @@ +package types + +import ( + "errors" + "strings" +) + +var ( + ErrNoAuthWorldData = errors.New("You shold pass world data for initialization") + ErrWrongFormat = errors.New("You have passed data in wrong format. Please check it once again") +) + +type WorldData struct { + Name string + Username string + UserId string + UserPass string +} + +func CreateWorldDataSlice(worldFlag string, userFlag string, passFlag string) ([]WorldData, error) { + worlds := strings.Split(worldFlag, ",") + users := strings.Split(userFlag, ",") + passwords := strings.Split(passFlag, ",") + + if (len(worlds) == 1 && worlds[0] == "") || (len(users) == 1 && users[0] == "") { + return nil, ErrNoAuthWorldData + } + + worldLen := len(worlds) + userLen := len(users) + passLen := len(passwords) + + worldData := make([]WorldData, worldLen) + if worldLen == userLen && userLen == passLen { + for i := range worlds { + worldData[i].Name = worlds[i] + worldData[i].Username = users[i] + worldData[i].UserPass = passwords[i] + } + } else if worldLen != userLen && userLen == passLen && passLen == 1 { + for i := range worlds { + worldData[i].Name = worlds[i] + worldData[i].Username = users[0] + worldData[i].UserPass = passwords[0] + } + } else { + return nil, ErrWrongFormat + } + return worldData, nil +}