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
8 changes: 4 additions & 4 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ concurrency:

jobs:
tests:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
Expand All @@ -20,7 +20,7 @@ jobs:
- name: setup golang
uses: actions/setup-go@v5
with:
go-version: '^1.24.0'
go-version: '^1.24.4'
- name: Set up gotestfmt
uses: gotesttools/gotestfmt-action@v2
with:
Expand All @@ -37,7 +37,7 @@ jobs:
path: /tmp/gotest.log
if-no-files-found: error
linter:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
Expand All @@ -46,7 +46,7 @@ jobs:
- name: setup golang
uses: actions/setup-go@v5
with:
go-version: '^1.24.0'
go-version: '^1.24.4'
- name: run linter
uses: golangci/golangci-lint-action@v6

13 changes: 10 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,28 @@ COPY frontend .
RUN ["npm", "run", "build"]
RUN ["npm", "prune", "--production"]

FROM golang:1.24.0 AS builder
FROM golang:1.24.4 AS builder

WORKDIR /opt/kayvault

COPY go.mod go.sum ./
COPY backend backend
COPY cmd cmd
COPY 'cmd' 'cmd'
COPY sql sql

RUN CGO_ENABLED=0 go build -o bin/kayvault cmd/main.go

FROM alpine:3.21.2 AS runner
FROM alpine:edge AS runner

COPY --from=frontend-builder /opt/kayvault-frontend/build static
COPY --from=builder /opt/kayvault/bin/kayvault kayvault
COPY sql/migrations sql/migrations

CMD ["./kayvault"]

FROM runner AS runner-debug

RUN apk add --no-cache delve

CMD ["dlv", "exec", "./kayvault", "--headless", "--listen=:4200", "--api-version=2", "--accept-multiclient", "--continue"]

16 changes: 9 additions & 7 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ vars:
sh: git tag --sort=-creatordate | head -n 1

tasks:
## Local
start-local:
cmds:
- cmd: docker compose up --build --detach
stop-local:
cmds:
- cmd: docker compose down
## CI/CD
test:
cmds:
- cmd: set -euo pipefail && go test -json -v ./... 2>&1 | gotestfmt
start-local:
cmds:
- cmd: npm run --prefix frontend build
- cmd: mv frontend/build/ static/
- cmd: go build -o bin/kayvault cmd/main.go
- cmd: ./bin/kayvault
release:
requires:
vars: [IMAGE_TAG]
cmds:
- cmd: docker buildx build -t ghcr.io/torfstack/kayvault:{{.IMAGE_TAG}} .
- cmd: docker buildx build --target runner -t ghcr.io/torfstack/kayvault:{{.IMAGE_TAG}} .
- cmd: docker push ghcr.io/torfstack/kayvault:{{.IMAGE_TAG}}
deploy:
requires:
Expand Down
6 changes: 3 additions & 3 deletions backend/convert/fromdb/fromdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import (

func Secret(in sqlc.Secret) models.Secret {
return models.Secret{
ID: in.ID,
ID: &in.ID,
Value: string(in.Value),
Key: in.Key,
Url: in.Url,
Tags: tagsSlice(in.Tags),
}
}

func Secrets(in []sqlc.Secret) []models.Secret {
func Secrets(in []sqlc.Secret) models.Secrets {
out := make([]models.Secret, len(in))
for i, s := range in {
out[i] = Secret(s)
Expand All @@ -27,7 +27,7 @@ func Secrets(in []sqlc.Secret) []models.Secret {

func User(in sqlc.User) models.User {
return models.User{
ID: in.ID,
ID: &in.ID,
Subject: in.Subject,
Email: in.Email,
FullName: in.FullName,
Expand Down
11 changes: 7 additions & 4 deletions backend/convert/todb/todb.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import (

func Secret(in models.Secret) sqlc.Secret {
return sqlc.Secret{
ID: in.ID,
ID: *in.ID,
Value: []byte(in.Value),
Key: in.Key,
Url: in.Url,
Tags: tagsString(in.Tags),
}
}

func InsertSecretParams(in models.Secret, userID int32) sqlc.InsertSecretParams {
func InsertSecretParams(in models.Secret, userID int64) sqlc.InsertSecretParams {
return sqlc.InsertSecretParams{
Value: []byte(in.Value),
Key: in.Key,
Expand All @@ -25,9 +25,9 @@ func InsertSecretParams(in models.Secret, userID int32) sqlc.InsertSecretParams
}
}

func UpdateSecretParams(in models.Secret, userID int32) sqlc.UpdateSecretParams {
func UpdateSecretParams(in models.Secret, userID int64) sqlc.UpdateSecretParams {
return sqlc.UpdateSecretParams{
ID: in.ID,
ID: *in.ID,
Value: []byte(in.Value),
Key: in.Key,
Url: in.Url,
Expand All @@ -45,6 +45,9 @@ func InsertUserParams(in models.User) sqlc.InsertUserParams {
}

func tagsString(tags []string) string {
if len(tags) == 0 {
return ""
}
t := ""
for _, tag := range tags {
t += tag + ","
Expand Down
24 changes: 24 additions & 0 deletions backend/db/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package db

import (
"context"

"github.com/torfstack/kayvault/backend/models"
)

type Database interface {
WithTx(ctx context.Context) (Database, Transaction)

DoesUserExist(ctx context.Context, username string) (bool, error)
InsertUser(ctx context.Context, params models.User) error
SelectUserByName(ctx context.Context, username string) (models.User, error)
UpsertSecret(ctx context.Context, secret models.Secret, userID int64) error
SelectSecrets(ctx context.Context, userID int64) ([]models.Secret, error)
}

type Transaction interface {
Commit(ctx context.Context)

// Rollback is a no-op if the transaction has already been committed
Rollback(ctx context.Context)
}
76 changes: 33 additions & 43 deletions backend/db/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,19 @@ import (
"context"

"github.com/jackc/pgx/v5"
"github.com/torfstack/kayvault/backend/convert/fromdb"
"github.com/torfstack/kayvault/backend/convert/todb"
"github.com/torfstack/kayvault/backend/models"
sqlc "github.com/torfstack/kayvault/sql/gen"
)

type Database interface {
WithTx(ctx context.Context) (Database, Transaction)

DoesUserExist(ctx context.Context, username string) (bool, error)
InsertUser(ctx context.Context, params sqlc.InsertUserParams) error
SelectUserByName(ctx context.Context, username string) (sqlc.User, error)
InsertSecret(ctx context.Context, params sqlc.InsertSecretParams) error
UpdateSecret(ctx context.Context, params sqlc.UpdateSecretParams) error
SelectSecrets(ctx context.Context, userID int32) ([]sqlc.Secret, error)
}

type Transaction interface {
Commit(ctx context.Context)

// Rollback is a no-op if the transaction has already been committed
Rollback(ctx context.Context)
}

type database struct {
connStr string
conn *pgx.Conn
tx pgx.Tx
}

type transaction struct {
conn *pgx.Conn
tx pgx.Tx
}
var _ Database = (*database)(nil)

func NewDatabase(connStr string) Database {
return &database{connStr: connStr}
Expand Down Expand Up @@ -72,49 +54,67 @@ func (d *database) DoesUserExist(ctx context.Context, username string) (bool, er
return q.DoesUserExist(ctx, username)
}

func (d *database) InsertUser(ctx context.Context, params sqlc.InsertUserParams) error {
func (d *database) InsertUser(ctx context.Context, user models.User) error {
q, err := startQuery(ctx, d)
defer endQuery(ctx, d)
if err != nil {
return err
}
params := todb.InsertUserParams(user)
return q.InsertUser(ctx, params)
}

func (d *database) SelectUserByName(ctx context.Context, username string) (sqlc.User, error) {
func (d *database) SelectUserByName(ctx context.Context, username string) (models.User, error) {
q, err := startQuery(ctx, d)
defer endQuery(ctx, d)
if err != nil {
return sqlc.User{}, err
return models.User{}, err
}
return q.SelectUserByName(ctx, username)
dbUser, err := q.SelectUserByName(ctx, username)
return fromdb.User(dbUser), err
}

func (d *database) InsertSecret(ctx context.Context, params sqlc.InsertSecretParams) error {
func (d *database) UpsertSecret(ctx context.Context, secret models.Secret, userID int64) error {
q, err := startQuery(ctx, d)
defer endQuery(ctx, d)
if err != nil {
return err
}
return q.InsertSecret(ctx, params)
if secret.ID == nil || *secret.ID == 0 {
params := todb.InsertSecretParams(secret, userID)
return q.InsertSecret(ctx, params)
} else {
params := todb.UpdateSecretParams(secret, userID)
return q.UpdateSecret(ctx, params)
}
}

func (d *database) UpdateSecret(ctx context.Context, params sqlc.UpdateSecretParams) error {
func (d *database) SelectSecrets(ctx context.Context, userID int64) ([]models.Secret, error) {
q, err := startQuery(ctx, d)
defer endQuery(ctx, d)
if err != nil {
return []models.Secret{}, err
}
dbSecrets, err := q.SelectSecrets(ctx, userID)
return fromdb.Secrets(dbSecrets), err
}

func (d *database) InsertSecret(ctx context.Context, params sqlc.InsertSecretParams) error {
q, err := startQuery(ctx, d)
defer endQuery(ctx, d)
if err != nil {
return err
}
return q.UpdateSecret(ctx, params)
return q.InsertSecret(ctx, params)
}

func (d *database) SelectSecrets(ctx context.Context, userID int32) ([]sqlc.Secret, error) {
func (d *database) UpdateSecret(ctx context.Context, params sqlc.UpdateSecretParams) error {
q, err := startQuery(ctx, d)
defer endQuery(ctx, d)
if err != nil {
return []sqlc.Secret{}, err
return err
}
return q.SelectSecrets(ctx, userID)
return q.UpdateSecret(ctx, params)
}

func startQuery(ctx context.Context, d *database) (*sqlc.Queries, error) {
Expand All @@ -137,13 +137,3 @@ func endQuery(ctx context.Context, d *database) {
d.conn = nil
}
}

func (t *transaction) Commit(ctx context.Context) {
_ = t.tx.Commit(ctx)
_ = t.tx.Conn().Close(ctx)
}

func (t *transaction) Rollback(ctx context.Context) {
_ = t.tx.Rollback(ctx)
_ = t.tx.Conn().Close(ctx)
}
Loading