package main import ( "fmt" "net/http" "git.phc.dm.unipi.it/aziis98/posti-dm/server/auth" "git.phc.dm.unipi.it/aziis98/posti-dm/server/db" "git.phc.dm.unipi.it/aziis98/posti-dm/server/httputil" "git.phc.dm.unipi.it/aziis98/posti-dm/server/httputil/serverevents" "git.phc.dm.unipi.it/aziis98/posti-dm/server/util" "github.com/alecthomas/repr" "github.com/go-chi/chi/v5" ) type Server struct { authService *auth.AuthService roomServerEventStreams map[string]serverevents.Handler Database db.Store ApiRoute chi.Router } func NewServer() *Server { sessions := make(map[string]*db.User) database := db.NewInMemoryStore() server := &Server{ Database: database, authService: &auth.AuthService{ CheckUserPassword: func(userID, password string) error { if password != "phc" { return fmt.Errorf(`invalid password`) } // FIXME: al momento quando la password รจ giusta creiamo tutti gli account necessari database.CreateUser(&db.User{ ID: userID, Permissions: []string{}, }) return nil }, UserPermissions: func(userID string) ([]string, error) { user, err := database.GetUser(userID) if err != nil { return nil, err } return user.Permissions, nil }, SessionTokenFromUser: func(userID string) (string, error) { user, err := database.GetUser(userID) if err != nil { return "", err } token := util.RandomHash(10) sessions[token] = user repr.Println("Sessions: ", sessions) return token, nil }, UserFromSessionToken: func(session string) (string, error) { user, present := sessions[session] if !present { return "", auth.ErrNoUserForSession } return user.ID, nil }, AuthenticationFailed: func(err error) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusUnauthorized) }) }, OtherError: func(err error) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) }) }, }, roomServerEventStreams: make(map[string]serverevents.Handler), ApiRoute: chi.NewRouter(), } roomIDs, _ := database.GetRooms() for _, roomID := range roomIDs { server.roomServerEventStreams[roomID] = serverevents.New(&serverevents.Config{ Connected: func(client chan string) { server.ConnectedToRoom(roomID, client) }, }) } server.setupRoutes() return server } func (server *Server) setupRoutes() { api := server.ApiRoute database := server.Database // Authenticated Routes api.Post("/login", func(w http.ResponseWriter, r *http.Request) { var credentials struct { Username string `json:"username"` Password string `json:"password"` } if err := httputil.ReadJSON(r, &credentials); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } server.authService.Login(w, r, credentials.Username, credentials.Password) }) api.With(server.authService.LoggedMiddleware()). Post("/logout", func(w http.ResponseWriter, r *http.Request) { server.authService.Logout(w) }) api.Get("/user", func(w http.ResponseWriter, r *http.Request) { userID, err := server.authService.UserFromSession(r) if err != nil { httputil.WriteJSON(w, nil) return } user, err := database.GetUser(userID) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) } httputil.WriteJSON(w, user) }) api.Get("/room/seats", func(w http.ResponseWriter, r *http.Request) { roomID, ok := r.URL.Query()["id"] if !ok { http.Error(w, `missing room id`, http.StatusBadRequest) } room, err := database.GetRoom(roomID[0]) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } seats := []*db.Seat{} for _, seatID := range room.SeatIDs { seat, err := database.GetSeat(seatID) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } seats = append(seats, seat) } httputil.WriteJSON(w, seats) }) api.HandleFunc("/room_events", func(w http.ResponseWriter, r *http.Request) { roomID, ok := r.URL.Query()["id"] if !ok { http.Error(w, `missing room id`, http.StatusBadRequest) return } server.roomServerEventStreams[roomID[0]].ServeHTTP(w, r) }) api.With(server.authService.LoggedMiddleware()). Post("/seat/occupy", func(w http.ResponseWriter, r *http.Request) { userID, err := server.authService.UserFromSession(r) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } seatID, ok := r.URL.Query()["id"] if !ok { http.Error(w, `missing seat id`, http.StatusBadRequest) return } seat, err := database.GetSeat(seatID[0]) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } repr.Println(userID, seatID) if err := database.OccupySeat(seatID[0], userID); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } server.roomServerEventStreams[seat.RoomID].Broadcast("refresh") httputil.WriteJSON(w, "ok") }) api.With(server.authService.LoggedMiddleware()). Post("/seat/leave", func(w http.ResponseWriter, r *http.Request) { seatID, ok := r.URL.Query()["id"] if !ok { http.Error(w, `missing seat id`, http.StatusBadRequest) return } seat, err := database.GetSeat(seatID[0]) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } if err := database.FreeSeat(seatID[0]); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } server.roomServerEventStreams[seat.RoomID].Broadcast("refresh") httputil.WriteJSON(w, "ok") }) } func (server *Server) ConnectedToRoom(roomID string, client chan string) { // go func() { // for { // client <- "hi from server!" // time.Sleep(1 * time.Second) // } // }() }