all repos — felt @ 4ea3e656d687f901f5d30c56d9196e9b99077dcb

virtual tabletop for dungeons and dragons (and similar) using Go, MongoDB, and websockets

admin/admin.go (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package admin

import (
	"encoding/json"
	_ "fmt"
	"hacklab.nilfm.cc/felt/admin/util"
	"hacklab.nilfm.cc/felt/models"
	"hacklab.nilfm.cc/felt/mongodb"
	"hacklab.nilfm.cc/quartzgun/auth"
	. "hacklab.nilfm.cc/quartzgun/middleware"
	"hacklab.nilfm.cc/quartzgun/renderer"
	"hacklab.nilfm.cc/quartzgun/router"
	. "hacklab.nilfm.cc/quartzgun/util"
	"html/template"
	"net/http"
)

func apiGetTableList(next http.Handler, udb auth.UserStore) http.Handler {
	handlerFunc := func(w http.ResponseWriter, req *http.Request) {

		user := util.GetUserFromToken(req)
		self, err := util.GetTablesByUser(user, udb)
		if err != nil {
			w.WriteHeader(404)
		} else {
			AddContextValue(req, "tableList", self)
		}
		next.ServeHTTP(w, req)
	}

	return http.HandlerFunc(handlerFunc)
}

func apiGetTableData(next http.Handler, udb auth.UserStore, dbAdapter mongodb.DbAdapter) http.Handler {
	handlerFunc := func(w http.ResponseWriter, req *http.Request) {

		urlParams := req.Context().Value("params").(map[string]string)
		tableName := urlParams["Slug"]
		tableKey := models.TableKey{
			Name:     tableName,
			Passcode: req.FormValue("passcode"),
		}

		if dbAdapter.CheckTable(tableKey) {
			mapUrl, _ := dbAdapter.GetMapImageUrl(tableKey)
			auxMessage, _ := dbAdapter.GetAuxMessage(tableKey)
			availableTokens, _ := dbAdapter.GetTokens(tableKey, true)
			activeTokens, _ := dbAdapter.GetTokens(tableKey, false)
			diceRolls, _ := dbAdapter.GetDiceRolls(tableKey)

			AddContextValue(req, "tableData", models.Table{
				Name:            tableKey.Name,
				Passcode:        tableKey.Passcode,
				DiceRolls:       diceRolls,
				MapImageUrl:     mapUrl,
				Tokens:          activeTokens,
				AvailableTokens: availableTokens,
				AuxMessage:      auxMessage,
			})
		} else {
			w.WriteHeader(404)
		}

		next.ServeHTTP(w, req)
	}

	return http.HandlerFunc(handlerFunc)
}

func apiCreateTable(next http.Handler, udb auth.UserStore, dbAdapter mongodb.DbAdapter) http.Handler {
	handlerFunc := func(w http.ResponseWriter, req *http.Request) {
		tableKey := models.TableKey{}
		err := json.NewDecoder(req.Body).Decode(&tableKey)
		if err != nil {
			w.WriteHeader(400)
			next.ServeHTTP(w, req)
			return
		}

		// table name is primary key so w edon't need to check
		err = dbAdapter.CreateTable(tableKey)

		if err != nil {
			AddContextValue(req, "result", err.Error())
			// TODO: parse error and change the status
			w.WriteHeader(500)
		} else {
			user := util.GetUserFromToken(req)
			tables, err := util.GetTablesByUser(user, udb)
			tables = append(tables, tableKey)
			err = util.SetTablesForUser(user, tables, udb)
			if err != nil {
				w.WriteHeader(500)
			} else {
				w.WriteHeader(201)
			}
		}
		next.ServeHTTP(w, req)
	}

	return http.HandlerFunc(handlerFunc)
}

func apiDestroyTable(next http.Handler, udb auth.UserStore, dbAdapter mongodb.DbAdapter) http.Handler {
	handlerFunc := func(w http.ResponseWriter, req *http.Request) {
		// check table actually belongs to this user
		user := util.GetUserFromToken(req)
		tables, err := util.GetTablesByUser(user, udb)

		if err == nil {

			destroy := false
			i := 0

			table := models.TableKey{}
			err = json.NewDecoder(req.Body).Decode(&table)
			if err != nil {
				w.WriteHeader(400)
			}

			for j, t := range tables {
				if t.Name == table.Name && t.Passcode == table.Passcode {

					// try to destroy it
					destroy = dbAdapter.DestroyTable(table) == nil
					i = j
					break
				}
			}

			if destroy {
				newTables := append(tables[:i], tables[i+1:]...)
				util.SetTablesForUser(user, newTables, udb)
				w.WriteHeader(204)
			} else {
				w.WriteHeader(404)
			}

		} else {
			w.WriteHeader(500)
		}
		next.ServeHTTP(w, req)
	}

	return http.HandlerFunc(handlerFunc)
}

func apiUploadMapImg(next http.Handler, udb auth.UserStore, dbAdapter mongodb.DbAdapter) http.Handler {
	handlerFunc := func(w http.ResponseWriter, req *http.Request) {
		// ensure data storage dir exists
		// check for filename; call create to overwrite regardless
		// get file data from multipart form
		// write to file
		// respond with URL?
	}

	return handlerFunc
}

func CreateAdminInterface(udb auth.UserStore, dbAdapter mongodb.DbAdapter) http.Handler {
	// create quartzgun router
	rtr := &router.Router{Fallback: *template.Must(template.ParseFiles("static/error.html"))}

	scopes := map[string]string{}

	rtr.Post("/api/auth/", Provision(udb, 84))
	rtr.Get("/api/table/", Validate(apiGetTableList(renderer.JSON("tableList"), udb), udb, scopes))
	rtr.Get(`/api/table/(?P<Slug>\S+)`, Validate(apiGetTableData(renderer.JSON("tableData"), udb, dbAdapter), udb, scopes))
	rtr.Post("/api/table/", Validate(apiCreateTable(renderer.JSON("result"), udb, dbAdapter), udb, scopes))
	rtr.Delete(`/api/table/(?P<Slug>\S+)`, Validate(apiDestroyTable(renderer.JSON("result"), udb, dbAdapter), udb, scopes))

	return http.HandlerFunc(rtr.ServeHTTP)
}