all repos — felt @ b125b3c3ec48c60e783345994b3a1a8ac58f098c

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

fix up map image switching, security fixes, skeleton for image deletion
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmSjxVEACgkQO3+8IhRO
Y5impxAAgJ+u2peTEXxRivx+5GULx+G8ncfzaEty4ZikXD2pjFSGZyxOENru987v
UUvSoe6SN4Or00oWs4liJDWcQwQikX+FSLY8Gu7IThLeA1HeKU1L5CLfIXOcQ/yL
AdU/0OJBjaKEg33jqSwsC/W3LbWo4rhaIMpyffKsNvMG+2VptHowOkakIN2SuSp9
Dh5HTPyJGZ/qJytQoaKu9VEEfabcy1OFhiJ96+5e0R3tZVeBh/s5bMtwkKY1P7sn
PEZZPtF0abDtUzg14oaA1fxHLj3PXqGn2+L5GVVyptappIGNym81hnyaZxGKivnX
eLT8ubFrRdOkHa5vDZkPivF+g0/5A5l3ZAQYYoqkKnDUaykhvmSUStMuHDfeDk/W
UYtyFeZPFLmpOrXzvlFqR+/81Q9LyZXC7grp4kvhj/BZqaqhWMmEdz4lbl9ehFmM
8zv8O76Ltx8osup+wCZaOAPaJMv9ASHJr6taK/1iWwg4Xfcm+ssZmO8Kb5WKPTIg
XniNFqtQs5/fw4kQtO4Hp9lwjgxQRaujXu6/YNo9/fXvAPspQ7aHn7LDO4T52t+I
xomJHe5+g5MLO8sME+evqXfHbT0r7hpqPGdM8UjxVO5iXINf3xwsxeXqETt0ADo6
E2Q2sshLRrcbqBMtZsobbmgH79nYiocOi9Ly8PFVaEnZm0eZ6dU=
=wQEb
-----END PGP SIGNATURE-----
commit

b125b3c3ec48c60e783345994b3a1a8ac58f098c

parent

17310f21cfe173ec6776335dca268d8aa256a2a9

6 files changed, 120 insertions(+), 40 deletions(-)

jump to
M admin/admin.goadmin/admin.go

@@ -170,7 +170,7 @@ }

// check if this table exists if !dbAdapter.CheckTable(tableKey) { - w.WriteHeader(401) + w.WriteHeader(404) next.ServeHTTP(w, req) return }

@@ -226,41 +226,97 @@

return http.HandlerFunc(handlerFunc) } -func apiListImages(next http.Handler, uploads string, uploadType string) http.Handler { +func apiListImages(next http.Handler, uploads string, uploadType string, 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"] - destPath := filepath.Join(uploads, tableName, uploadType) - files, err := ioutil.ReadDir(destPath) + tableKey := models.TableKey{ + Name: tableName, + Passcode: req.FormValue("passcode"), + } + + // check table actually belongs to this user + user := util.GetUserFromToken(req) + tables, err := util.GetTablesByUser(user, udb) + + if err == nil { - if err != nil { - w.WriteHeader(500) - next.ServeHTTP(w, req) - return - } + ok := false - fileNames := []string{} - for _, file := range files { - if !file.IsDir() { - fileNames = append(fileNames, "/uploads/"+tableName+"/"+uploadType+"/"+file.Name()) + for _, t := range tables { + if t.Name == tableKey.Name && t.Passcode == tableKey.Passcode { + ok = true + } } - } + + if ok { + if dbAdapter.CheckTable(tableKey) { + destPath := filepath.Join(uploads, tableName, uploadType) + files, err := ioutil.ReadDir(destPath) + + if err != nil { + w.WriteHeader(500) + next.ServeHTTP(w, req) + return + } + + fileNames := []string{} + for _, file := range files { + if !file.IsDir() { + fileNames = append(fileNames, "/uploads/"+tableName+"/"+uploadType+"/"+file.Name()) + } + } - AddContextValue(req, "files", fileNames) - next.ServeHTTP(w, req) + AddContextValue(req, "files", fileNames) + next.ServeHTTP(w, req) + return + } + } + } + w.WriteHeader(422) + next.ServeHTTP(w, req) + return } + return http.HandlerFunc(handlerFunc) } -func apiDeleteImage(next http.Handler, uploads string, uploadType string) http.Handler { - handlerFunc := func(w http.ResponseWriter, req *http.Request) { - // put the path together - // if the file exists, delete it and return the deleted path - // otherwise, return an error - } - - return http.HandlerFunc(handlerFunc) +func apiDeleteImage(next http.Handler, uploads string, uploadType string, udb auth.UserStore, dbAdapter mongodb.DbAdapter) http.Handler { + handlerFunc := func(w http.ResponseWriter, req *http.Request) { + // put the path together +urlParams := req.Context().Value("params").(map[string]string) + tableName := urlParams["Slug"] + tableKey := models.TableKey{ + Name: tableName, + Passcode: req.FormValue("passcode"), + } + + // check table actually belongs to this user + user := util.GetUserFromToken(req) + tables, err := util.GetTablesByUser(user, udb) + + if err == nil { + + ok := false + + for _, t := range tables { + if t.Name == tableKey.Name && t.Passcode == tableKey.Passcode { + ok = true + } + } + + if ok { + if dbAdapter.CheckTable(tableKey) { + // if the file exists, delete it and return the deleted path + } + } + } + + // otherwise, return an error + } + + return http.HandlerFunc(handlerFunc) } func CreateAdminInterface(udb auth.UserStore, dbAdapter mongodb.DbAdapter, uploads string, uploadMaxMB int) http.Handler {

@@ -279,11 +335,11 @@ rtr.Delete(`/api/table/(?P<Slug>\S+)`, Validate(apiDestroyTable(renderer.JSON("result"), udb, dbAdapter), udb, scopes))

// asset management rtr.Post(`/api/upload/(?P<Slug>\S+)/map/`, Validate(apiUploadImg(renderer.JSON("location"), dbAdapter, uploads, "map", uploadMaxMB), udb, scopes)) - // GET /api/upload/<table>/map/ - rtr.Get(`/api/upload/(?P<Slug>\S+)/map/`, Validate(apiListImages(renderer.JSON("files"), uploads, "map"), udb, scopes)) - // DELETE /api/upload/<table>/map/<map> + rtr.Get(`/api/upload/(?P<Slug>\S+)/map/`, Validate(apiListImages(renderer.JSON("files"), uploads, "map", udb, dbAdapter), udb, scopes)) + rtr.Delete(`/api/upload/(?P<table>\S+)/map/(?P<file>\S+)`, Validate(apiDeleteImage(renderer.JSON("deleted"), uploads, "map", udb, dbAdapter), udb, scopes)) + rtr.Delete(`/api/upload/(?P<table>\S+)/token/(?P<file>\S+)`, Validate(apiDeleteImage(renderer.JSON("deleted"), uploads, "token", udb, dbAdapter), udb, scopes)) rtr.Post(`/api/upload/(?P<Slug>\S+)/token/`, Validate(apiUploadImg(renderer.JSON("location"), dbAdapter, uploads, "token", uploadMaxMB), udb, scopes)) - rtr.Get(`/api/upload/(?P<Slug>\S+)/token/`, Validate(apiListImages(renderer.JSON("files"), uploads, "token"), udb, scopes)) + rtr.Get(`/api/upload/(?P<Slug>\S+)/token/`, Validate(apiListImages(renderer.JSON("files"), uploads, "token", udb, dbAdapter), udb, scopes)) // DELETE /api/upload/<table>/token/<token> return http.HandlerFunc(rtr.ServeHTTP)
M gametable/server.gogametable/server.go

@@ -164,8 +164,10 @@ fmt.Println(err.Error())

return } - err = self.writeToDB(tableMsg) - + err = self.writeToDB(&tableMsg) + tableMsg.Auth = nil + clean, err := json.Marshal(tableMsg) + fmt.Println(string(clean[:])) if err != nil { fmt.Println(err.Error()) return

@@ -175,7 +177,7 @@

for s, k := range self.subscribers { if k == *tableMsg.Key { select { - case s.msgs <- msg: + case s.msgs <- clean: default: go s.closeSlow() }

@@ -212,7 +214,7 @@ }

return []byte("{\"error\": \"table not found\"}") } -func (self *GameTableServer) writeToDB(tableMsg models.TableMessage) error { +func (self *GameTableServer) writeToDB(tableMsg *models.TableMessage) error { key := *tableMsg.Key if tableMsg.DiceRoll != nil { err := self.dbAdapter.InsertDiceRoll(key, *tableMsg.DiceRoll)

@@ -239,6 +241,8 @@ }

} } } + + tableMsg.Auth = nil return nil }
M models/models.gomodels/models.go

@@ -36,7 +36,7 @@ AuxMessage string `json:"auxMsg"`

} type TableMessage struct { - Auth *string `json:"auth"` + Auth *string `json:"auth,omitempty"` Key *TableKey `json:"key"` DiceRoll *DiceRoll `json:"diceRoll"` Token *Token `json:"token"`
M static/admin.jsstatic/admin.js

@@ -14,7 +14,7 @@ method: 'GET',

headers: headers, }); - const mapImgs = await fetch (`/admin/api/upload/${name}/map/`, { + const mapImgs = await fetch (`/admin/api/upload/${name}/map/?passcode=${pass}`, { method: 'GET', headers: headers, });

@@ -33,7 +33,7 @@ const imgs = await mapImgs.json();

infoHtml += "<ul>"; for (const i of imgs) { const parts = i.split("/"); - infoHtml += `<li>${parts[parts.length - 1]} <a href="${i}">view</a> <button onclick="sendMapImg(${i});">Set</button> <button onclick="deleteMapImg(${i})">Delete</button></li>\n`; + infoHtml += `<li>${parts[parts.length - 1]} <a href="${i}">view</a> <button onclick="sendMapImg('${i}');">Set</button> <button onclick="deleteMapImg('${i}')">Delete</button></li>\n`; } infoHtml += "</ul>"; } else {

@@ -57,6 +57,7 @@ }

} function sendMapImg(url) { + console.log("sending " + url); publish({mapImg: url, auth: adminToken.access_token}); }

@@ -75,12 +76,19 @@ method: "POST",

body: data, }); if (res.ok) { + // refresh so we can see the new entry in the list getTable(tableKey.name, tableKey.passcode); } else { throw new Error("Something went wrong uploading the map BG..."); } } catch (err) { setErr(`${err.name}: ${err.message}`); + } +} + +async function deleteMapImg() { + try { + } catch { } }
M static/map.jsstatic/map.js

@@ -1,8 +1,15 @@

let map = null; +let mapImg = null; function initializeMap(mapImgUrl) { - map = L.map('map', { minZoom: 0, maxZoom: 4, crs: L.CRS.Simple }); - L.imageOverlay(mapImgUrl, [[-180, 180],[180, -180]]).addTo(map); + if (!map) { + map = L.map('map', { minZoom: 0, maxZoom: 4, crs: L.CRS.Simple }); + } + if (mapImg) { + mapImg.removeFrom(map); + } + mapImg = L.imageOverlay(mapImgUrl, [[-180, 180],[180, -180]]); + mapImg.addTo(map); map.setMaxBounds([[-180,180],[180,-180]]); map.setView([0,0], 2); }
M static/util.jsstatic/util.js

@@ -17,8 +17,10 @@ }

} function saveName() { + console.log("saving username"); const username = document.getElementById("name_entry"); if (username) { + console.log(username.value + "input found"); document.cookie = "username=" + username.value; } }

@@ -27,9 +29,12 @@ function loadName() {

const username = document.getElementById("name_entry"); if (username) { const cookies = document.cookie.split(";") - if (cookies[0].trim().startsWith("username=")) { - username.value = cookies[0].trim().split("=")[1]; - } + cookies.forEach(c=>{ + console.log(c); + if (c.trim().startsWith("username=")) { + username.value = c.trim().split("=")[1]; + } + }); } }