Expand server and invite management, expose invite logs
This commit is contained in:
parent
c15f3f70ab
commit
7f7a601a49
8
main.go
8
main.go
|
@ -25,15 +25,19 @@ func main() {
|
|||
// API endpoints
|
||||
mux.Group(func(mux *flow.Mux) {
|
||||
mux.Use(handlers.Cors)
|
||||
mux.HandleFunc("/api/v1/invite/:id", handlers.GetInvite, "GET", "DELETE")
|
||||
mux.HandleFunc("/api/v1/invite/:id", handlers.GetInvite, "GET")
|
||||
|
||||
mux.Use(handlers.SessionAuth)
|
||||
mux.HandleFunc("/api/v1/me", handlers.CurrentUser, "GET")
|
||||
|
||||
mux.HandleFunc("/api/v1/invites", handlers.CreateInvite, "POST")
|
||||
mux.HandleFunc("/api/v1/invite/:id/accept", handlers.AcceptInvite, "POST")
|
||||
mux.HandleFunc("/api/v1/invite/:id/log", handlers.InviteLog, "GET")
|
||||
mux.HandleFunc("/api/v1/invite/:id", handlers.DeleteInvite, "DELETE")
|
||||
|
||||
mux.HandleFunc("/api/v1/servers", handlers.Server, "GET", "POST")
|
||||
mux.HandleFunc("/api/v1/servers", handlers.Servers, "GET", "POST")
|
||||
mux.HandleFunc("/api/v1/server/:id", handlers.Server, "GET", "DELETE")
|
||||
mux.HandleFunc("/api/v1/server/:id/invites", handlers.ServerInvites, "GET")
|
||||
})
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -26,8 +26,10 @@ type Storer interface {
|
|||
GetServer(id string) (Server, error)
|
||||
SaveServer(server Server) error
|
||||
GetUserServers(user User) ([]Server, error)
|
||||
DeleteServer(server Server, user User) error
|
||||
LogInviteUse(user string, invite Invite) error
|
||||
InviteLog(invite Invite) ([]InviteLog, error)
|
||||
DeleteInvite(invite Invite) error
|
||||
GetUser(uid string) (User, error)
|
||||
SaveUser(user User) error
|
||||
SaveSession(token string, user User) error
|
||||
|
@ -35,6 +37,7 @@ type Storer interface {
|
|||
SaveOauthState(state OauthState) error
|
||||
OauthState(id string) (OauthState, error)
|
||||
Close() error
|
||||
ServerInvites(server Server) ([]Invite, error)
|
||||
}
|
||||
|
||||
type OauthState struct {
|
||||
|
@ -78,6 +81,12 @@ type Session struct {
|
|||
Expiry time.Time
|
||||
}
|
||||
|
||||
type InviteLog struct {
|
||||
EntryID string `json:"entry_id"`
|
||||
Invite Invite `json:"invite"`
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
func Open() (*Store, error) {
|
||||
database := os.Getenv("WLM_DATABASE_PATH")
|
||||
if database == "" {
|
||||
|
@ -165,12 +174,6 @@ func (s *Store) LogInviteUse(user string, invite Invite) error {
|
|||
return err
|
||||
}
|
||||
|
||||
type InviteLog struct {
|
||||
EntryID string
|
||||
Invite string
|
||||
User string
|
||||
}
|
||||
|
||||
func (s *Store) InviteLog(invite Invite) ([]InviteLog, error) {
|
||||
q, err := s.database.Query("SELECT * FROM invite_log WHERE invite=$1", invite.Token)
|
||||
if err != nil {
|
||||
|
@ -180,10 +183,15 @@ func (s *Store) InviteLog(invite Invite) ([]InviteLog, error) {
|
|||
var log []InviteLog
|
||||
for q.Next() {
|
||||
var logEntry InviteLog
|
||||
err := q.Scan(&logEntry.EntryID, &logEntry.Invite, &logEntry.User)
|
||||
err := q.Scan(&logEntry.EntryID, &logEntry.Invite.Token, &logEntry.User.Id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
user, err := s.GetUser(logEntry.User.Id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
logEntry.User = user
|
||||
log = append(log, logEntry)
|
||||
}
|
||||
|
||||
|
@ -354,3 +362,62 @@ func (s *Store) OauthState(id string) (OauthState, error) {
|
|||
func (s *Store) Close() error {
|
||||
return s.database.Close()
|
||||
}
|
||||
|
||||
func (s *Store) ServerInvites(server Server) ([]Invite, error) {
|
||||
q, err := s.database.Query("SELECT * FROM invites WHERE server=$1", server.Id)
|
||||
if err != nil {
|
||||
return []Invite{}, err
|
||||
}
|
||||
var invites []Invite
|
||||
for q.Next() {
|
||||
var invite Invite
|
||||
err = q.Scan(&invite.Token, &invite.Creator.Id, &invite.Server.Id, &invite.Uses, &invite.Unlimited)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
invites = append(invites, invite)
|
||||
}
|
||||
|
||||
return invites, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteInvite(invite Invite) error {
|
||||
inviteDeleteQuery, err := s.database.Prepare("DELETE FROM invites WHERE token=$1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.database.Exec("DELETE FROM invite_log WHERE invite=$1", invite.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = inviteDeleteQuery.Exec(invite.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteServer(server Server, user User) error {
|
||||
serverDeleteQuery, err := s.database.Prepare("DELETE FROM servers WHERE id=$1 AND owner=$2")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverInvites, err := s.ServerInvites(server)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, invite := range serverInvites {
|
||||
err = s.DeleteInvite(invite)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
_, err = serverDeleteQuery.Exec(server.Id, user.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -29,10 +29,16 @@ type Handle interface {
|
|||
CurrentUser(w http.ResponseWriter, r *http.Request)
|
||||
CreateInvite(w http.ResponseWriter, r *http.Request)
|
||||
GetInvite(w http.ResponseWriter, r *http.Request)
|
||||
DeleteInvite(w http.ResponseWriter, r *http.Request)
|
||||
AcceptInvite(w http.ResponseWriter, r *http.Request)
|
||||
AuthRedirect(w http.ResponseWriter, r *http.Request)
|
||||
AuthCallback(w http.ResponseWriter, r *http.Request)
|
||||
Server(w http.ResponseWriter, r *http.Request)
|
||||
Servers(w http.ResponseWriter, r *http.Request)
|
||||
CreateServer(w http.ResponseWriter, r *http.Request)
|
||||
DeleteServer(w http.ResponseWriter, r *http.Request)
|
||||
ServerInvites(w http.ResponseWriter, r *http.Request)
|
||||
InviteLog(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
func New(store store.Storer) *Handler {
|
||||
|
@ -239,7 +245,7 @@ func generateSessionToken() (string, error) {
|
|||
return base64.URLEncoding.EncodeToString(b), err
|
||||
}
|
||||
|
||||
func (h *Handler) Server(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *Handler) Servers(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value("user").(store.User)
|
||||
if r.Method == http.MethodGet {
|
||||
servers, err := h.store.GetUserServers(user)
|
||||
|
@ -268,6 +274,49 @@ func (h *Handler) Server(w http.ResponseWriter, r *http.Request) {
|
|||
fmt.Fprintf(w, "created server %s", server.Id)
|
||||
}
|
||||
|
||||
func (h *Handler) Server(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value("user").(store.User)
|
||||
serverId := flow.Param(r.Context(), "id")
|
||||
if r.Method == http.MethodGet {
|
||||
server, err := h.store.GetServer(serverId)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if server.Owner.Id != user.Id {
|
||||
http.Error(w, "not owner of server", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(server)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodDelete {
|
||||
serverId := flow.Param(r.Context(), "id")
|
||||
user := r.Context().Value("user").(store.User)
|
||||
server, err := h.store.GetServer(serverId)
|
||||
if err != nil {
|
||||
http.Error(w, "no such server", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if server.Owner.Id != user.Id {
|
||||
http.Error(w, "user not server owner", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.store.DeleteServer(server, user)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte("deleted"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (h *Handler) CurrentUser(w http.ResponseWriter, r *http.Request) {
|
||||
value := r.Context().Value("user")
|
||||
if value == nil {
|
||||
|
@ -277,3 +326,72 @@ func (h *Handler) CurrentUser(w http.ResponseWriter, r *http.Request) {
|
|||
user := value.(store.User)
|
||||
w.Write([]byte(user.DisplayName))
|
||||
}
|
||||
|
||||
func (h *Handler) ServerInvites(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value("user").(store.User)
|
||||
serverId := flow.Param(r.Context(), "id")
|
||||
server, err := h.store.GetServer(serverId)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if server.Owner.Id != user.Id {
|
||||
http.Error(w, "not owner of server", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
serverInvites, err := h.store.ServerInvites(server)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if server.Owner.Id != user.Id {
|
||||
http.Error(w, "not owner of server", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(serverInvites)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *Handler) InviteLog(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value("user").(store.User)
|
||||
inviteToken := flow.Param(r.Context(), "id")
|
||||
invite, err := h.store.GetInvite(inviteToken)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if invite.Creator.Id != user.Id {
|
||||
http.Error(w, "not owner of invite", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
logs, err := h.store.InviteLog(invite)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(logs)
|
||||
}
|
||||
|
||||
func (h *Handler) DeleteInvite(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value("user").(store.User)
|
||||
inviteToken := flow.Param(r.Context(), "id")
|
||||
invite, err := h.store.GetInvite(inviteToken)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if invite.Creator.Id != user.Id {
|
||||
http.Error(w, "not owner of invite", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.store.DeleteInvite(invite)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write([]byte("deleted"))
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue