From d075388696da4ee7181eac9e7dfb5b78b445aca5 Mon Sep 17 00:00:00 2001 From: WeatherGod3218 Date: Mon, 11 May 2026 01:46:27 -0500 Subject: [PATCH 1/5] feat: V1 working! --- README.md | 2 +- api.go | 78 +++++++++++++++++++++++----- database/counter.go | 115 ++++++++++++++++++++++++++++++++++++----- database/database.go | 12 ++--- database/reset.go | 34 +++++++++++- go.mod | 36 +++++++------ go.sum | 38 ++++++++++++++ main.go | 14 +++-- templates/counter.tmpl | 111 +++++++++++++++++++++++++++++++++------ templates/create.tmpl | 10 ---- templates/index.html | 4 +- templates/reset.tmpl | 12 +---- users.go | 2 +- 13 files changed, 372 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 48fa055..3caaf47 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A simple interface for logging and displaying time since a certain event has occured, allowing for CSHer's to track how long its been since a prior event. Heavily inspired off the "Days since last..." meme format. -This project uses Golang, [Gin](https://fastapi.tiangolo.com/), HTML/CSS, and Javascript. +This project uses Golang, [Gin](https://gin-gonic.com/en/), HTML/CSS, and Javascript. This project ALSO uses a modified version of bootstrap 5! Check it out [here!](https://github.com/ComputerScienceHouse/csh-material-bootstrap/tree/bootstrap-5) diff --git a/api.go b/api.go index cb23620..f441ea1 100644 --- a/api.go +++ b/api.go @@ -11,8 +11,6 @@ import ( "go.mongodb.org/mongo-driver/v2/bson" ) -const tempName string = "A Person!" - func translateTime(inputTime string) time.Time { timeZone, _ := time.LoadLocation("America/New_York") @@ -26,13 +24,11 @@ func translateTime(inputTime string) time.Time { if timeConverted.After(currentTime) { timeConverted = currentTime } - return timeConverted } func GetHomePage(c *gin.Context) { - // This is intentionally left unprotected - // A user may be unable to vote but should still be able to see a list of polls + user := GetUserData(c) counters, err := database.GetAllCounters(c) @@ -47,22 +43,40 @@ func GetHomePage(c *gin.Context) { c.HTML(http.StatusOK, "index.html", gin.H{ "Counters": counters, + "Username": user.Username, + "FullName": user.FullName, + "EBoard": IsEboard(user), + "RTP": IsActiveRTP(user), }) } func GetCreatePage(c *gin.Context) { - c.HTML(http.StatusOK, "create.tmpl", gin.H{}) + user := GetUserData(c) + + c.HTML(http.StatusOK, "create.tmpl", gin.H{ + "Username": user.Username, + "FullName": user.FullName, + "EBoard": IsEboard(user), + "RTP": IsActiveRTP(user), + }) } func GetResetPage(c *gin.Context) { + user := GetUserData(c) + idToUse := c.Param("id") c.HTML(http.StatusOK, "reset.tmpl", gin.H{ - "Id": idToUse, + "Id": idToUse, + "Username": user.Username, + "FullName": user.FullName, + "EBoard": IsEboard(user), + "RTP": IsActiveRTP(user), }) } func LoadCounter(c *gin.Context) { idToUse := c.Param("id") + user := GetUserData(c) counter, cError := database.GetCounterFromId(c, idToUse) if cError != nil { @@ -78,20 +92,27 @@ func LoadCounter(c *gin.Context) { c.HTML(200, "counter.tmpl", gin.H{ "Id": counter.Id.Hex(), + "CounterID": counter.UserID, "Title": counter.Title, "Description": counter.Description, "Timestamp": counter.LastReset.Timestamp, "History": history.History, + "Username": user.Username, + "FullName": user.FullName, + "UserID": user.Uuid, + "EBoard": IsEboard(user), + "RTP": IsActiveRTP(user), }) } func ResetCounter(c *gin.Context) { resetTime := translateTime(c.PostForm("reset-time")) + user := GetUserData(c) reset := &database.Reset{ Id: bson.NewObjectID(), - Reporter: tempName, - Instigator: c.PostForm("reset-user"), + UserID: user.Uuid, + Reporter: user.Username, Description: c.PostForm("reset-description"), Timestamp: resetTime, } @@ -108,18 +129,20 @@ func ResetCounter(c *gin.Context) { func CreateCounter(c *gin.Context) { resetTime := translateTime(c.PostForm("reset-time")) + user := GetUserData(c) reset := &database.Reset{ Id: bson.NewObjectID(), - Reporter: tempName, - Instigator: c.PostForm("reset-user"), + UserID: user.Uuid, + Reporter: user.Username, Description: c.PostForm("reset-description"), Timestamp: resetTime, } counter := &database.Counter{ Id: bson.NewObjectID(), - CreatedBy: tempName, + UserID: user.Uuid, + CreatedBy: user.Username, Title: c.PostForm("title"), Description: c.PostForm("description"), LastReset: *reset, @@ -133,3 +156,34 @@ func CreateCounter(c *gin.Context) { c.Redirect(http.StatusFound, "/counters/"+counter.IDHex()) } + +func DeleteReset(c *gin.Context) { + counterIdString := c.PostForm("counterId") + resetId, _ := bson.ObjectIDFromHex(c.PostForm("resetId")) + counterId, _ := bson.ObjectIDFromHex(counterIdString) + + exists, err := database.DeleteReset(c, counterId, resetId) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + if exists { + c.Redirect(http.StatusFound, "/counters/"+counterIdString) + return + } + + c.Redirect(http.StatusFound, "/") +} + +func DeleteCounter(c *gin.Context) { + counterId, _ := bson.ObjectIDFromHex(c.PostForm("counterId")) + + err := database.DeleteCounter(c, counterId) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.Redirect(http.StatusFound, "/") +} diff --git a/database/counter.go b/database/counter.go index 242ec48..54ffc31 100644 --- a/database/counter.go +++ b/database/counter.go @@ -2,14 +2,18 @@ package database import ( "context" - "sort" "time" "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo/options" + + "github.com/WeatherGod3218/counters/logging" + "github.com/sirupsen/logrus" ) type Counter struct { Id bson.ObjectID `bson:"_id,omitempty"` + UserID string `bson:"uuid"` CreatedBy string `bson:"createdBy"` Title string `bson:"title"` Description string `bson:"description"` @@ -81,7 +85,19 @@ func GetAllCounters(ctx context.Context) ([]*Counter, error) { return counters, nil } -func (counter *Counter) Reset(ctx context.Context, reset *Reset) error { +func DeleteCounter(ctx context.Context, counterId bson.ObjectID) error { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + counter, err := GetCounterFromId(context.Background(), counterId.Hex()) + if err != nil { + logging.Logger.WithFields(logrus.Fields{"error": err, "module": "reset", "method": "DeleteReset"}).Fatal("error deleting the counter!") + } + + return counter.Delete(ctx) +} + +func (counter *Counter) Delete(ctx context.Context) error { ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() @@ -92,22 +108,66 @@ func (counter *Counter) Reset(ctx context.Context, reset *Reset) error { defer session.EndSession(context.Background()) _, err = session.WithTransaction(ctx, func(sessCtx context.Context) (any, error) { + _, err = Client.Database(db).Collection("history").DeleteOne( + sessCtx, + bson.M{"_id": counter.Id}, + ) - var history History + if err != nil { + return nil, err + } + + _, err = Client.Database(db).Collection("counters").DeleteOne( + sessCtx, + bson.M{"_id": counter.Id}, + ) - err := Client.Database(db).Collection("history").FindOne(sessCtx, bson.M{"_id": counter.Id}).Decode(&history) if err != nil { return nil, err } - resetHistory := history.History - resetHistory = append(resetHistory, *reset) - sort.Slice(resetHistory, func(i, j int) bool { - return resetHistory[i].Timestamp.After(resetHistory[j].Timestamp) - }) + return nil, nil + }) + + if err != nil { + logging.Logger.WithFields(logrus.Fields{"error": err, "module": "counter", "method": "Delete", "counter": counter.Id}).Warn("error deleting the counter!") + return err + } + + return nil +} + +func (counter *Counter) Update(ctx context.Context) (bool, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + session, err := Client.StartSession() + if err != nil { + return false, err + } + defer session.EndSession(context.Background()) + + counterEmpty := false - lastReset := resetHistory[0] + _, err = session.WithTransaction(ctx, func(sessCtx context.Context) (any, error) { + var history History + + err = Client.Database(db).Collection("history").FindOne( + sessCtx, + bson.M{"_id": counter.Id}, + options.FindOne().SetProjection(bson.M{"history": bson.M{"$slice": 1}}), + ).Decode(&history) + if err != nil { + return nil, err + } + + if len(history.History) == 0 { + counterEmpty = true + return nil, nil + } + + lastReset := history.History[0] _, err = Client.Database(db).Collection("counters").UpdateOne( sessCtx, bson.M{"_id": counter.Id}, @@ -117,6 +177,33 @@ func (counter *Counter) Reset(ctx context.Context, reset *Reset) error { return nil, err } + counter.LastReset = lastReset + return nil, nil + }) + + if err != nil { + logging.Logger.WithFields(logrus.Fields{"error": err, "module": "counter", "method": "Update", "counter": counter.Id}).Warn("error updating the counter!") + return false, err + } + + if counterEmpty { + return false, counter.Delete(context.Background()) + } + + return true, nil +} + +func (counter *Counter) Reset(ctx context.Context, reset *Reset) (any, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + session, err := Client.StartSession() + if err != nil { + return true, err + } + defer session.EndSession(context.Background()) + + _, err = session.WithTransaction(ctx, func(sessCtx context.Context) (any, error) { _, err = Client.Database(db).Collection("history").UpdateOne( sessCtx, bson.M{"_id": counter.Id}, @@ -131,12 +218,14 @@ func (counter *Counter) Reset(ctx context.Context, reset *Reset) error { return nil, err } - counter.LastReset = lastReset - return nil, nil }) - return err + if err != nil { + logging.Logger.WithFields(logrus.Fields{"error": err, "module": "counter", "method": "Reset", "counter": counter.Id}).Fatal("error updating counters history!") + } + + return counter.Update(context.Background()) } func (c *Counter) IDHex() string { diff --git a/database/database.go b/database/database.go index 3e398c9..ff90694 100644 --- a/database/database.go +++ b/database/database.go @@ -1,3 +1,4 @@ +// Package database contains modules for each struct in the database package database import ( @@ -13,18 +14,10 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo/readpref" ) -type UpsertResult int - -const ( - New UpsertResult = 0 - Updated UpsertResult = 1 -) - var Client *mongo.Client var db = "" -var logger *logrus.Logger = logrus.New() - +// Connects to the MongoDB database func Connect() *mongo.Client { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -46,6 +39,7 @@ func Connect() *mongo.Client { return client } +// Disconnects from the MongoDB database func Disconnect() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() diff --git a/database/reset.go b/database/reset.go index 61f55d1..0ba59d5 100644 --- a/database/reset.go +++ b/database/reset.go @@ -1,15 +1,47 @@ package database import ( + "context" "time" + "github.com/WeatherGod3218/counters/logging" + "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/v2/bson" ) type Reset struct { Id bson.ObjectID `bson:"_id,omitempty"` - Instigator string `bson:"instigator"` + UserID string `bson:"uuid"` Reporter string `bson:"reporter"` Description string `bson:"description"` Timestamp time.Time `bson:"timestamp"` } + +func (r *Reset) IDHex() string { + return r.Id.Hex() +} + +func DeleteReset(ctx context.Context, counterId bson.ObjectID, resetId bson.ObjectID) (bool, error) { + ctx, cancel := context.WithTimeout(ctx, 15*time.Second) + defer cancel() + + _, err := Client.Database(db).Collection("history").UpdateOne( + ctx, + bson.M{"_id": counterId}, + bson.M{"$pull": bson.M{ + "history": bson.M{"_id": resetId}, + }}, + ) + + if err != nil { + return false, err + } + + counter, err := GetCounterFromId(ctx, counterId.Hex()) + if err != nil { + logging.Logger.WithFields(logrus.Fields{"error": err, "module": "reset", "method": "DeleteReset"}).Warn("error deleting the counter!") + return false, err + } + + return counter.Update(ctx) +} diff --git a/go.mod b/go.mod index c6a3df9..4496206 100644 --- a/go.mod +++ b/go.mod @@ -3,34 +3,36 @@ module github.com/WeatherGod3218/counters go 1.25.7 require ( - github.com/computersciencehouse/csh-auth/v2 v2.0.0 + github.com/computersciencehouse/csh-auth/v2 v2.0.1 github.com/gin-gonic/gin v1.12.0 github.com/sirupsen/logrus v1.9.4 go.mongodb.org/mongo-driver/v2 v2.6.0 ) require ( - github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.15.0 // indirect - github.com/bytedance/sonic/loader v0.5.0 // indirect - github.com/cloudwego/base64x v0.1.6 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.1 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect + github.com/cloudwego/base64x v0.1.7 // indirect github.com/coreos/go-oidc v2.5.0+incompatible // indirect - github.com/gabriel-vasile/mimetype v1.4.12 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect + github.com/coreos/go-oidc/v3 v3.18.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.13 // indirect + github.com/gin-contrib/sse v1.1.1 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.1 // indirect - github.com/goccy/go-json v0.10.5 // indirect + github.com/go-playground/validator/v10 v10.30.2 // indirect + github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.6 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/pquerna/cachecontrol v0.2.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect @@ -40,13 +42,13 @@ require ( github.com/xdg-go/scram v1.2.0 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect - golang.org/x/arch v0.22.0 // indirect - golang.org/x/crypto v0.50.0 // indirect - golang.org/x/net v0.52.0 // indirect + golang.org/x/arch v0.27.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/net v0.54.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.36.0 // indirect - google.golang.org/protobuf v1.36.10 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/text v0.37.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect ) diff --git a/go.sum b/go.sum index 17c6386..454c9e7 100644 --- a/go.sum +++ b/go.sum @@ -1,24 +1,42 @@ github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic v1.15.1 h1:nJD5PmM0vY7J8CT6MxoqbVAAMhkSmV2HgRAUrrpLoOw= +github.com/bytedance/sonic v1.15.1/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA= github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI= +github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg= github.com/computersciencehouse/csh-auth/v2 v2.0.0 h1:uRP8Ti/pb1SaSSBvhk3dLVpHagGdGIj216fQXkYhT9E= github.com/computersciencehouse/csh-auth/v2 v2.0.0/go.mod h1:JelmcPFBLpo8wnmErF4Zoa4UJKi0psgUDpcuTq6pWbY= +github.com/computersciencehouse/csh-auth/v2 v2.0.1 h1:rtGa9cBDZJZZJ8aeGefwAM/rzPMxWNAGDwuVDZI80ro= +github.com/computersciencehouse/csh-auth/v2 v2.0.1/go.mod h1:uL/2UDr9GJlAQORsn+rmFc18YkBsZPymYJbwb+uTRig= github.com/coreos/go-oidc v2.5.0+incompatible h1:6W0vGJR3Tu0r0PwfmjOrRZSlfxeEln8dsejt3ZWIvwo= github.com/coreos/go-oidc v2.5.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-oidc/v3 v3.18.0 h1:V9orjXynvu5wiC9SemFTWnG4F45v403aIcjWo0d41+A= +github.com/coreos/go-oidc/v3 v3.18.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= +github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= +github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -27,8 +45,12 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= +github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ= +github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= +github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= @@ -48,6 +70,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -55,6 +79,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= +github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k= @@ -96,16 +122,22 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= +golang.org/x/arch v0.27.0 h1:0WNVcR8u9yFz8j5FvdHpgwNp3FS5U4guYdzHwEiGjoU= +golang.org/x/arch v0.27.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -120,6 +152,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -128,12 +162,16 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= diff --git a/main.go b/main.go index 03f8cd6..0a7212c 100644 --- a/main.go +++ b/main.go @@ -8,12 +8,15 @@ import ( "github.com/gin-gonic/gin" "github.com/WeatherGod3218/counters/logging" - cshAuth "github.com/computersciencehouse/csh-auth/v2" "github.com/sirupsen/logrus" + + cshAuth "github.com/computersciencehouse/csh-auth/v2" ) var DEV_FORCE_IS_EBOARD bool = os.Getenv("DEV_FORCE_IS_EBOARD") == "true" +var oidcClient = OIDCClient{} + func main() { database.Client = database.Connect() @@ -42,13 +45,16 @@ func main() { router.Use(auth.CookieMiddleware()) router.GET("/", GetHomePage) - router.GET("counters/:id", LoadCounter) + router.GET("/counters/:id", LoadCounter) router.GET("/create", GetCreatePage) router.POST("/create", CreateCounter) - router.GET("reset/:id", GetResetPage) - router.POST("reset/:id", ResetCounter) + router.GET("/reset/:id", GetResetPage) + router.POST("/reset/:id", ResetCounter) + + router.POST("/delete/counter", DeleteCounter) + router.POST("/delete/reset", DeleteReset) router.Run(":8080") } diff --git a/templates/counter.tmpl b/templates/counter.tmpl index 6a2fc03..d4d1768 100644 --- a/templates/counter.tmpl +++ b/templates/counter.tmpl @@ -1,6 +1,48 @@ {{ define "counter.tmpl"}} {{ template "header.tmpl" . }} + + + +

Days Since {{.Title}}

{{.Description}}
@@ -8,37 +50,65 @@
+ + {{if or .Eboard .RTP (eq .UserID .CounterID)}} + + {{end}}

    {{ range $i, $reset := .History }} -
  • + {{if or $.Eboard $.RTP (eq $.UserID $reset.UserID)}} +
  • - {{/*
    -
    -

    {{ $reset.Description }}

    +
    +
    +
    + {{ $reset.Description }} +
    + reported by: {{ $reset.Reporter }} +
    +
    +
    +
    + + Day(s) Ago +
    -
    */}} -
    +
    +
    +
    +
    + +
    +
    +
    +
  • + {{else}} +
  • +
    +
    +
    -
    - {{ $reset.Description }} -
    - reported by: {{ $reset.Reporter }} -
    +
    + {{ $reset.Description }} +
    + reported by: {{ $reset.Reporter }} +
    -
    - - Day(s) Ago -
    +
    + + Day(s) Ago +
  • + {{end}} {{ end }}
@@ -48,6 +118,17 @@ (() => { 'use strict' + document.getElementById("deleteReset").addEventListener("show.bs.modal", function(event) { + let button = event.relatedTarget + document.getElementById("reset-modal-reset-id").value = button.getAttribute("data-reset-id") + document.getElementById("reset-modal-counter-id").value = button.getAttribute("data-counter-id") + }) + + document.getElementById("deleteCounter").addEventListener("show.bs.modal", function(event) { + let button = event.relatedTarget + document.getElementById("counter-modal-counter-id").value = button.getAttribute("data-counter-id") + }) + document.querySelectorAll(".days-since").forEach(el => { const days = Math.floor((Date.now() - new Date(el.dataset.timestamp)) / 86400000); el.textContent = days; diff --git a/templates/create.tmpl b/templates/create.tmpl index c88671b..2369fb4 100644 --- a/templates/create.tmpl +++ b/templates/create.tmpl @@ -26,16 +26,6 @@
First Reset
-
- - -
Days Since Last...

- +
-