diff --git a/.earthignore b/.earthignore deleted file mode 100644 index 622e4b4..0000000 --- a/.earthignore +++ /dev/null @@ -1,10 +0,0 @@ -build/ -.git/ -docker-compose.yml -README.md -Earthfile -config.example.json -.gitignore -.vscode/ -budgeteer -budgeteer.exe diff --git a/.vscode/settings.json b/.vscode/settings.json index b61973e..1820a53 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,11 @@ { "files.exclude": { "**/node_modules": true, - "**/vendor": true + "**/vendor": true, + "**/*.sql.go": true, + ".task/": true, + "build/": true, + "web/dist/": true }, "gopls": { "formatting.gofumpt": true, diff --git a/.woodpecker.yml b/.woodpecker.yml deleted file mode 100644 index 2476945..0000000 --- a/.woodpecker.yml +++ /dev/null @@ -1,23 +0,0 @@ -pipeline: - build: - name: Taskfile.dev - image: hub.javil.eu/budgeteer:dev - pull: true - commands: - - task ci - - docker: - image: plugins/docker - secrets: [ docker_username, docker_password ] - settings: - registry: hub.javil.eu - repo: hub.javil.eu/budgeteer - context: build - dockerfile: build/Dockerfile - tags: - - latest - when: - event: [push, tag, deployment] - -image_pull_secrets: -- hub.javil.eu diff --git a/Earthfile b/Earthfile deleted file mode 100644 index ffc0310..0000000 --- a/Earthfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM golang:1.17 -WORKDIR /src - -build: - COPY go.mod go.sum . - RUN go mod download - COPY . . - RUN --mount=type=cache,target=/root/.cache/go-build go build -o build/budgeteer ./cmd/budgeteer - SAVE ARTIFACT build/budgeteer /budgeteer AS LOCAL build/budgeteer - -docker: - WORKDIR /app - COPY +build/budgeteer . - ENTRYPOINT ["/app/budgeteer"] - SAVE IMAGE hub.javil.eu/budgeteer:latest - -run: - LOCALLY - WITH DOCKER --load=+docker - RUN docker-compose up -d - END diff --git a/Taskfile.yml b/Taskfile.yml index ac286ae..2e3cf85 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -96,7 +96,7 @@ tasks: - ./docker/build.sh - ./web/package.json cmds: - - docker build -t {{.IMAGE_NAME}}:dev . -f docker/Dockerfile + - docker build -t {{.IMAGE_NAME}}:dev . -f docker/Dockerfile.dev - docker push {{.IMAGE_NAME}}:dev run: diff --git a/build/Dockerfile b/build/Dockerfile deleted file mode 100644 index 5795b27..0000000 --- a/build/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM scratch -COPY ./budgeteer /app/budgeteer -ENTRYPOINT ["/app/budgeteer"] diff --git a/config.example.json b/config.example.json deleted file mode 100644 index 0a97561..0000000 --- a/config.example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "DatabaseHost": "localhost", - "DatabaseUser": "user", - "DatabasePassword": "thisismypassword", - "DatabaseName": "budgeteer" -} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 1775bfb..5795b27 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,17 +1,3 @@ -FROM alpine as godeps -RUN apk --no-cache add go -RUN go install github.com/kyleconroy/sqlc/cmd/sqlc@latest -RUN go install github.com/go-task/task/v3/cmd/task@latest -RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - -FROM alpine -RUN apk --no-cache add go nodejs yarn bash curl git git-perl tmux -ADD docker/build.sh / -RUN yarn global add @vue/cli -ENV PATH="/root/.yarn/bin/:${PATH}" -WORKDIR /src/web -ADD web/package.json web/yarn.lock /src/web/ -RUN yarn -WORKDIR /src -COPY --from=godeps /root/go/bin/task /root/go/bin/sqlc /root/go/bin/golangci-lint /usr/local/bin/ -CMD /build.sh +FROM scratch +COPY ./budgeteer /app/budgeteer +ENTRYPOINT ["/app/budgeteer"] diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev new file mode 100644 index 0000000..07183db --- /dev/null +++ b/docker/Dockerfile.dev @@ -0,0 +1,17 @@ +FROM alpine as godeps +RUN apk --no-cache add go +RUN go install github.com/kyleconroy/sqlc/cmd/sqlc@latest +RUN go install github.com/go-task/task/v3/cmd/task@latest +RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +FROM alpine +RUN apk --no-cache add go nodejs yarn bash curl git git-perl tmux +ADD docker/dev.sh / +RUN yarn global add @vue/cli +ENV PATH="/root/.yarn/bin/:${PATH}" +WORKDIR /src/web +ADD web/package.json web/yarn.lock /src/web/ +RUN yarn +WORKDIR /src +COPY --from=godeps /root/go/bin/task /root/go/bin/sqlc /root/go/bin/golangci-lint /usr/local/bin/ +CMD /dev.sh diff --git a/docker/build.sh b/docker/dev.sh similarity index 100% rename from docker/build.sh rename to docker/dev.sh diff --git a/docker-compose.dev.yml b/docker/docker-compose.dev.yml similarity index 100% rename from docker-compose.dev.yml rename to docker/docker-compose.dev.yml diff --git a/docker-compose.yml b/docker/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to docker/docker-compose.yml diff --git a/go.mod b/go.mod index 240f1d9..957b246 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa ) -require github.com/DATA-DOG/go-txdb v0.1.5 // indirect +require github.com/DATA-DOG/go-txdb v0.1.5 require ( github.com/gin-contrib/sse v0.1.0 // indirect diff --git a/go.sum b/go.sum index 03f0d45..20995cb 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,7 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +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/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= diff --git a/jwt/login.go b/jwt/token-verifier.go similarity index 68% rename from jwt/login.go rename to jwt/token-verifier.go index 190ebd7..e247f12 100644 --- a/jwt/login.go +++ b/jwt/token-verifier.go @@ -12,10 +12,11 @@ import ( // TokenVerifier verifies Tokens. type TokenVerifier struct { - secret string + Expiration time.Duration + secret string } -var ErrEmptySecret = fmt.Errorf("secret is required") +const DefaultExpiration = time.Hour * time.Duration(72) func NewTokenVerifier(secret string) (*TokenVerifier, error) { if secret == "" { @@ -23,20 +24,16 @@ func NewTokenVerifier(secret string) (*TokenVerifier, error) { } return &TokenVerifier{ - secret: secret, + Expiration: DefaultExpiration, + secret: secret, }, nil } -// Token contains everything to authenticate a user. -type Token struct { - username string - name string - expiry float64 - id uuid.UUID -} - -const ( - expiration = 72 +var ( + ErrUnexpectedSigningMethod = fmt.Errorf("unexpected signing method") + ErrInvalidToken = fmt.Errorf("token is invalid") + ErrTokenExpired = fmt.Errorf("token has expired") + ErrEmptySecret = fmt.Errorf("secret is required") ) // CreateToken creates a new token from username and name. @@ -48,7 +45,7 @@ func (tv *TokenVerifier) CreateToken(user *postgres.User) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "usr": user.Email, "name": user.Name, - "exp": time.Now().Add(time.Hour * expiration).Unix(), + "exp": time.Now().Add(tv.Expiration).Unix(), "id": user.ID, }) @@ -61,13 +58,7 @@ func (tv *TokenVerifier) CreateToken(user *postgres.User) (string, error) { return t, nil } -var ( - ErrUnexpectedSigningMethod = fmt.Errorf("unexpected signing method") - ErrInvalidToken = fmt.Errorf("token is invalid") - ErrTokenExpired = fmt.Errorf("token has expired") -) - -// VerifyToken verifys a given string-token. +// VerifyToken verifies a given string-token. func (tv *TokenVerifier) VerifyToken(tokenString string) (budgeteer.Token, error) { //nolint:ireturn if tv.secret == "" { return nil, ErrEmptySecret @@ -96,36 +87,3 @@ func (tv *TokenVerifier) VerifyToken(tokenString string) (budgeteer.Token, error } return tkn, nil } - -func verifyToken(token *jwt.Token) (jwt.MapClaims, error) { - if !token.Valid { - return nil, ErrInvalidToken - } - - claims, ok := token.Claims.(jwt.MapClaims) - if !ok { - return nil, ErrInvalidToken - } - - if !claims.VerifyExpiresAt(time.Now().Unix(), true) { - return nil, ErrTokenExpired - } - - return claims, nil -} - -func (t *Token) GetName() string { - return t.name -} - -func (t *Token) GetUsername() string { - return t.username -} - -func (t *Token) GetExpiry() float64 { - return t.expiry -} - -func (t *Token) GetID() uuid.UUID { - return t.id -} diff --git a/jwt/token.go b/jwt/token.go new file mode 100644 index 0000000..c9537cd --- /dev/null +++ b/jwt/token.go @@ -0,0 +1,49 @@ +package jwt + +import ( + "time" + + "github.com/dgrijalva/jwt-go" + "github.com/google/uuid" +) + +// Token contains everything to authenticate a user. +type Token struct { + username string + name string + expiry float64 + id uuid.UUID +} + +func verifyToken(token *jwt.Token) (jwt.MapClaims, error) { + if !token.Valid { + return nil, ErrInvalidToken + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + return nil, ErrInvalidToken + } + + if !claims.VerifyExpiresAt(time.Now().Unix(), true) { + return nil, ErrTokenExpired + } + + return claims, nil +} + +func (t *Token) GetName() string { + return t.name +} + +func (t *Token) GetUsername() string { + return t.username +} + +func (t *Token) GetExpiry() float64 { + return t.expiry +} + +func (t *Token) GetID() uuid.UUID { + return t.id +} diff --git a/web/index.html b/web/index.html index 791426e..b2535d4 100644 --- a/web/index.html +++ b/web/index.html @@ -6,7 +6,7 @@