diff --git a/Readme.md b/Readme.md index 78901e4..59d5032 100644 --- a/Readme.md +++ b/Readme.md @@ -3,9 +3,9 @@ ## Goals - manage sessions - - [ ] login - - [ ] register - - [ ] logout + - [x] login + - [x] register + - [x] logout - edit users - [ ] status - [ ] bio diff --git a/api/user.go b/api/user.go index b24b2b0..077e040 100644 --- a/api/user.go +++ b/api/user.go @@ -1,6 +1,7 @@ package api import ( + "fmt" "net/http" "git.tek.govt.hu/dowerx/chat/server/controller" @@ -14,6 +15,7 @@ func userInfo(c *gin.Context) { userController, err := controller.MakeUserController() if err != nil { + fmt.Println(err.Error()) sendError(c, err) return } diff --git a/controller/AuthController.go b/controller/AuthController.go index cab5067..3e45983 100644 --- a/controller/AuthController.go +++ b/controller/AuthController.go @@ -6,14 +6,16 @@ import ( "git.tek.govt.hu/dowerx/chat/server/config" "git.tek.govt.hu/dowerx/chat/server/dao" + "git.tek.govt.hu/dowerx/chat/server/dao/postgres" + "git.tek.govt.hu/dowerx/chat/server/dao/valkey" "git.tek.govt.hu/dowerx/chat/server/model" "git.tek.govt.hu/dowerx/chat/server/util" "golang.org/x/crypto/bcrypt" ) type AuthController struct { - userDAO dao.IUserDAO - sessionDAO dao.ISessionDAO + UserDAO dao.IUserDAO + SessionDAO dao.ISessionDAO } const ( @@ -23,22 +25,6 @@ const ( TOKEN_LENGTH int = 32 ) -func (c *AuthController) init() *util.ChatError { - userDAO, err := dao.MakeUserDAO() - c.userDAO = userDAO - if err != nil { - return err - } - - sessionDao, err := dao.MakeSessionDAO() - c.sessionDAO = sessionDao - if err != nil { - return err - } - - return nil -} - func (c AuthController) Register(username string, password string, repeatPassword string) *util.ChatError { if len(username) < MIN_USERNAME_LENGTH { return &util.ChatError{Message: "", Code: util.USERNAME_TOO_SHORT} @@ -58,7 +44,7 @@ func (c AuthController) Register(username string, password string, repeatPasswor return util.MakeError(err, util.GENERAL_ERROR) } - return c.userDAO.Create(model.User{ + return c.UserDAO.Create(model.User{ Username: username, PasswordHash: string(hash), }) @@ -75,7 +61,7 @@ func generateToken(length int) (string, error) { } func (c AuthController) Login(username string, password string) (string, *util.ChatError) { - user, err := c.userDAO.Read(model.User{Username: username}) + user, err := c.UserDAO.Read(model.User{Username: username}) if err != nil { return "", err } @@ -89,12 +75,12 @@ func (c AuthController) Login(username string, password string) (string, *util.C return "", util.MakeError(err, util.GENERAL_ERROR) } - err = c.sessionDAO.DeleteAllByID(user.ID) + err = c.SessionDAO.DeleteAllByID(user.ID) if err != nil { return "", err } - err = c.sessionDAO.Set(token, user.ID) + err = c.SessionDAO.Set(token, user.ID) if err != nil { return "", err } @@ -103,9 +89,30 @@ func (c AuthController) Login(username string, password string) (string, *util.C } func (c AuthController) Logout(token string) *util.ChatError { - return c.sessionDAO.Delete(token) + return c.SessionDAO.Delete(token) } func (c AuthController) Bump(token string) *util.ChatError { - return c.sessionDAO.Bump(token, config.GetConfig().API.TokenLife) + return c.SessionDAO.Bump(token, config.GetConfig().API.TokenLife) +} + +func MakeAuthController() (AuthController, *util.ChatError) { + controller := AuthController{} + + userDAO := postgres.UserDAOPG{} + err := userDAO.Init() + if err != nil { + return controller, err + } + + sessionDAO := valkey.SessionDAOVK{} + err = sessionDAO.Init() + if err != nil { + return controller, err + } + + controller.UserDAO = userDAO + controller.SessionDAO = sessionDAO + + return controller, nil } diff --git a/controller/Factory.go b/controller/Factory.go deleted file mode 100644 index 9ea8190..0000000 --- a/controller/Factory.go +++ /dev/null @@ -1,15 +0,0 @@ -package controller - -import "git.tek.govt.hu/dowerx/chat/server/util" - -func MakeAuthController() (AuthController, *util.ChatError) { - authController := &AuthController{} - err := authController.init() - return *authController, err -} - -func MakeUserController() (UserController, *util.ChatError) { - userController := &UserController{} - err := userController.init() - return *userController, err -} diff --git a/controller/IController.go b/controller/IController.go deleted file mode 100644 index 9a95e64..0000000 --- a/controller/IController.go +++ /dev/null @@ -1,7 +0,0 @@ -package controller - -import "git.tek.govt.hu/dowerx/chat/server/util" - -type IController interface { - init() *util.ChatError -} diff --git a/controller/UserController.go b/controller/UserController.go index 8f137e1..0a4aa59 100644 --- a/controller/UserController.go +++ b/controller/UserController.go @@ -2,24 +2,29 @@ package controller import ( "git.tek.govt.hu/dowerx/chat/server/dao" + "git.tek.govt.hu/dowerx/chat/server/dao/postgres" "git.tek.govt.hu/dowerx/chat/server/model" "git.tek.govt.hu/dowerx/chat/server/util" ) type UserController struct { - userDAO dao.IUserDAO -} - -func (c *UserController) init() *util.ChatError { - userDAO, err := dao.MakeUserDAO() - c.userDAO = userDAO - if err != nil { - return err - } - - return nil + UserDAO dao.IUserDAO } func (c UserController) GetUser(username string) (model.User, *util.ChatError) { - return c.userDAO.Read(model.User{Username: username}) + return c.UserDAO.Read(model.User{Username: username}) +} + +func MakeUserController() (UserController, *util.ChatError) { + controller := UserController{} + + userDAO := postgres.UserDAOPG{} + err := userDAO.Init() + if err != nil { + return controller, err + } + + controller.UserDAO = userDAO + + return controller, nil } diff --git a/dao/Factory.go b/dao/Factory.go index 39d793f..e3dc8b8 100644 --- a/dao/Factory.go +++ b/dao/Factory.go @@ -6,14 +6,31 @@ import ( "git.tek.govt.hu/dowerx/chat/server/util" ) -func MakeUserDAO() (IUserDAO, *util.ChatError) { - dao := &postgres.UserDAOPG{} - err := dao.Init() - return dao, err +var userDAO IUserDAO +var sessionDAO ISessionDAO + +func GetUserDAO() (IUserDAO, *util.ChatError) { + if !userDAO.Ready() { + dao, err := postgres.MakeUserDAO() + if err != nil { + return userDAO, err + } + + userDAO = dao + } + + return userDAO, nil } -func MakeSessionDAO() (ISessionDAO, *util.ChatError) { - dao := &valkey.SessionDAOVK{} - err := dao.Init() - return dao, err +func GetSessionDAO() (ISessionDAO, *util.ChatError) { + if !sessionDAO.Ready() { + dao, err := valkey.MakeUserDAO() + if err != nil { + return sessionDAO, err + } + + sessionDAO = dao + } + + return sessionDAO, nil } diff --git a/dao/IDAO.go b/dao/IDAO.go index f2264cd..1c4c9b1 100644 --- a/dao/IDAO.go +++ b/dao/IDAO.go @@ -1,7 +1,5 @@ package dao -import "git.tek.govt.hu/dowerx/chat/server/util" - type IDAO interface { - Init() *util.ChatError + Ready() bool } diff --git a/dao/ISessionDAO.go b/dao/ISessionDAO.go index b632863..c2a8d27 100644 --- a/dao/ISessionDAO.go +++ b/dao/ISessionDAO.go @@ -3,6 +3,7 @@ package dao import "git.tek.govt.hu/dowerx/chat/server/util" type ISessionDAO interface { + IDAO Set(token string, id int) *util.ChatError Get(token string) (int, *util.ChatError) Delete(token string) *util.ChatError diff --git a/dao/IUserDAO.go b/dao/IUserDAO.go index 5879372..3b6c714 100644 --- a/dao/IUserDAO.go +++ b/dao/IUserDAO.go @@ -6,6 +6,7 @@ import ( ) type IUserDAO interface { + IDAO Create(user model.User) *util.ChatError Read(user model.User) (model.User, *util.ChatError) List() ([]model.User, *util.ChatError) diff --git a/dao/postgres/Connection.go b/dao/postgres/Connection.go index e55c19c..3cc7907 100644 --- a/dao/postgres/Connection.go +++ b/dao/postgres/Connection.go @@ -2,6 +2,7 @@ package postgres import ( "fmt" + "sync" "git.tek.govt.hu/dowerx/chat/server/config" "git.tek.govt.hu/dowerx/chat/server/util" @@ -10,16 +11,20 @@ import ( ) var db *sqlx.DB +var mu sync.Mutex func getDatabase() (*sqlx.DB, *util.ChatError) { + mu.Lock() if db == nil { cfg := config.GetConfig() newDB, err := sqlx.Connect("postgres", fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", cfg.Database.Host, cfg.Database.Port, cfg.Database.User, cfg.Database.Password, cfg.Database.DBname)) if err != nil { + mu.Unlock() return nil, util.MakeError(err, util.DATABASE_CONNECTION_FAULT) } db = newDB } + mu.Unlock() return db, nil } diff --git a/dao/postgres/UserDAO.go b/dao/postgres/UserDAO.go index 43c4f98..4d84fe8 100644 --- a/dao/postgres/UserDAO.go +++ b/dao/postgres/UserDAO.go @@ -25,6 +25,7 @@ func (d UserDAOPG) Read(user model.User) (model.User, *util.ChatError) { } else { rows, err = d.db.NamedQuery(`select * from "user" where "username" = :username`, &user) } + defer rows.Close() if err != nil { return user, util.MakeError(err, util.DATABASE_QUERY_FAULT) @@ -44,6 +45,7 @@ func (d UserDAOPG) List() ([]model.User, *util.ChatError) { if err != nil { return nil, util.MakeError(err, util.DATABASE_QUERY_FAULT) } + defer rows.Close() users := make([]model.User, 0) @@ -78,3 +80,18 @@ func (d UserDAOPG) Delete(user model.User) *util.ChatError { return util.MakeError(err, util.DATABASE_QUERY_FAULT) } + +func (d UserDAOPG) Ready() bool { + return d.db != nil +} + +func MakeUserDAO() (UserDAOPG, *util.ChatError) { + dao := UserDAOPG{} + conn, err := getDatabase() + if err != nil { + return dao, err + } + + dao.db = conn + return dao, nil +} diff --git a/dao/valkey/Connection.go b/dao/valkey/Connection.go index d721952..19053c5 100644 --- a/dao/valkey/Connection.go +++ b/dao/valkey/Connection.go @@ -1,19 +1,25 @@ package valkey import ( + "sync" + "git.tek.govt.hu/dowerx/chat/server/config" "git.tek.govt.hu/dowerx/chat/server/util" "github.com/valkey-io/valkey-go" ) var vk valkey.Client = nil +var mu sync.Mutex func getClient() (*valkey.Client, *util.ChatError) { + mu.Lock() if vk == nil { client, err := valkey.NewClient(config.GetConfig().Valkey) vk = client + mu.Unlock() return &vk, util.MakeError(err, util.DATABASE_CONNECTION_FAULT) } + mu.Unlock() return &vk, nil } diff --git a/dao/valkey/SessionDAO.go b/dao/valkey/SessionDAO.go index bd20476..33d2e89 100644 --- a/dao/valkey/SessionDAO.go +++ b/dao/valkey/SessionDAO.go @@ -88,3 +88,18 @@ func (d SessionDAOVK) Bump(token string, time int) *util.ChatError { cmd := (*d.vk).B().Expire().Key(SESSION_PREFIX + token).Seconds(int64(time)).Build() return util.MakeError((*d.vk).Do(context.Background(), cmd).Error(), util.DATABASE_QUERY_FAULT) } + +func (d SessionDAOVK) Ready() bool { + return d.vk != nil +} + +func MakeUserDAO() (SessionDAOVK, *util.ChatError) { + dao := SessionDAOVK{} + conn, err := getClient() + if err != nil { + return dao, err + } + + dao.vk = conn + return dao, nil +}