add db function for user connections
This commit is contained in:
+66
-8
@@ -33,6 +33,15 @@ func DbInit(ctx context.Context) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = dbConn.Exec(ctx, `
|
||||||
|
CREATE TABLE IF NOT EXISTS user_connections (
|
||||||
|
requestor_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
recipient_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
is_accepted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
|
||||||
_, err = dbConn.Exec(ctx, `
|
_, err = dbConn.Exec(ctx, `
|
||||||
CREATE TABLE IF NOT EXISTS chat_groups (
|
CREATE TABLE IF NOT EXISTS chat_groups (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
@@ -63,9 +72,9 @@ func DbInit(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DbUserSaveWithoutGroups saves user in db without groups and sets its id
|
// DbUserSaveWithoutGroupsConnections saves user in db without groups and sets its id
|
||||||
// return: error if not successful
|
// return: error if not successful
|
||||||
func DbUserSaveWithoutGroups(ctx context.Context, user *User) error {
|
func DbUserSaveWithoutGroupsConnections(ctx context.Context, user *User) error {
|
||||||
err := dbConn.QueryRow(ctx, `
|
err := dbConn.QueryRow(ctx, `
|
||||||
INSERT INTO users (name, pass_hash, pronouns, color_red, color_green, color_blue, created_at)
|
INSERT INTO users (name, pass_hash, pronouns, color_red, color_green, color_blue, created_at)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
@@ -84,7 +93,7 @@ func DbUserDelete(ctx context.Context, id uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DbUserSetByName sets all fields of given struct with database's data using name
|
// DbUserSetByName sets all fields of given struct with database's data
|
||||||
// return: error if not successful
|
// return: error if not successful
|
||||||
func DbUserSetByName(ctx context.Context, user *User) error {
|
func DbUserSetByName(ctx context.Context, user *User) error {
|
||||||
err := dbConn.QueryRow(ctx, `
|
err := dbConn.QueryRow(ctx, `
|
||||||
@@ -93,12 +102,16 @@ func DbUserSetByName(ctx context.Context, user *User) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return DbUserSetGroups(ctx, user)
|
err = DbUserSetGroups(ctx, user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return DbUserSetConnections(ctx, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DbUserSetByIdWithoutGroups sets all fields of given struct with database's data using id, excluding groups
|
// DbUserSetByIdWithoutGroupsConnections sets all fields of given struct with database's data using id, excluding groups
|
||||||
// return: error if not successful
|
// return: error if not successful
|
||||||
func DbUserSetByIdWithoutGroups(ctx context.Context, user *User) error {
|
func DbUserSetByIdWithoutGroupsConnections(ctx context.Context, user *User) error {
|
||||||
err := dbConn.QueryRow(ctx, `
|
err := dbConn.QueryRow(ctx, `
|
||||||
SELECT name, pass_hash, pronouns, color_red, color_green, color_blue, created_at FROM users WHERE id = $1
|
SELECT name, pass_hash, pronouns, color_red, color_green, color_blue, created_at FROM users WHERE id = $1
|
||||||
`, user.Id).Scan(&user.Name, &user.PasswordHash, &user.Pronouns, &user.Color[0], &user.Color[1], &user.Color[2], &user.CreatedAt)
|
`, user.Id).Scan(&user.Name, &user.PasswordHash, &user.Pronouns, &user.Color[0], &user.Color[1], &user.Color[2], &user.CreatedAt)
|
||||||
@@ -108,11 +121,15 @@ func DbUserSetByIdWithoutGroups(ctx context.Context, user *User) error {
|
|||||||
// DbUserSetById sets all fields of given struct with database's data using id, including groups
|
// DbUserSetById sets all fields of given struct with database's data using id, including groups
|
||||||
// return: error if not successful
|
// return: error if not successful
|
||||||
func DbUserSetById(ctx context.Context, user *User) error {
|
func DbUserSetById(ctx context.Context, user *User) error {
|
||||||
err := DbUserSetByIdWithoutGroups(ctx, user)
|
err := DbUserSetByIdWithoutGroupsConnections(ctx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return DbUserSetGroups(ctx, user)
|
err = DbUserSetGroups(ctx, user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return DbUserSetConnections(ctx, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DbUserSetGroups populates user's Groups map with ids of all groups the user belongs to from database
|
// DbUserSetGroups populates user's Groups map with ids of all groups the user belongs to from database
|
||||||
@@ -137,6 +154,47 @@ func DbUserSetGroups(ctx context.Context, user *User) error {
|
|||||||
return rows.Err()
|
return rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DbUserSetConnections(ctx context.Context, user *User) error {
|
||||||
|
rows, err := dbConn.Query(ctx, `
|
||||||
|
SELECT requestor_id, recipient_id, is_accepted, created_at FROM user_connections WHERE requestor_id = $1 or recipient_id = $1
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
var (
|
||||||
|
requestorId uint32
|
||||||
|
recipientId uint32
|
||||||
|
isAccepted bool
|
||||||
|
createdAt time.Time
|
||||||
|
)
|
||||||
|
err = rows.Scan(&requestorId, &recipientId, &isAccepted, &createdAt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestorId == user.Id {
|
||||||
|
user.Connections[recipientId] = &Connection{
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
With: recipientId,
|
||||||
|
IsFromUser: true,
|
||||||
|
IsAccepted: isAccepted,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
user.Connections[requestorId] = &Connection{
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
With: requestorId,
|
||||||
|
IsFromUser: false,
|
||||||
|
IsAccepted: isAccepted,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// DbUserSetColor set user's color based on id
|
// DbUserSetColor set user's color based on id
|
||||||
// return: error if not successful
|
// return: error if not successful
|
||||||
func DbUserSetColor(ctx context.Context, user *User) error {
|
func DbUserSetColor(ctx context.Context, user *User) error {
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func HttpHandleUserNew(response http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
|
|
||||||
err = DbUserSaveWithoutGroups(ctx, newUser)
|
err = DbUserSaveWithoutGroupsConnections(ctx, newUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(response, "name taken", http.StatusUnauthorized)
|
http.Error(response, "name taken", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
@@ -199,6 +199,16 @@ func HttpHandleUserModifyAbout(response http.ResponseWriter, request *http.Reque
|
|||||||
response.WriteHeader(http.StatusAccepted)
|
response.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HttpHandleUserMessage(response http.ResponseWriter, request *http.Request) {
|
||||||
|
ctx := request.Context()
|
||||||
|
user, err := getUser(ctx, request.FormValue("token"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func HttpHandleNewToken(response http.ResponseWriter, request *http.Request) {
|
func HttpHandleNewToken(response http.ResponseWriter, request *http.Request) {
|
||||||
if !isMethodAllowed(&response, request) {
|
if !isMethodAllowed(&response, request) {
|
||||||
return
|
return
|
||||||
@@ -488,7 +498,7 @@ func HttpHandleGroupChangeOwner(response http.ResponseWriter, request *http.Requ
|
|||||||
response.WriteHeader(http.StatusAccepted)
|
response.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpHandleNewMessage(response http.ResponseWriter, request *http.Request) {
|
func HttpHandleGroupMessage(response http.ResponseWriter, request *http.Request) {
|
||||||
if !isMethodAllowed(&response, request) {
|
if !isMethodAllowed(&response, request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,16 +20,20 @@ func main() {
|
|||||||
http.HandleFunc("/new/user", withCORS(HttpHandleUserNew))
|
http.HandleFunc("/new/user", withCORS(HttpHandleUserNew))
|
||||||
http.HandleFunc("/new/token", withCORS(HttpHandleNewToken))
|
http.HandleFunc("/new/token", withCORS(HttpHandleNewToken))
|
||||||
http.HandleFunc("/new/group", withCORS(HttpHandeGroupCreate))
|
http.HandleFunc("/new/group", withCORS(HttpHandeGroupCreate))
|
||||||
http.HandleFunc("/new/message", withCORS(HttpHandleNewMessage))
|
|
||||||
http.HandleFunc("mod/user/appearence", withCORS(HttpHandleUserModifyAppearance))
|
http.HandleFunc("/mod/user/appearence", withCORS(HttpHandleUserModifyAppearance))
|
||||||
http.HandleFunc("mod/user/about", withCORS(HttpHandleUserModifyAbout))
|
http.HandleFunc("/mod/user/about", withCORS(HttpHandleUserModifyAbout))
|
||||||
http.HandleFunc("/mod/group/addusers", withCORS(HttpHandleGroupAddUser))
|
http.HandleFunc("/mod/group/addusers", withCORS(HttpHandleGroupAddUser))
|
||||||
http.HandleFunc("/mod/group/removeusers", withCORS(HttpHandleGroupRemoveUser))
|
http.HandleFunc("/mod/group/removeusers", withCORS(HttpHandleGroupRemoveUser))
|
||||||
http.HandleFunc("/mod/group/color", withCORS(HttpHandleGroupChangeColor))
|
http.HandleFunc("/mod/group/color", withCORS(HttpHandleGroupChangeColor))
|
||||||
http.HandleFunc("/mod/group/owner", withCORS(HttpHandleGroupChangeOwner))
|
http.HandleFunc("/mod/group/owner", withCORS(HttpHandleGroupChangeOwner))
|
||||||
|
|
||||||
http.HandleFunc("/get/groups", withCORS(HttpHandleGroupsGetWithoutMembers))
|
http.HandleFunc("/get/groups", withCORS(HttpHandleGroupsGetWithoutMembers))
|
||||||
|
|
||||||
http.HandleFunc("/get/group/members", withCORS(HttpHandleGroupMembersGet))
|
http.HandleFunc("/get/group/members", withCORS(HttpHandleGroupMembersGet))
|
||||||
http.HandleFunc("/del/group", withCORS(HttpHandleGroupDelete))
|
http.HandleFunc("/del/group", withCORS(HttpHandleGroupDelete))
|
||||||
|
|
||||||
|
http.HandleFunc("/msg/group", withCORS(HttpHandleGroupMessage))
|
||||||
http.HandleFunc("/ws", ServeWsConnection)
|
http.HandleFunc("/ws", ServeWsConnection)
|
||||||
|
|
||||||
log.Println("listening on :8080")
|
log.Println("listening on :8080")
|
||||||
|
|||||||
@@ -14,9 +14,17 @@ type User struct {
|
|||||||
WsConn *websocket.Conn
|
WsConn *websocket.Conn
|
||||||
Id uint32
|
Id uint32
|
||||||
Groups map[uint32]struct{}
|
Groups map[uint32]struct{}
|
||||||
|
Connections map[uint32]*Connection
|
||||||
Color [3]uint8
|
Color [3]uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Connection struct {
|
||||||
|
CreatedAt time.Time
|
||||||
|
With uint32
|
||||||
|
IsFromUser bool
|
||||||
|
IsAccepted bool
|
||||||
|
}
|
||||||
|
|
||||||
type Group struct {
|
type Group struct {
|
||||||
Name string
|
Name string
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
|
|||||||
+1
-1
@@ -138,7 +138,7 @@ func handleUnauthenticatedMessage(ctx context.Context, user *User, userMessage *
|
|||||||
userFromCache, err := CacheGetUserById(userId)
|
userFromCache, err := CacheGetUserById(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dbUser := &User{Id: userId}
|
dbUser := &User{Id: userId}
|
||||||
err = DbUserSetByIdWithoutGroups(ctx, dbUser)
|
err = DbUserSetByIdWithoutGroupsConnections(ctx, dbUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var msg = map[string]any{
|
var msg = map[string]any{
|
||||||
"from": "server",
|
"from": "server",
|
||||||
|
|||||||
Reference in New Issue
Block a user