lishwist/core/group.go

138 lines
4.0 KiB
Go

package lishwist
import (
"fmt"
"lishwist/core/internal/db"
"strconv"
"strings"
)
type Group struct {
Id string
Name string
Reference string
Members []User
}
func (g *Group) MemberIndex(userId string) int {
for i, u := range g.Members {
if u.Id == userId {
return i
}
}
return -1
}
func queryManyGroups(query string, args ...any) ([]Group, error) {
groups := []Group{}
rows, err := db.Connection.Query(query, args...)
if err != nil {
return nil, fmt.Errorf("Query failed: %w", err)
}
defer rows.Close()
for rows.Next() {
var group Group
err := rows.Scan(&group.Id, &group.Name, &group.Reference)
if err != nil {
return nil, fmt.Errorf("Failed to scan row: %w", err)
}
members, err := queryManyGroupMembers(group.Id)
if err != nil {
return nil, fmt.Errorf("Failed to query for group members: %w", err)
}
group.Members = members
groups = append(groups, group)
}
err = rows.Err()
if err != nil {
return nil, fmt.Errorf("Rows error: %w", err)
}
return groups, nil
}
func queryOneGroup(query string, args ...any) (*Group, error) {
groups, err := queryManyGroups(query, args...)
if err != nil {
return nil, err
}
if len(groups) < 1 {
return nil, nil
}
return &groups[0], nil
}
func queryManyGroupMembers(groupId string) ([]User, error) {
query := "SELECT user.id, user.name, user.display_name, user.reference, user.is_admin, user.is_live, user.password_from_admin FROM v_user AS user JOIN group_member ON group_member.user_id = user.id JOIN [group] ON [group].id = group_member.group_id WHERE [group].id = ? ORDER BY group_member.user_id"
members, err := queryManyUsers(query, groupId)
if err != nil {
return members, err
}
return members, nil
}
func (s *Session) GetGroupByReference(reference string) (*Group, error) {
// FIXME: This function doesn't make much sense when there's already a public function to fetch any group, below
stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] JOIN group_member ON [group].id == group_member.group_id WHERE [group].reference = ? AND group_member.user_id = ?;"
return queryOneGroup(stmt, reference, s.User().Id)
}
func GetGroupByReference(reference string) (*Group, error) {
stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] WHERE [group].reference = ?;"
return queryOneGroup(stmt, reference)
}
func (a *Admin) ListGroups() ([]Group, error) {
query := "SELECT id, name, reference FROM [group];"
return queryManyGroups(query)
}
func (a *Admin) CreateGroup(name string, reference string) (*Group, error) {
name = strings.TrimSpace(name)
reference = strings.TrimSpace(reference)
stmt := "INSERT INTO [group] (name, reference) VALUES (?, ?)"
result, err := db.Connection.Exec(stmt, name, reference)
if err != nil {
return nil, err
}
id, err := result.LastInsertId()
if err != nil {
return nil, err
}
group := Group{
Id: strconv.FormatInt(id, 10),
Name: name,
Reference: reference,
}
recordEventCreateGroup(a.session.user.Id, group.Id)
return &group, nil
}
func (a *Admin) AddUserToGroup(userId, groupId string) error {
stmt := "INSERT INTO group_member (user_id, group_id) VALUES (?, ?)"
result, err := db.Connection.Exec(stmt, userId, groupId)
if err != nil {
return fmt.Errorf("query execution failed: %w", err)
}
id, err := result.LastInsertId()
if err != nil {
return fmt.Errorf("failed to get last insert id: %w", err)
}
recordEventCreateGroupMember(a.session.user.Id, strconv.FormatInt(id, 10))
return nil
}
func (a *Admin) RemoveUserFromGroup(userId, groupId string) error {
stmt := "DELETE FROM group_member WHERE group_id = ? AND user_id = ?"
_, err := db.Connection.Exec(stmt, userId, groupId)
if err != nil {
return err
}
return nil
}
// Get the groups the session user belongs to
func (u *Session) GetGroups() ([]Group, error) {
stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] JOIN group_member ON group_member.group_id = [group].id JOIN v_user AS user ON user.id = group_member.user_id WHERE user.id = ?"
return queryManyGroups(stmt, u.User().Id)
}