Merge remote-tracking branch 'refs/remotes/origin/dev' into dev
This commit is contained in:
		
						commit
						f8277617a9
					
				
					 12 changed files with 261 additions and 21 deletions
				
			
		
							
								
								
									
										25
									
								
								.github/workflows/sqlite3-migrations.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.github/workflows/sqlite3-migrations.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
name: SQLite3 Migrations
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [ "master" ]
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [ "master" ]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    
 | 
			
		||||
    defaults:
 | 
			
		||||
      run:
 | 
			
		||||
        working-directory: ./backend
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@v3
 | 
			
		||||
    - name: Install SQLite3
 | 
			
		||||
      run: sudo apt-get install sqlite3
 | 
			
		||||
    - name: Install Make
 | 
			
		||||
      run: sudo apt-get install make
 | 
			
		||||
    - name: Run Migrations
 | 
			
		||||
      run: make migrate
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
 | 
			
		||||
bin
 | 
			
		||||
db.sqlite3
 | 
			
		||||
*.png
 | 
			
		||||
 | 
			
		||||
# Test binary, built with `go test -c`
 | 
			
		||||
*.test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ MIGRATIONS_DIR = internal/database/migrations
 | 
			
		|||
 | 
			
		||||
# Build target
 | 
			
		||||
build:
 | 
			
		||||
	$(GOBUILD) -o bin/server cmd/*.go
 | 
			
		||||
	$(GOBUILD) -o bin/server main.go
 | 
			
		||||
 | 
			
		||||
# Run target
 | 
			
		||||
run: build
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +43,7 @@ update:
 | 
			
		|||
 | 
			
		||||
# Migration target
 | 
			
		||||
migrate:
 | 
			
		||||
	@echo "If this ever fails, run make clean and try again"
 | 
			
		||||
	@echo "Migrating database $(DB_FILE) using SQL scripts in $(MIGRATIONS_DIR)"
 | 
			
		||||
	@for file in $(wildcard $(MIGRATIONS_DIR)/*.sql); do \
 | 
			
		||||
		echo "Applying migration: $$file"; \
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +71,31 @@ lint:
 | 
			
		|||
# Default target
 | 
			
		||||
default: build	
 | 
			
		||||
 | 
			
		||||
# Generate swagger docs
 | 
			
		||||
.PHONY: docs
 | 
			
		||||
docs:
 | 
			
		||||
	swag init -outputTypes go
 | 
			
		||||
 | 
			
		||||
.PHONY: docfmt
 | 
			
		||||
docfmt:
 | 
			
		||||
	swag fmt
 | 
			
		||||
 | 
			
		||||
# Generate ERD
 | 
			
		||||
# Requires eralchemy2
 | 
			
		||||
.PHONY: erd
 | 
			
		||||
erd:
 | 
			
		||||
	eralchemy2 -i sqlite:///db.sqlite3 -o erd.png
 | 
			
		||||
 | 
			
		||||
install-swag:
 | 
			
		||||
	@echo "Installing swag"
 | 
			
		||||
	@go get -u github.com/swaggo/swag/cmd/swag
 | 
			
		||||
 | 
			
		||||
# Convenience target to install golangci-lint
 | 
			
		||||
install-lint:
 | 
			
		||||
	@echo "Installing golangci-lint"
 | 
			
		||||
	@curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.42.1
 | 
			
		||||
 | 
			
		||||
# Convenience target to install just (requires sudo privileges)
 | 
			
		||||
install-just:
 | 
			
		||||
	@echo "Installing just"
 | 
			
		||||
	@curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										80
									
								
								backend/docs/docs.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								backend/docs/docs.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
// Package docs Code generated by swaggo/swag. DO NOT EDIT
 | 
			
		||||
package docs
 | 
			
		||||
 | 
			
		||||
import "github.com/swaggo/swag"
 | 
			
		||||
 | 
			
		||||
const docTemplate = `{
 | 
			
		||||
    "schemes": {{ marshal .Schemes }},
 | 
			
		||||
    "swagger": "2.0",
 | 
			
		||||
    "info": {
 | 
			
		||||
        "description": "{{escape .Description}}",
 | 
			
		||||
        "title": "{{.Title}}",
 | 
			
		||||
        "contact": {},
 | 
			
		||||
        "license": {
 | 
			
		||||
            "name": "AGPL",
 | 
			
		||||
            "url": "https://www.gnu.org/licenses/agpl-3.0.html"
 | 
			
		||||
        },
 | 
			
		||||
        "version": "{{.Version}}"
 | 
			
		||||
    },
 | 
			
		||||
    "host": "{{.Host}}",
 | 
			
		||||
    "basePath": "{{.BasePath}}",
 | 
			
		||||
    "paths": {
 | 
			
		||||
        "/api/register": {
 | 
			
		||||
            "post": {
 | 
			
		||||
                "description": "Register a new user",
 | 
			
		||||
                "consumes": [
 | 
			
		||||
                    "application/json"
 | 
			
		||||
                ],
 | 
			
		||||
                "produces": [
 | 
			
		||||
                    "application/json"
 | 
			
		||||
                ],
 | 
			
		||||
                "tags": [
 | 
			
		||||
                    "User"
 | 
			
		||||
                ],
 | 
			
		||||
                "summary": "Register a new user",
 | 
			
		||||
                "responses": {
 | 
			
		||||
                    "200": {
 | 
			
		||||
                        "description": "User added",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "type": "string"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "400": {
 | 
			
		||||
                        "description": "Bad request",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "type": "string"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "500": {
 | 
			
		||||
                        "description": "Internal server error",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "type": "string"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "externalDocs": {
 | 
			
		||||
        "description": "OpenAPI",
 | 
			
		||||
        "url": "https://swagger.io/resources/open-api/"
 | 
			
		||||
    }
 | 
			
		||||
}`
 | 
			
		||||
 | 
			
		||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
 | 
			
		||||
var SwaggerInfo = &swag.Spec{
 | 
			
		||||
	Version:          "0.0.1",
 | 
			
		||||
	Host:             "localhost:8080",
 | 
			
		||||
	BasePath:         "/api",
 | 
			
		||||
	Schemes:          []string{},
 | 
			
		||||
	Title:            "TTime API",
 | 
			
		||||
	Description:      "This is the API for TTime, a time tracking application.",
 | 
			
		||||
	InfoInstanceName: "swagger",
 | 
			
		||||
	SwaggerTemplate:  docTemplate,
 | 
			
		||||
	LeftDelim:        "{{",
 | 
			
		||||
	RightDelim:       "}}",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,32 @@ require (
 | 
			
		|||
	github.com/mattn/go-sqlite3 v1.14.22
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/KyleBanks/depth v1.2.1 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/purell v1.2.1 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
 | 
			
		||||
	github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
 | 
			
		||||
	github.com/go-openapi/jsonpointer v0.20.3 // indirect
 | 
			
		||||
	github.com/go-openapi/jsonreference v0.20.5 // indirect
 | 
			
		||||
	github.com/go-openapi/spec v0.20.15 // indirect
 | 
			
		||||
	github.com/go-openapi/swag v0.22.10 // indirect
 | 
			
		||||
	github.com/gofiber/swagger v1.0.0 // indirect
 | 
			
		||||
	github.com/josharian/intern v1.0.0 // indirect
 | 
			
		||||
	github.com/mailru/easyjson v0.7.7 // indirect
 | 
			
		||||
	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 | 
			
		||||
	github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
 | 
			
		||||
	github.com/swaggo/files/v2 v2.0.0 // indirect
 | 
			
		||||
	github.com/swaggo/swag v1.16.3 // indirect
 | 
			
		||||
	github.com/urfave/cli/v2 v2.27.1 // indirect
 | 
			
		||||
	github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
 | 
			
		||||
	golang.org/x/net v0.22.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.14.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.19.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
	sigs.k8s.io/yaml v1.4.0 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/MicahParks/keyfunc/v2 v2.1.0 // indirect
 | 
			
		||||
	github.com/gofiber/contrib/jwt v1.0.8
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,28 @@
 | 
			
		|||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
 | 
			
		||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 | 
			
		||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
 | 
			
		||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
 | 
			
		||||
github.com/MicahParks/keyfunc/v2 v2.1.0 h1:6ZXKb9Rp6qp1bDbJefnG7cTH8yMN1IC/4nf+GVjO99k=
 | 
			
		||||
github.com/MicahParks/keyfunc/v2 v2.1.0/go.mod h1:rW42fi+xgLJ2FRRXAfNx9ZA8WpD4OeE/yHVMteCkw9k=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
 | 
			
		||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 | 
			
		||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 | 
			
		||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
 | 
			
		||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 | 
			
		||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
 | 
			
		||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.20.3 h1:jykzYWS/kyGtsHfRt6aV8JTB9pcQAXPIA7qlZ5aRlyk=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.20.3/go.mod h1:c7l0rjoouAuIxCm8v/JWKRgMjDG/+/7UBWsXMrv6PsM=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.20.5 h1:hutI+cQI+HbSQaIGSfsBsYI0pHk+CATf8Fk5gCSj0yI=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.20.5/go.mod h1:thAqAp31UABtI+FQGKAQfmv7DbFpKNUlva2UPCxKu2Y=
 | 
			
		||||
github.com/go-openapi/spec v0.20.15 h1:8bDcVxF607pTh9NpPwgsH4J5Uhh5mV5XoWnkurdiY+U=
 | 
			
		||||
github.com/go-openapi/spec v0.20.15/go.mod h1:o0upgqg5uYFG7O5mADrDVmSG3Wa6y6OLhwiCqQ+sTv4=
 | 
			
		||||
github.com/go-openapi/swag v0.22.10 h1:4y86NVn7Z2yYd6pfS4Z+Nyh3aAUL3Nul+LMbhFKy0gA=
 | 
			
		||||
github.com/go-openapi/swag v0.22.10/go.mod h1:Cnn8BYtRlx6BNE3DPN86f/xkapGIcLWzh3CLEb4C1jI=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 | 
			
		||||
github.com/gofiber/contrib/jwt v1.0.8 h1:/GeOsm/Mr1OGr0GTy+RIVSz5VgNNyP3ZgK4wdqxF/WY=
 | 
			
		||||
| 
						 | 
				
			
			@ -14,20 +31,28 @@ github.com/gofiber/fiber/v2 v2.52.1 h1:1RoU2NS+b98o1L77sdl5mboGPiW+0Ypsi5oLmcYlg
 | 
			
		|||
github.com/gofiber/fiber/v2 v2.52.1/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
 | 
			
		||||
github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo=
 | 
			
		||||
github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
 | 
			
		||||
github.com/gofiber/swagger v1.0.0 h1:BzUzDS9ZT6fDUa692kxmfOjc1DZiloLiPK/W5z1H1tc=
 | 
			
		||||
github.com/gofiber/swagger v1.0.0/go.mod h1:QrYNF1Yrc7ggGK6ATsJ6yfH/8Zi5bu9lA7wB8TmCecg=
 | 
			
		||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 | 
			
		||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 | 
			
		||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 | 
			
		||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
 | 
			
		||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 | 
			
		||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
 | 
			
		||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
 | 
			
		||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 | 
			
		||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 | 
			
		||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
 | 
			
		||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
 | 
			
		||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
 | 
			
		||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
 | 
			
		||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 | 
			
		||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
 | 
			
		||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 | 
			
		||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 | 
			
		||||
| 
						 | 
				
			
			@ -38,10 +63,21 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
 | 
			
		|||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 | 
			
		||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 | 
			
		||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
 | 
			
		||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
 | 
			
		||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 | 
			
		||||
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
 | 
			
		||||
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
 | 
			
		||||
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
 | 
			
		||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
 | 
			
		||||
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
 | 
			
		||||
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
 | 
			
		||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 | 
			
		||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 | 
			
		||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
 | 
			
		||||
| 
						 | 
				
			
			@ -50,9 +86,24 @@ github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7g
 | 
			
		|||
github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
 | 
			
		||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
 | 
			
		||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
 | 
			
		||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI=
 | 
			
		||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
 | 
			
		||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
 | 
			
		||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
 | 
			
		||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
 | 
			
		||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
 | 
			
		||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
			
		||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
 | 
			
		||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 | 
			
		||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 | 
			
		||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@ package database
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"embed"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"time"
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +36,7 @@ type Db struct {
 | 
			
		|||
var scripts embed.FS
 | 
			
		||||
 | 
			
		||||
const userInsert = "INSERT INTO users (username, password) VALUES (?, ?)"
 | 
			
		||||
const projectInsert = "INSERT INTO projects (name, description, user_id) SELECT ?, ?, id FROM users WHERE username = ?"
 | 
			
		||||
const projectInsert = "INSERT INTO projects (name, description, owner_user_id) SELECT ?, ?, id FROM users WHERE username = ?"
 | 
			
		||||
const promoteToAdmin = "INSERT INTO site_admin (admin_id) SELECT id FROM users WHERE username = ?"
 | 
			
		||||
const addTimeReport = "INSERT INTO activity (report_id, activity_nbr, start_time, end_time, break, comment) VALUES (?, ?, ?, ?, ?, ?)" // WIP
 | 
			
		||||
const addUserToProject = "INSERT INTO project_member (project_id, user_id, role) VALUES (?, ?, ?)"                                     // WIP
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +153,6 @@ func (d *Db) Migrate(dirname string) error {
 | 
			
		|||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		log.Println("Executed SQL file:", file.Name())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if tr.Commit() != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,9 @@ CREATE TABLE IF NOT EXISTS projects (
 | 
			
		|||
  projectId TEXT DEFAULT (HEX(RANDOMBLOB(4))) NOT NULL UNIQUE,
 | 
			
		||||
  name VARCHAR(255) NOT NULL UNIQUE,
 | 
			
		||||
  description TEXT NOT NULL,
 | 
			
		||||
  user_id INTEGER NOT NULL,
 | 
			
		||||
  FOREIGN KEY (user_id) REFERENCES users (id)
 | 
			
		||||
  owner_user_id INTEGER NOT NULL,
 | 
			
		||||
  FOREIGN KEY (owner_user_id) REFERENCES users (id)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
CREATE INDEX IF NOT EXISTS projects_projectId_index ON projects (projectId);
 | 
			
		||||
CREATE INDEX IF NOT EXISTS projects_user_id_index ON projects (user_id);
 | 
			
		||||
CREATE INDEX IF NOT EXISTS projects_user_id_index ON projects (owner_user_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
-- This table represents the possible role a user can have in a project.
 | 
			
		||||
-- It has nothing to do with the site admin table.
 | 
			
		||||
CREATE TABLE IF NOT EXISTS project_role (
 | 
			
		||||
    p_role TEXT PRIMARY KEY
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
-- Insert the possible roles a user can have in a project.
 | 
			
		||||
INSERT OR IGNORE INTO project_role (p_role) VALUES ('admin');
 | 
			
		||||
INSERT OR IGNORE INTO project_role (p_role) VALUES ('member');
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +1,9 @@
 | 
			
		|||
CREATE TABLE IF NOT EXISTS user_roles (
 | 
			
		||||
  user_id INTEGER NOT NULL,
 | 
			
		||||
  project_id INTEGER NOT NULL,
 | 
			
		||||
  role STRING NOT NULL, -- 'admin' or 'member'
 | 
			
		||||
  p_role TEXT NOT NULL, -- 'admin' or 'member'
 | 
			
		||||
  FOREIGN KEY (user_id) REFERENCES users (id)
 | 
			
		||||
  FOREIGN KEY (project_id) REFERENCES projects (id)
 | 
			
		||||
  FOREIGN KEY (p_role) REFERENCES project_role (p_role)
 | 
			
		||||
  PRIMARY KEY (user_id, project_id)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
-- Make sure that the role is either 'admin' or 'member'
 | 
			
		||||
CREATE TRIGGER IF NOT EXISTS user_role_admin_or_member
 | 
			
		||||
  BEFORE INSERT ON user_roles
 | 
			
		||||
  FOR EACH ROW
 | 
			
		||||
  BEGIN
 | 
			
		||||
    SELECT RAISE(ABORT, 'Invalid role') WHERE NEW.role NOT IN ('admin', 'member');
 | 
			
		||||
  END;
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +46,17 @@ type GState struct {
 | 
			
		|||
	ButtonCount int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Register is a simple handler that registers a new user
 | 
			
		||||
//
 | 
			
		||||
//	@Summary		Register a new user
 | 
			
		||||
//	@Description	Register a new user
 | 
			
		||||
//	@Tags			User
 | 
			
		||||
//	@Accept			json
 | 
			
		||||
//	@Produce		json
 | 
			
		||||
//	@Success		200	{string}	string	"User added"
 | 
			
		||||
//	@Failure		400	{string}	string	"Bad request"
 | 
			
		||||
//	@Failure		500	{string}	string	"Internal server error"
 | 
			
		||||
//	@Router			/api/register [post]
 | 
			
		||||
func (gs *GState) Register(c *fiber.Ctx) error {
 | 
			
		||||
	u := new(types.User)
 | 
			
		||||
	if err := c.BodyParser(u); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,34 @@
 | 
			
		|||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	_ "ttime/docs"
 | 
			
		||||
	"ttime/internal/config"
 | 
			
		||||
	"ttime/internal/database"
 | 
			
		||||
	"ttime/internal/handlers"
 | 
			
		||||
 | 
			
		||||
	"github.com/BurntSushi/toml"
 | 
			
		||||
	"github.com/gofiber/fiber/v2"
 | 
			
		||||
	"github.com/gofiber/swagger"
 | 
			
		||||
	_ "github.com/mattn/go-sqlite3"
 | 
			
		||||
 | 
			
		||||
	jwtware "github.com/gofiber/contrib/jwt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//	@title			TTime API
 | 
			
		||||
//	@version		0.0.1
 | 
			
		||||
//	@description	This is the API for TTime, a time tracking application.
 | 
			
		||||
 | 
			
		||||
//	@license.name	AGPL
 | 
			
		||||
//	@license.url	https://www.gnu.org/licenses/agpl-3.0.html
 | 
			
		||||
 | 
			
		||||
//	@host		localhost:8080
 | 
			
		||||
//	@BasePath	/api
 | 
			
		||||
 | 
			
		||||
// @externalDocs.description	OpenAPI
 | 
			
		||||
// @externalDocs.url			https://swagger.io/resources/open-api/
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	conf, err := config.ReadConfigFromFile("config.toml")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,9 +36,11 @@ func main() {
 | 
			
		|||
		_ = conf.WriteConfigToFile("config.toml")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Pretty print the current config
 | 
			
		||||
	str, _ := json.MarshalIndent(conf, "", "  ")
 | 
			
		||||
	fmt.Println(string(str))
 | 
			
		||||
	// Pretty print the current config with toml
 | 
			
		||||
	_ = toml.NewEncoder(os.Stdout).Encode(conf)
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("Starting server on http://localhost:%d\n", conf.Port)
 | 
			
		||||
	fmt.Printf("For documentation, go to http://localhost:%d/swagger/index.html\n", conf.Port)
 | 
			
		||||
 | 
			
		||||
	// Connect to the database
 | 
			
		||||
	db := database.DbConnect(conf.DbPath)
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +49,8 @@ func main() {
 | 
			
		|||
	// Create the server
 | 
			
		||||
	server := fiber.New()
 | 
			
		||||
 | 
			
		||||
	server.Get("/swagger/*", swagger.HandlerDefault)
 | 
			
		||||
 | 
			
		||||
	// Mount our static files (Beware of the security implications of this!)
 | 
			
		||||
	// This will likely be replaced by an embedded filesystem in the future
 | 
			
		||||
	server.Static("/", "./static")
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue