diff --git a/dao/Factory.go b/dao/Factory.go index e3dc8b8..4ead2f4 100644 --- a/dao/Factory.go +++ b/dao/Factory.go @@ -7,6 +7,7 @@ import ( ) var userDAO IUserDAO +var channelDAO IChannelDAO var sessionDAO ISessionDAO func GetUserDAO() (IUserDAO, *util.ChatError) { @@ -22,6 +23,19 @@ func GetUserDAO() (IUserDAO, *util.ChatError) { return userDAO, nil } +func GetChannelDAO() (IChannelDAO, *util.ChatError) { + if !channelDAO.Ready() { + dao, err := postgres.MakeChannelDAO() + if err != nil { + return channelDAO, err + } + + channelDAO = dao + } + + return channelDAO, nil +} + func GetSessionDAO() (ISessionDAO, *util.ChatError) { if !sessionDAO.Ready() { dao, err := valkey.MakeUserDAO() diff --git a/dao/IChannelDAD.go b/dao/IChannelDAD.go new file mode 100644 index 0000000..7633d0d --- /dev/null +++ b/dao/IChannelDAD.go @@ -0,0 +1,15 @@ +package dao + +import ( + "git.tek.govt.hu/dowerx/chat/server/model" + "git.tek.govt.hu/dowerx/chat/server/util" +) + +type IChannelDAO interface { + IDAO + Create(channel model.Channel) *util.ChatError + Read(channel model.Channel) (model.Channel, *util.ChatError) + List() ([]model.Channel, *util.ChatError) + Update(channel model.Channel) *util.ChatError + Delete(channel model.Channel) *util.ChatError +} diff --git a/dao/postgres/ChannelDAO.go b/dao/postgres/ChannelDAO.go new file mode 100644 index 0000000..05f0dcd --- /dev/null +++ b/dao/postgres/ChannelDAO.go @@ -0,0 +1,87 @@ +package postgres + +import ( + "git.tek.govt.hu/dowerx/chat/server/model" + "git.tek.govt.hu/dowerx/chat/server/util" + "github.com/jmoiron/sqlx" +) + +type ChannelDAOPG struct { + pgDAO +} + +// Create a new channel +func (d ChannelDAOPG) Create(channel model.Channel) *util.ChatError { + _, err := d.db.NamedExec(`call add_channel(:name, :description)`, &channel) + return util.MakeError(err, util.DATABASE_QUERY_FAULT) +} + +// Read returns a channel by ID +func (d ChannelDAOPG) Read(channel model.Channel) (model.Channel, *util.ChatError) { + var rows *sqlx.Rows + var err error + rows, err = d.db.NamedQuery(`select * from "channel" where "id" = :id`, &channel) + if err != nil { + return channel, util.MakeError(err, util.DATABASE_QUERY_FAULT) + } + defer rows.Close() + + if !rows.Next() { + return channel, &util.ChatError{Message: "", Code: util.NOT_FOUND} + } + + err = rows.StructScan(&channel) + return channel, util.MakeError(err, util.DATABASE_QUERY_FAULT) +} + +// List all channels +func (d ChannelDAOPG) List() ([]model.Channel, *util.ChatError) { + rows, err := d.db.Queryx(`select * from "channel" order by "name"`) + if err != nil { + return nil, util.MakeError(err, util.DATABASE_QUERY_FAULT) + } + defer rows.Close() + + channels := make([]model.Channel, 0) + + for rows.Next() { + channel := model.Channel{} + + err = rows.StructScan(&channel) + if err != nil { + break + } + + channels = append(channels, channel) + } + + return channels, util.MakeError(err, util.DATABASE_QUERY_FAULT) +} + +// Update sets all the fields of the Channel with the given ID +func (d ChannelDAOPG) Update(channel model.Channel) *util.ChatError { + _, err := d.db.NamedExec(`update "channel" set "name" = :name, "description" = :description where "id" = :id`, &channel) + return util.MakeError(err, util.DATABASE_QUERY_FAULT) +} + +// Delete removes a channel by ID +func (d ChannelDAOPG) Delete(channel model.Channel) *util.ChatError { + var err error + _, err = d.db.NamedExec(`delete from "channel" where "id" = :id`, &channel) + return util.MakeError(err, util.DATABASE_QUERY_FAULT) +} + +func (d ChannelDAOPG) Ready() bool { + return d.db != nil +} + +func MakeChannelDAO() (ChannelDAOPG, *util.ChatError) { + dao := ChannelDAOPG{} + conn, err := getDatabase() + if err != nil { + return dao, err + } + + dao.db = conn + return dao, nil +} diff --git a/dao/postgres/UserDAO.go b/dao/postgres/UserDAO.go index 4d84fe8..c1402e8 100644 --- a/dao/postgres/UserDAO.go +++ b/dao/postgres/UserDAO.go @@ -32,7 +32,7 @@ func (d UserDAOPG) Read(user model.User) (model.User, *util.ChatError) { } if !rows.Next() { - return user, &util.ChatError{Message: "", Code: util.USER_NOT_FOUND} + return user, &util.ChatError{Message: "", Code: util.NOT_FOUND} } err = rows.StructScan(&user) diff --git a/model/Channel.go b/model/Channel.go index 80d4f48..16ab800 100644 --- a/model/Channel.go +++ b/model/Channel.go @@ -1,6 +1,7 @@ package model type Channel struct { - ID int - Name string + ID int `db:"id" json:"id"` + Name string `db:"name" json:"name"` + Description string `db:"description" json:"description"` } diff --git a/util/errors.go b/util/errors.go index 94e4d51..3caaa0a 100644 --- a/util/errors.go +++ b/util/errors.go @@ -13,7 +13,7 @@ const ( DATABASE_CONNECTION_FAULT DATABASE_QUERY_FAULT - USER_NOT_FOUND + NOT_FOUND WRONG_PASSWORD USERNAME_TOO_SHORT PASSWORD_TOO_SHORT @@ -24,7 +24,7 @@ var codeToMessage = map[ChatErrorCode]string{ GENERAL_ERROR: "an unexpected error occurred", DATABASE_CONNECTION_FAULT: "database connection failed", DATABASE_QUERY_FAULT: "database query failed", - USER_NOT_FOUND: "user not found", + NOT_FOUND: "item not found", WRONG_PASSWORD: "incorrect password", USERNAME_TOO_SHORT: "username is too short", PASSWORD_TOO_SHORT: "password is too short", @@ -58,7 +58,7 @@ func (e *ChatError) ErrorFromCode() string { // Status returns the http status of the error type func (e *ChatError) Status() int { switch e.Code { - case USER_NOT_FOUND: + case NOT_FOUND: fallthrough case WRONG_PASSWORD: fallthrough