You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
4.2 KiB
Go

// This package contains the database interface and an in memory implementation.
//
// For the in-memory implementation see the "NewInMemoryStore()" function.
package db
import (
"errors"
"fmt"
"sync"
"git.phc.dm.unipi.it/aziis98/posti-dm/server/util"
)
// ErrAlreadyExists is the error thrown from Store functions when an entity already exists.
var ErrAlreadyExists = errors.New(`object already exists in database`)
// ErrDoesntExist is the error thrown from Store functions when an entity doesn't exist.
var ErrDoesntExist = errors.New(`object doesn't exist in database`)
const (
PermissionAdmin = "admin"
PermissionModerator = "moderator"
)
// Entities
// type FrontendUser struct {
// Anonymous bool `json:"anonymous,omitempty"`
// ID string `json:"id,omitempty"`
// Permissions []string `json:"permissions,omitempty"`
// }
// User represents a user in the database.
type User struct {
ID string `json:"id"`
Permissions util.Set[string] `json:"permissions"`
// passwordSaltHash string
}
func (user User) UID() string {
return user.ID
}
// Room represents a room in the database, a room has an id, a name and a collection of seatIDs of this room.
type Room struct {
ID string `json:"id"`
SeatIDs []string `json:"seatIds"`
// gridRows, gridCols int
}
// Version 1:
//
// type SeatState struct {
// Occupied bool
// Anonymous bool
// UserID string
// }
// Version 2:
//
// type SeatState interface{ isSeatState() }
//
// type SeatNotOccupied struct{}
// type SeatOccupiedByUser struct{ UserID string }
// type SeatOccupiedByAnonymous struct{}
//
// func (s SeatNotOccupied) isSeatState()
// func (s SeatOccupiedByUser) isSeatState()
// func (s SeatOccupiedByAnonymous) isSeatState()
// Seat represents a seat in the database, it belongs to a single room and can be free or occupied by some user (referenced by userID).
type Seat struct {
ID string `json:"id"`
RoomID string `json:"roomId"`
// OccupiedBy is an empty list or a singleton of a userID
OccupiedBy []string `json:"occupiedBy"`
// x, y, w, h int
}
// type FrontendSeat struct {
// ID string `json:"id"`
// RoomID string `json:"roomId"`
// // OccupiedBy is an empty list or a singleton of a userID
// OccupiedBy *FrontendUser `json:"occupiedBy"`
// DiagramRect struct {
// X int `json:"x"`
// Y int `json:"y"`
// Width int `json:"width"`
// Height int `json:"height"`
// } `json:"diagramRect"`
// }
//
// Database Interfaces
//
// Database is the main interface for interacting with database implementations, for now the only implementation is "memDB".
type Database interface {
BeginTransaction()
EndTransaction()
CreateUser(user *User) error
CreateRoom(room *Room) error
CreateSeat(seat *Seat) error
DeleteUser(user *User) error
DeleteRoom(room *Room) error
DeleteSeat(seat *Seat) error
GetUser(userID string) (*User, error)
GetRoom(roomID string) (*Room, error)
GetSeat(seatID string) (*Seat, error)
GetRooms() ([]string, error)
GetRoomOccupiedSeats(roomID string) ([]string, error)
GetRoomFreeSeats(roomID string) ([]string, error)
GetUserSeats(userID string) (util.Set[string], error)
OccupySeat(seatID, userID string) error
FreeSeat(seatID string) error
}
// TODO: Create an SQLite implementation
// NewInMemoryStore creates an instance of memDB hidden behind the Store interface.
func NewInMemoryStore() Database {
db := &memDB{
&sync.Mutex{},
make(map[string]*User),
make(map[string]*Room),
make(map[string]*Seat),
}
db.rooms["aula-stud"] = &Room{
ID: "aula-stud",
SeatIDs: []string{},
}
for i := 1; i <= 11; i++ {
seatID := fmt.Sprintf(`aula-stud/posto-%d`, i)
db.rooms["aula-stud"].SeatIDs = append(db.rooms["aula-stud"].SeatIDs, seatID)
db.seats[seatID] = &Seat{
ID: seatID,
RoomID: "aula-stud",
OccupiedBy: []string{},
}
}
db.seats["aula-stud/posto-7"].OccupiedBy = []string{"aziis98"}
db.seats["aula-stud/posto-1"].OccupiedBy = []string{"bachoseven"}
db.users["aziis98"] = &User{
ID: "aziis98",
Permissions: util.NewSet(PermissionAdmin),
}
db.users["bachoseven"] = &User{
ID: "bachoseven",
Permissions: util.NewSet(PermissionAdmin),
}
return db
}