Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions .github/workflows/build.yml

This file was deleted.

14 changes: 11 additions & 3 deletions .github/workflows/sonarqube.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
- main
pull_request:

types: [opened, synchronize, reopened]

jobs:
build:
Expand All @@ -15,8 +15,16 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- uses: SonarSource/sonarqube-scan-action@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
# If you wish to fail your job when the Quality Gate is red, uncomment the
# following lines. This would typically be used to fail a deployment.
# We do not recommend to use this in a pull request. Prefer using pull request
# decoration instead.
# - uses: SonarSource/sonarqube-quality-gate-action@v1
# timeout-minutes: 5
# env:
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@

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)

## Installing
## Local Development
### Installing
1. Clone and cd into the repo: git clone https://github.com/WeatherGod3218/counters
>> (OPTIONAL): Make another branch if your working on a large thing!

## Setup
### Setup
1. Make sure you have docker installed
>> (OPTIONAL): You can use docker compose as well!!
2. Copy the .env.template file, rename it to .env and place it in the root folder
3. Ask an RTP for counters secrets, add them to the .env accordingly

## Run
### Run

Counters is containerized through a docker file.

Expand All @@ -30,11 +31,16 @@ Counters is containerized through a docker file.
docker run -p 8080:80 Counters
```

## Docker Compose
### Docker Compose

Counters also has support for Docker Compose, a extended version of docker that simplifies the steps.

(This is a really cool thing! If you use docker often, check it out!)
```
docker compose up
```

## TODO
- [] Add API Integration
- [] Add Logging (similar to Votes "Actions")
- [] Time Zone support
90 changes: 72 additions & 18 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand All @@ -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)

Expand All @@ -47,51 +43,76 @@ 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 {
c.JSON(http.StatusInternalServerError, gin.H{"error": cError.Error()})
counter, err := database.GetCounterFromId(c, idToUse)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

history, hError := database.GetHistoryFromId(c, idToUse)
if hError != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": hError.Error()})
history, err := database.GetHistoryFromId(c, idToUse)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

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,
}
Expand All @@ -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,
Expand All @@ -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, "/")
}
Loading
Loading