Switching Dev Systems

This commit is contained in:
Brian Buller 2017-10-18 17:18:12 -05:00
parent cdd0ce6a44
commit d1496007fb
10 changed files with 234 additions and 330 deletions

View File

@ -11,29 +11,28 @@ func handleAdminClients(w http.ResponseWriter, req *http.Request, page *pageData
vars := mux.Vars(req)
page.SubTitle = "Clients"
clientId := vars["id"]
client := db.getClient(clientId)
client := m.GetClient(clientId)
clientIp, _, _ := net.SplitHostPort(req.RemoteAddr)
if clientId == "" {
type clientsPageData struct {
Clients []Client
}
page.TemplateData = clientsPageData{Clients: db.getAllClients()}
page.TemplateData = clientsPageData{Clients: m.clients}
page.SubTitle = "Clients"
page.show("admin-clients.html", w)
} else {
switch vars["function"] {
case "add":
page.SubTitle = "Authenticate Client"
cli := db.getClient(clientId)
if cli.IP == "" {
cli.IP = clientIp
if client.IP == "" {
client.IP = clientIp
}
type actClientPageData struct {
Id string
Ip string
Name string
}
page.TemplateData = actClientPageData{Id: cli.UUID, Ip: cli.IP, Name: cli.Name}
page.TemplateData = actClientPageData{Id: client.UUID, Ip: client.IP, Name: client.Name}
page.show("admin-activateclient.html", w)
case "auth":
email := req.FormValue("email")
@ -44,16 +43,13 @@ func handleAdminClients(w http.ResponseWriter, req *http.Request, page *pageData
client.Name = clientName
}
client.IP = clientIp
client.save()
m.UpdateClient(client)
if page.LoggedIn || doLogin(email, password) == nil {
// Received a valid login
// Authenticate the client
client.Auth = true
if client.save() == nil {
m.UpdateClient(client)
page.session.setFlashMessage("Client Authenticated", "success")
} else {
page.session.setFlashMessage("Client Authentication Failed", "error")
}
if page.LoggedIn {
redirect("/admin/clients", w, req)
}
@ -61,11 +57,8 @@ func handleAdminClients(w http.ResponseWriter, req *http.Request, page *pageData
redirect("/", w, req)
case "deauth":
client.Auth = false
if client.save() == nil {
m.UpdateClient(client)
page.session.setFlashMessage("Client De-Authenticated", "success")
} else {
page.session.setFlashMessage("Client De-Authentication Failed", "success")
}
redirect("/admin/clients", w, req)
}
}

View File

@ -62,8 +62,8 @@ func handleAdminSetMode(w http.ResponseWriter, req *http.Request, page *pageData
if err != nil {
page.session.setFlashMessage("Invalid Mode: "+vars["id"], "error")
}
if db.setPublicSiteMode(newMode) != nil {
page.session.setFlashMessage("Invalid Mode: "+vars["id"], "error")
if err = m.site.SetPublicMode(newMode); err != nil {
page.session.setFlashMessage(err.Error(), "error")
}
redirect("/admin", w, req)
}
@ -74,8 +74,8 @@ func handleAdminSetAuthMode(w http.ResponseWriter, req *http.Request, page *page
if err != nil {
page.session.setFlashMessage("Invalid Authentication Mode: "+vars["id"], "error")
}
if db.site.setAuthMode(newMode) != nil {
page.session.setFlashMessage("Invalid Authentication Mode: "+vars["id"], "error")
if err = m.site.SetAuthMode(newMode); err != nil {
page.session.setFlashMessage(err.Error(), "error")
}
redirect("/admin", w, req)
}

View File

@ -20,24 +20,25 @@ func handleAdminGames(w http.ResponseWriter, req *http.Request, page *pageData)
teamId := vars["id"]
if teamId == "" {
// Games List
// TODO: We should be able to just pass m.jam to the template instead of a custom struct
type gamesPageData struct {
Teams []Team
}
gpd := new(gamesPageData)
gpd.Teams = db.getAllTeams()
gpd.Teams = m.jam.Teams
page.TemplateData = gpd
page.SubTitle = "Games"
page.show("admin-games.html", w)
} else {
tm := db.getTeam(teamId)
tm := m.jam.GetTeamById(teamId)
if tm != nil {
switch vars["function"] {
case "save":
gm := db.newGame(tm.UUID)
gm := NewGame(tm.UUID)
gm.Name = req.FormValue("gamename")
gm.Link = req.FormValue("gamelink")
gm.Description = req.FormValue("gamedesc")
if err := gm.save(); err != nil {
if err := m.jam.UpdateGame(tm.UUID, gm); err != nil {
page.session.setFlashMessage("Error updating game: "+err.Error(), "error")
} else {
page.session.setFlashMessage("Team game updated", "success")

View File

@ -17,13 +17,6 @@ type model struct {
clients []Client // Web clients that have connected to the server
}
// Authentication Modes: Flags for which clients are able to vote
const (
AuthModeAuthentication = iota
AuthModeAll
AuthModeError
)
// Update Flags: Which parts of the model need to be updated
const (
UpdateSiteData = iota
@ -122,5 +115,10 @@ func (m *model) saveChanges() error {
return err
}
}
if m.clientsUpdated {
if err = m.SaveAllClients(); err != nil {
return err
}
}
return nil
}

View File

@ -1,11 +1,5 @@
package main
import (
"strconv"
"strings"
"time"
)
/**
* Client
* A client is a system that is connecting to the web server
@ -26,24 +20,31 @@ func NewClient(id string) *Client {
}
}
// Load all clients
/**
* DB Functions
* These are generally just called when the app starts up, or when the periodic 'save' runs
*/
// Load all clients from the DB
func (m *model) LoadAllClients() []Client {
var err error
var ret []Client
if err = m.openDB(); err != nil {
return err
return ret
}
defer m.closeDB()
var clientUids []string
cliPath := []string{"clients"}
if clientUids, err = m.bolt.GetBucketList(cliPath); err != nil {
return err
return ret
}
for _, v := range clientUids {
if cl := m.LoadClient(v); cl != nil {
m.clients = append(m.clients, *cl)
ret = append(ret, *cl)
}
}
return ret
}
// Load a client from the DB and return it
@ -61,15 +62,23 @@ func (m *model) LoadClient(clId string) *Client {
return cl
}
func (m *model) getClientById(ip string) *Client {
for i := range m.clients {
if m.clients[i].IP == ip {
return &m.clients[i].IP
// SaveAllClients saves all clients to the DB
func (m *model) SaveAllClients() error {
var err error
if err = m.openDB(); err != nil {
return nil
}
defer m.closeDB()
for _, v := range m.clients {
if err = m.SaveClient(v); err != nil {
return err
}
}
return nil
}
// SaveClient saves a client to the DB
func (m *model) SaveClient(cl *Client) error {
var err error
if err = m.openDB(); err != nil {
@ -87,20 +96,43 @@ func (m *model) SaveClient(cl *Client) error {
}
/**
* OLD FUNCTIONS
* In Memory functions
* This is generally how the app accesses client data
*/
func (c *Client) saveVote(timestamp time.Time, votes []string) error {
var err error
if err = db.open(); err != nil {
// Return a client by it's UUID
func (m *model) GetClient(id string) *Client {
for i := range m.clients {
if m.clients[i].UUID == id {
return &m.clients[i]
}
}
return nil
}
defer db.close()
// Make sure we don't clobber a duplicate vote
votesBkt := []string{"votes", c.UUID, timestamp.Format(time.RFC3339)}
for i := range votes {
if strings.TrimSpace(votes[i]) != "" {
db.bolt.SetValue(votesBkt, strconv.Itoa(i), votes[i])
// Return a client by it's IP address
func (m *model) GetClientByIp(ip string) *Client {
for i := range m.clients {
if m.clients[i].IP == ip {
return &m.clients[i]
}
}
return err
return nil
}
// Add/Update a client in the data model
func (m *model) UpdateClient(cl *Client) {
var found bool
for i := range m.clients {
if m.clients[i].UUID == cl.UUID {
found = true
m.clients[i].Auth = cl.Auth
m.clients[i].Name = cl.Name
m.clients[i].IP = cl.IP
}
}
if !found {
m.clients = append(m.clients, cl)
}
m.clientsUpdated = true
}

View File

@ -15,7 +15,7 @@ type Gamejam struct {
m *model // The model that holds this gamejam's data
mPath []string // The path in the db to this gamejam
updates []string
changed bool // Flag to tell if we need to update the db
}
func NewGamejam(m *model) *Gamejam {
@ -25,6 +25,11 @@ func NewGamejam(m *model) *Gamejam {
return gj
}
/**
* DB Functions
* These are generally just called when the app starts up, or when the periodic 'save' runs
*/
func (m *model) LoadCurrentJam() *Gamejam {
if err := m.openDB(); err != nil {
return err
@ -44,6 +49,19 @@ func (m *model) LoadCurrentJam() *Gamejam {
return gj
}
// Save everything to the DB whether it's flagged as changed or not
func (gj *Gamejam) saveToDB() error {
if err := gj.m.openDB(); err != nil {
return err
}
defer gj.m.closeDB()
}
/**
* In Memory functions
* This is generally how the app accesses client data
*/
func (gj *Gamejam) getTeamByUUID(uuid string) *Team {
for i := range gj.Teams {
if gj.Teams[i].UUID == uuid {
@ -53,17 +71,27 @@ func (gj *Gamejam) getTeamByUUID(uuid string) *Team {
return nil
}
func (gj *Gamejam) needsSave() bool {
return len(updates) > 0
// Check if pth is already in updates, if not, add it
func (gj *Gamejam) NeedsUpdate(pth []string) {
var found bool
for _, v := range gj.updates {
if !(len(v) == len(pth)) {
continue
}
func (gj *Gamejam) saveToDB() error {
if err := gj.m.openDB(); err != nil {
return err
}
defer gj.m.closeDB()
for i := range updates {
// TODO: Save
// The lengths are the same, do all elements match?
var nxt bool
for i := range pth {
if v[i] != pth[i] {
nxt = true
}
}
if !nxt {
// This pth is already in the 'updates' list
found = true
break
}
}
if !found {
gj.updates = append(gj.updates, pth)
}
}

View File

@ -1,5 +1,7 @@
package main
import "errors"
/**
* Game
* A team's game, including links, description, and screenshots
@ -49,6 +51,11 @@ func NewScreenshot(tmId, ssId string) *Screenshot {
}
}
/**
* DB Functions
* These are generally just called when the app starts up, or when the periodic 'save' runs
*/
// Load a team's game from the DB and return it
func (gj *Gamejam) LoadTeamGame(tmId string) *Game {
var err error
@ -122,21 +129,14 @@ func (gj *Gamejam) LoadTeamGameScreenshot(tmId, ssId string) *Screenshot {
return ret
}
// Save a game to the given model's DB
// Save a game to the DB
func (gj *Gamejam) SaveGame(gm *Game) error {
//func (gm *Game) save(m *model) error {
var err error
if err = gj.m.openDB(); err != nil {
return err
}
defer gj.m.closeDB()
/*
tm := gj.getTeam(gm.TeamId)
if tm == nil {
return errors.New("Invalid Team: " + gm.TeamId)
}
*/
if err := gj.m.bolt.MkBucketPath(gm.mPath); err != nil {
return err
}
@ -221,3 +221,20 @@ func (gj *Gamejam) DeleteScreenshot(ss *Screenshot) error {
ssPath := ss.mPath[:len(ss.mPath)-1]
return gj.m.bolt.DeleteBucket(ssPath, ss.UUID)
}
/**
* In Memory functions
* This is generally how the app accesses client data
*/
// Set the given team's game to gm
func (gj *Gamejam) UpdateGame(tmId string, gm *Game) error {
var found bool
tm := gj.GetTeamById(tmId)
if tm == nil {
return errors.New("Invalid team ID: " + gm.TeamId)
}
tm.Game = gm
gj.NeedsUpdate([]string{"team", tmId, "game"})
return nil
}

View File

@ -1,5 +1,7 @@
package main
import "strconv"
/**
* SiteData
* Contains configuration for the website
@ -16,6 +18,7 @@ type siteData struct {
Mode int
m *model
mPath []string // The path in the db to this site data
changed bool
}
@ -26,10 +29,18 @@ func NewSiteData(m *model) *siteData {
ret.Port = 8080
ret.SessionName = "ict-gamejam"
ret.ServerDir = "./"
ret.mPath = []string{"site"}
ret.m = m
return ret
}
// Authentication Modes: Flags for which clients are able to vote
const (
AuthModeAuthentication = iota
AuthModeAll
AuthModeError
)
// Mode flags for how the site is currently running
const (
SiteModeWaiting = iota
@ -39,72 +50,82 @@ const (
// load the site data out of the database
// If fields don't exist in the DB, don't clobber what is already in s
func (s *siteData) loadFromDB() error {
func (s *siteData) LoadFromDB() error {
if err := s.m.openDB(); err != nil {
return err
}
defer s.m.closeDB()
siteConf := []string{"site"}
if title, err := s.m.bolt.GetValue(siteConf, "title"); err == nil {
if title, err := s.m.bolt.GetValue(s.mPath, "title"); err == nil {
s.Title = title
}
if port, err := s.m.bolt.GetInt(siteConf, "port"); err == nil {
if port, err := s.m.bolt.GetInt(s.mPath, "port"); err == nil {
s.Port = port
}
if sessionName, err = s.m.bolt.GetValue(siteConf, "session-name"); err == nil {
if sessionName, err = s.m.bolt.GetValue(s.mPath, "session-name"); err == nil {
s.SessionName = sessionName
}
if serverDir, err = s.m.bolt.GetValue(siteConf, "server-dir"); err == nil {
if serverDir, err = s.m.bolt.GetValue(s.mPath, "server-dir"); err == nil {
s.ServerDir = serverDir
}
s.changed = false
return nil
}
func (s *siteData) needsSave() bool {
// Return if the site data in memory has changed
func (s *siteData) NeedsSave() bool {
return s.changed
}
func (s *siteData) saveToDB() error {
// Save the site data into the DB
func (s *siteData) SaveToDB() error {
if err := s.m.openDB(); err != nil {
return err
}
defer s.m.closeDB()
siteConf := []string{"site"}
if err = s.m.bolt.SetValue(siteConf, "title", s.Title); err != nil {
if err = s.m.bolt.SetValue(s.mPath, "title", s.Title); err != nil {
return err
}
if err = s.m.bolt.SetInt(siteConf, "port", s.Port); err != nil {
if err = s.m.bolt.SetInt(s.mPath, "port", s.Port); err != nil {
return err
}
if err = s.m.bolt.SetValue(siteConf, "session-name", s.SessionName); err != nil {
if err = s.m.bolt.SetValue(s.mPath, "session-name", s.SessionName); err != nil {
return err
}
if err = s.m.bolt.SetValue(siteConf, "server-dir", s.ServerDir); err != nil {
if err = s.m.bolt.SetValue(s.mPath, "server-dir", s.ServerDir); err != nil {
return err
}
s.changed = false
return nil
}
func (s *siteData) getAuthMode() int {
// Return the Auth Mode
func (s *siteData) GetAuthMode() int {
return s.authMode
}
func (s *siteData) setAuthMode(mode int) {
// Set the auth mode
func (s *siteData) SetAuthMode(mode int) error {
if mode < AuthModeAuthentication || mode >= AuthModeError {
return errors.Error("Invalid Authentication Mode: " + strconv.Itoa(mode))
}
if mode != s.authMode {
s.authMode = mode
s.changed = true
}
}
func (s *siteData) getPublicMode() int {
// Return the public site mode
func (s *siteData) GetPublicMode() int {
return s.publicMode
}
func (s *siteData) setPublicMode(mode int) {
// Set the public site mode
func (s *siteData) SetPublicMode(mode int) error {
if mode < SiteModeWaiting || mode >= SiteModeError {
return errors.Error("Invalid Public Mode: " + strconv.Itoa(mode))
}
if mode != s.publicMode {
s.publicMode = mode
s.changed = true

View File

@ -1,10 +1,6 @@
package main
import (
"errors"
"github.com/pborman/uuid"
)
import "errors"
/**
* Team
@ -32,6 +28,8 @@ type TeamMember struct {
SlackId string
Twitter string
Email string
mPath []string // The path in the DB to this team member
}
// Create a new team member
@ -42,6 +40,11 @@ func NewTeamMember(tmId, uId string) *TeamMember {
}
}
/**
* DB Functions
* These are generally just called when the app starts up, or when the periodic 'save' runs
*/
// LoadAllTeams loads all teams for the jam out of the database
func (gj *Gamejam) LoadAllTeams() []Team {
var err error
@ -164,229 +167,58 @@ func (gj *Gamejam) SaveTeam(tm *Team) error {
}
// Save team game
if err = gj.m.bolt.SetValue(tm.
return gj.SaveGame(gm)
}
// Delete the team tm
func (gj *Gamejam) DeleteTeam(tm *Team) error {
var err error
if err = gj.m.openDB(); err != nil {
return err
}
defer gj.m.closeDB()
if len(tm.mPath) < 2 {
return errors.New("Invalid team path: " + string(tm.mPath))
}
return gj.m.bolt.DeleteBucket(tm.mPath[:len(tm.mPath)-1], tm.UUID)
}
// Delete the TeamMember mbr from Team tm
func (gj *Gamejam) DeleteTeamMember(tm *Team, mbr *TeamMember) error {
var err error
if err = gj.m.openDB(); err != nil {
return err
}
defer gj.m.closeDB()
if len(mbr.mPath) < 2 {
return errors.New("Invalid team path: " + string(tm.mPath))
}
return gj.m.bolt.DeleteBucket(mbr.mPath[:len(mbr.mPath)-1], mbr.UUID)
}
/**
* OLD FUNCTIONS
* In Memory functions
* This is generally how the app accesses data
*/
// NewTeam creates a team with name nm and stores it in the DB
func NewTeam(nm string) error {
var err error
if err = db.open(); err != nil {
return err
}
defer db.close()
// Generate a UUID
uuid := uuid.New()
teamPath := []string{"teams", uuid}
if err := db.bolt.MkBucketPath(teamPath); err != nil {
return err
}
if err := db.bolt.SetValue(teamPath, "name", nm); err != nil {
return err
}
if err := db.bolt.MkBucketPath(append(teamPath, "members")); err != nil {
return err
}
gamePath := append(teamPath, "game")
if err := db.bolt.MkBucketPath(gamePath); err != nil {
return err
}
if err := db.bolt.SetValue(append(gamePath), "name", ""); err != nil {
return err
}
return db.bolt.MkBucketPath(append(gamePath, "screenshots"))
}
// getTeam returns a team with the given id, or nil
func (db *currJamDb) getTeam(id string) *Team {
var err error
if err = db.open(); err != nil {
return nil
}
defer db.close()
teamPath := []string{"teams", id}
tm := new(Team)
tm.UUID = id
if tm.Name, err = db.bolt.GetValue(teamPath, "name"); err != nil {
return nil
}
tm.Members = tm.getTeamMembers()
tm.Game = tm.getGame()
return tm
}
// This function returns the team for a specific member
func (db *currJamDb) getTeamForMember(mbrid string) (*Team, error) {
var err error
if err = db.open(); err != nil {
return nil, err
}
defer db.close()
teams := db.getAllTeams()
for i := range teams {
var tmMbrs []TeamMember
tmMbrs = teams[i].getTeamMembers()
if err == nil {
for j := range tmMbrs {
if tmMbrs[j].UUID == mbrid {
return &teams[i], nil
}
}
}
}
return nil, errors.New("Unable to find team member")
}
// getAllTeams returns all teams in the database
func (db *currJamDb) getAllTeams() []Team {
var ret []Team
var err error
if err = db.open(); err != nil {
return ret
}
defer db.close()
teamPath := []string{"teams"}
var teamUids []string
if teamUids, err = db.bolt.GetBucketList(teamPath); err != nil {
return ret
}
for _, v := range teamUids {
if tm := db.getTeam(v); tm != nil {
ret = append(ret, *tm)
}
}
return ret
}
// getTeamByName returns a team with the given name or nil
func (db *currJamDb) getTeamByName(nm string) *Team {
var err error
if err = db.open(); err != nil {
return nil
}
defer db.close()
teamPath := []string{"teams"}
var teamUids []string
if teamUids, err = db.bolt.GetBucketList(teamPath); err != nil {
for _, v := range teamUids {
var name string
if name, err = db.bolt.GetValue(append(teamPath, v), "name"); name == nm {
return db.getTeam(v)
}
// Find a team by it's ID
func (gj *Gamejam) GetTeamById(id string) *Team {
for i := range gj.Teams {
if gj.Teams[i].UUID == id {
return gj.Teams[i]
}
}
return nil
}
// save saves the team to the db
func (tm *Team) save() error {
var err error
if err = db.open(); err != nil {
return err
// Find a team by name
func (gj *Gamejam) GetTeamByName(nm string) *Team {
for i := range gj.Teams {
if gj.Teams[i].Name == nm {
return gj.Teams[i]
}
defer db.close()
teamPath := []string{"teams", tm.UUID}
if err = db.bolt.SetValue(teamPath, "name", tm.Name); err != nil {
return err
}
// TODO: Save Team Members
// TODO: Save Team Game
return nil
}
// delete removes the team from the database
func (tm *Team) delete() error {
var err error
if err = db.open(); err != nil {
return err
}
defer db.close()
teamPath := []string{"teams"}
return db.bolt.DeleteBucket(teamPath, tm.UUID)
}
func (tm *Team) getTeamMembers() []TeamMember {
var ret []TeamMember
var err error
if err = db.open(); err != nil {
return ret
}
defer db.close()
teamPath := []string{"teams", tm.UUID, "members"}
var memberUuids []string
if memberUuids, err = db.bolt.GetBucketList(teamPath); err == nil {
for _, v := range memberUuids {
var mbr *TeamMember
if mbr = tm.getTeamMember(v); mbr != nil {
ret = append(ret, *mbr)
}
}
}
return ret
}
func (tm *Team) updateTeamMember(mbr *TeamMember) error {
var err error
if err = db.open(); err != nil {
return err
}
defer db.close()
if mbr.UUID == "" {
mbrs := tm.getTeamMembers()
if len(mbrs) > 0 {
for i := range mbrs {
if mbrs[i].Name == mbr.Name {
mbr.UUID = mbrs[i].UUID
break
}
}
}
}
if mbr.UUID == "" {
// It's really a new one
mbr.UUID = uuid.New()
}
mbrPath := []string{"teams", tm.UUID, "members", mbr.UUID}
if db.bolt.SetValue(mbrPath, "name", mbr.Name) != nil {
return err
}
if db.bolt.SetValue(mbrPath, "slackid", mbr.SlackId) != nil {
return err
}
if db.bolt.SetValue(mbrPath, "twitter", mbr.Twitter) != nil {
return err
}
if db.bolt.SetValue(mbrPath, "email", mbr.Email) != nil {
return err
}
return nil
}
// deleteTeamMember removes a member from the database
func (tm *Team) deleteTeamMember(mbr *TeamMember) error {
var err error
if err = db.open(); err != nil {
return err
}
defer db.close()
teamPath := []string{"teams", tm.UUID, "members"}
return db.bolt.DeleteBucket(teamPath, mbr.UUID)
}

View File

@ -71,21 +71,3 @@ func (gj *Gamejam) LoadVote(clientId, tm string) *Vote {
}
return &vt
}
/**
* OLD FUNCTIONS
*/
func (db *currJamDb) getAllVotes() []Vote {
var ret []Vote
var err error
if err = db.open(); err != nil {
return ret
}
defer db.close()
clients := db.getAllClients()
for _, cl := range clients {
ret = append(ret, cl.getVotes()...)
}
return ret
}