mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-07-02 08:10:15 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a6c716c4e2 |
@@ -36,9 +36,9 @@ jobs:
|
|||||||
- name: Check codegen is up to date
|
- name: Check codegen is up to date
|
||||||
run: |
|
run: |
|
||||||
sqlc generate
|
sqlc generate
|
||||||
go generate ./...
|
go generate ./internal/repository/...
|
||||||
git diff --exit-code
|
git diff --exit-code -- internal/repository/
|
||||||
git status --porcelain | grep -q . && echo "untracked files in git diff" && exit 1 || true
|
git status --porcelain -- internal/repository/ | grep -q . && echo "untracked files in internal/repository/" && exit 1 || true
|
||||||
|
|
||||||
- name: Install frontend dependencies
|
- name: Install frontend dependencies
|
||||||
working-directory: ./frontend
|
working-directory: ./frontend
|
||||||
|
|||||||
+7
-5
@@ -52,15 +52,17 @@ WORKDIR /tinyauth
|
|||||||
|
|
||||||
COPY --from=builder /tinyauth/tinyauth ./
|
COPY --from=builder /tinyauth/tinyauth ./
|
||||||
|
|
||||||
RUN mkdir -p /data
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Make the data directory with a non-root user
|
||||||
|
RUN addgroup tinyauth && adduser -DH tinyauth -G tinyauth
|
||||||
|
RUN mkdir -p /data/resources /data/oidc /data/tailscale
|
||||||
|
RUN chown -R tinyauth:tinyauth /data
|
||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db
|
# Tell tinyauth that it's running in a container and where to find the data directory
|
||||||
|
ENV RUNTIME_ENV=docker
|
||||||
ENV TINYAUTH_RESOURCES_PATH=/data/resources
|
|
||||||
|
|
||||||
ENV PATH=$PATH:/tinyauth
|
ENV PATH=$PATH:/tinyauth
|
||||||
|
|
||||||
|
|||||||
@@ -40,13 +40,16 @@ COPY ./cmd ./cmd
|
|||||||
COPY ./internal ./internal
|
COPY ./internal ./internal
|
||||||
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
|
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
|
||||||
|
|
||||||
RUN mkdir -p data
|
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 go build -ldflags "${LDFLAGS} \
|
RUN CGO_ENABLED=0 go build -ldflags "${LDFLAGS} \
|
||||||
-X github.com/tinyauthapp/tinyauth/internal/model.Version=${VERSION} \
|
-X github.com/tinyauthapp/tinyauth/internal/model.Version=${VERSION} \
|
||||||
-X github.com/tinyauthapp/tinyauth/internal/model.CommitHash=${COMMIT_HASH} \
|
-X github.com/tinyauthapp/tinyauth/internal/model.CommitHash=${COMMIT_HASH} \
|
||||||
-X github.com/tinyauthapp/tinyauth/internal/model.BuildTimestamp=${BUILD_TIMESTAMP}" ./cmd/tinyauth
|
-X github.com/tinyauthapp/tinyauth/internal/model.BuildTimestamp=${BUILD_TIMESTAMP}" ./cmd/tinyauth
|
||||||
|
|
||||||
|
# Make the data directory with a non-root user
|
||||||
|
RUN addgroup tinyauth && adduser -DH tinyauth -G tinyauth
|
||||||
|
RUN mkdir -p /data/resources /data/oidc /data/tailscale
|
||||||
|
RUN chown -R tinyauth:tinyauth /data
|
||||||
|
|
||||||
# Runner
|
# Runner
|
||||||
FROM gcr.io/distroless/static-debian12:latest AS runner
|
FROM gcr.io/distroless/static-debian12:latest AS runner
|
||||||
|
|
||||||
@@ -55,15 +58,14 @@ WORKDIR /tinyauth
|
|||||||
COPY --from=builder /tinyauth/tinyauth ./
|
COPY --from=builder /tinyauth/tinyauth ./
|
||||||
|
|
||||||
# Since it's distroless, we need to copy the data directory from the builder stage
|
# Since it's distroless, we need to copy the data directory from the builder stage
|
||||||
COPY --from=builder /tinyauth/data /data
|
COPY --from=builder /data /data
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db
|
# Tell tinyauth that it's running in a container and where to find the data directory
|
||||||
|
ENV RUNTIME_ENV=docker
|
||||||
ENV TINYAUTH_RESOURCES_PATH=/data/resources
|
|
||||||
|
|
||||||
ENV PATH=$PATH:/tinyauth
|
ENV PATH=$PATH:/tinyauth
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ PROD_COMPOSE := $(shell test -f "docker-compose.test.prod.yml" && echo "docker-c
|
|||||||
|
|
||||||
.DEFAULT_GOAL := binary
|
.DEFAULT_GOAL := binary
|
||||||
|
|
||||||
|
.PHONY: deps clean-data clean-webui webui binary binary-linux-amd64 binary-linux-arm64 test vet test-race dev dev-infisical prod prod-infisical sql generate docker docker-distroless
|
||||||
|
|
||||||
# Deps
|
# Deps
|
||||||
deps:
|
deps:
|
||||||
cd frontend && pnpm ci
|
cd frontend && pnpm ci
|
||||||
@@ -58,12 +60,10 @@ binary-linux-arm64:
|
|||||||
$(MAKE) binary
|
$(MAKE) binary
|
||||||
|
|
||||||
# Go test
|
# Go test
|
||||||
.PHONY: test
|
|
||||||
test:
|
test:
|
||||||
go test -v ./...
|
go test -v ./...
|
||||||
|
|
||||||
# Go vet
|
# Go vet
|
||||||
.PHONY: vet
|
|
||||||
vet:
|
vet:
|
||||||
go vet ./...
|
go vet ./...
|
||||||
|
|
||||||
@@ -88,10 +88,18 @@ prod-infisical:
|
|||||||
infisical run --env=dev -- docker compose -f $(PROD_COMPOSE) up --force-recreate --pull=always --remove-orphans
|
infisical run --env=dev -- docker compose -f $(PROD_COMPOSE) up --force-recreate --pull=always --remove-orphans
|
||||||
|
|
||||||
# SQL
|
# SQL
|
||||||
.PHONY: sql
|
|
||||||
sql:
|
sql:
|
||||||
sqlc generate
|
sqlc generate
|
||||||
|
|
||||||
# Go gen
|
# Go gen
|
||||||
generate:
|
generate:
|
||||||
go generate ./...
|
go run ./gen
|
||||||
|
go generate ./internal/repository/...
|
||||||
|
|
||||||
|
# Docker image
|
||||||
|
docker:
|
||||||
|
docker buildx build -t tinyauthapp/tinyauth:dev --build-arg=VERSION=$(TAG_NAME) --build-arg=COMMIT_HASH=$(COMMIT_HASH) --build-arg=BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) -f Dockerfile .
|
||||||
|
|
||||||
|
# Docker image distroless
|
||||||
|
docker-distroless:
|
||||||
|
docker buildx build -t tinyauthapp/tinyauth:dev-distroless --build-arg=VERSION=$(TAG_NAME) --build-arg=COMMIT_HASH=$(COMMIT_HASH) --build-arg=BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) -f Dockerfile.distroless .
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/tinyauthapp/paerser/cli"
|
||||||
|
"github.com/tinyauthapp/tinyauth/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func configCmd(tconfig *model.Config, loaders []cli.ResourceLoader) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "config",
|
||||||
|
Description: "Print the configuration of Tinyauth",
|
||||||
|
Configuration: tconfig,
|
||||||
|
Resources: loaders,
|
||||||
|
Run: func(_ []string) error {
|
||||||
|
jsonBytes, err := json.MarshalIndent(tconfig, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal configuration: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(jsonBytes))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
tConfig := model.NewDefaultConfiguration()
|
env := model.DetectRuntimeEnv()
|
||||||
|
tConfig := model.NewDefaultConfiguration(env)
|
||||||
|
|
||||||
loaders := []cli.ResourceLoader{
|
loaders := []cli.ResourceLoader{
|
||||||
&loaders.FileLoader{},
|
&loaders.FileLoader{},
|
||||||
@@ -52,6 +53,12 @@ func main() {
|
|||||||
log.Fatal().Err(err).Msg("Failed to add version command")
|
log.Fatal().Err(err).Msg("Failed to add version command")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = cmdTinyauth.AddCommand(configCmd(tConfig, loaders))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("Failed to add config command")
|
||||||
|
}
|
||||||
|
|
||||||
err = cmdUser.AddCommand(verifyUserCmd())
|
err = cmdUser.AddCommand(verifyUserCmd())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,131 +0,0 @@
|
|||||||
// gen/context_paths generates the ignore paths for the user context since
|
|
||||||
// gin will not less apply the middleware to only specific paths.
|
|
||||||
//
|
|
||||||
// The generator reads every controller and looks for the //context:ignore comment.
|
|
||||||
// The format for the context ignore comment is:
|
|
||||||
//
|
|
||||||
// //contxt:ignore /api/mypath GET,POST
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
_ "embed"
|
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed paths.tmpl
|
|
||||||
var pathsTmplSrc string
|
|
||||||
|
|
||||||
var pathsTmpl = template.Must(template.New("paths").Parse(pathsTmplSrc))
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := run(); err != nil {
|
|
||||||
fmt.Printf("Failed to generate: %s", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() error {
|
|
||||||
// load pkg
|
|
||||||
pkgConfig := &packages.Config{
|
|
||||||
Mode: packages.NeedFiles,
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgs, err := packages.Load(pkgConfig, "github.com/tinyauthapp/tinyauth/internal/controller")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to load pkg: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pkgs) == 0 {
|
|
||||||
return fmt.Errorf("failed to get controllers package")
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg := pkgs[0]
|
|
||||||
|
|
||||||
// for each file we check the comments and either add or remove the context
|
|
||||||
var contextIgnorePaths []string
|
|
||||||
|
|
||||||
for _, gofile := range pkg.GoFiles {
|
|
||||||
// read the file
|
|
||||||
file, err := os.ReadFile(gofile)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to read %s, ignoring", gofile)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the comment lines
|
|
||||||
lines := strings.SplitSeq(string(file), "\n")
|
|
||||||
|
|
||||||
for line := range lines {
|
|
||||||
if !strings.HasPrefix(strings.TrimSpace(line), "//context:ignore") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
path, methods, ok := parseContextIgnoreLine(line)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
fmt.Printf("Failed to parse %s rule, ignore", line)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range methods {
|
|
||||||
contextIgnorePaths = append(contextIgnorePaths, m+" "+path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate out
|
|
||||||
type tmplData struct {
|
|
||||||
IgnorePaths []string
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
if err := pathsTmpl.Execute(&buf, tmplData{
|
|
||||||
IgnorePaths: contextIgnorePaths,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
formatted, err := format.Source(buf.Bytes())
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("gofmt failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// write out
|
|
||||||
err = os.WriteFile("context_paths.go", formatted, 0666)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to write out: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseContextIgnoreLine(line string) (string, []string, bool) {
|
|
||||||
line = strings.TrimPrefix(line, "//context:ignore ")
|
|
||||||
path, methodStr, ok := strings.Cut(line, " ")
|
|
||||||
if !ok {
|
|
||||||
return "", []string{}, false
|
|
||||||
}
|
|
||||||
var methodsParsed []string
|
|
||||||
methodParts := strings.SplitSeq(methodStr, ",")
|
|
||||||
for m := range methodParts {
|
|
||||||
if strings.TrimSpace(m) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m = strings.ToUpper(m)
|
|
||||||
methodsParsed = append(methodsParsed, m)
|
|
||||||
}
|
|
||||||
return path, methodsParsed, true
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
// Code generated by gen/context_paths. DO NOT EDIT.
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
var contextSkipPathsPrefix = []string{
|
|
||||||
{{range .IgnorePaths}}"{{.}}",
|
|
||||||
{{end}}}
|
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
// gen/docs generates the .env.example and config.gen.md
|
|
||||||
// files for the configuration of Tinyauth. Run via:
|
|
||||||
//
|
|
||||||
// The generator reads the Tinyauth configuration package and using reflection it generates the
|
|
||||||
// example files. The .env.example is used in this repo while the config.gen.md is used in the
|
|
||||||
// documentaton alongside some warnings that are added later.
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -20,7 +20,7 @@ type EnvEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateExampleEnv() {
|
func generateExampleEnv() {
|
||||||
cfg := model.NewDefaultConfiguration()
|
cfg := model.NewDefaultConfiguration(model.RuntimeEnvUnknown)
|
||||||
entries := make([]EnvEntry, 0)
|
entries := make([]EnvEntry, 0)
|
||||||
|
|
||||||
root := reflect.TypeOf(cfg).Elem()
|
root := reflect.TypeOf(cfg).Elem()
|
||||||
@@ -21,7 +21,7 @@ type MarkdownEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateMarkdown() {
|
func generateMarkdown() {
|
||||||
cfg := model.NewDefaultConfiguration()
|
cfg := model.NewDefaultConfiguration(model.RuntimeEnvUnknown)
|
||||||
entries := make([]MarkdownEntry, 0)
|
entries := make([]MarkdownEntry, 0)
|
||||||
|
|
||||||
root := reflect.TypeOf(cfg).Elem()
|
root := reflect.TypeOf(cfg).Elem()
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
// gen/sqlc_wrapper generates store.go wrapper files for each sqlc driver package under
|
// gen/sqlc-wrapper generates store.go wrapper files for each sqlc driver package under
|
||||||
// internal/repository/<driver>/.
|
// internal/repository/<driver>/. Run via:
|
||||||
|
//
|
||||||
|
// go generate ./internal/repository/...
|
||||||
//
|
//
|
||||||
// The generator introspects *Queries methods and the model/params types in the
|
// The generator introspects *Queries methods and the model/params types in the
|
||||||
// driver package, then emits a store.go that wraps *Queries so it satisfies
|
// driver package, then emits a store.go that wraps *Queries so it satisfies
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Code generated by cmd/gen/sqlc_wrapper. DO NOT EDIT.
|
// Code generated by cmd/gen/sqlc-wrapper. DO NOT EDIT.
|
||||||
package {{.PkgName}}
|
package {{.PkgName}}
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package docs
|
|
||||||
|
|
||||||
//go:generate go run github.com/tinyauthapp/tinyauth/gen/docs
|
|
||||||
@@ -147,7 +147,6 @@ func (controller *ContextController) userContextHandler(c *gin.Context) {
|
|||||||
c.JSON(200, userContext)
|
c.JSON(200, userContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/context/app GET
|
|
||||||
func (controller *ContextController) appContextHandler(c *gin.Context) {
|
func (controller *ContextController) appContextHandler(c *gin.Context) {
|
||||||
c.JSON(200, AppContextResponse{
|
c.JSON(200, AppContextResponse{
|
||||||
Status: 200,
|
Status: 200,
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ func NewHealthController(i HealthControllerInput) *HealthController {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/healthz GET,HEAD
|
|
||||||
func (controller *HealthController) healthHandler(c *gin.Context) {
|
func (controller *HealthController) healthHandler(c *gin.Context) {
|
||||||
c.JSON(200, gin.H{
|
c.JSON(200, gin.H{
|
||||||
"status": 200,
|
"status": 200,
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ func NewOAuthController(i OAuthControllerInput) *OAuthController {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/oauth/url GET
|
|
||||||
func (controller *OAuthController) oauthURLHandler(c *gin.Context) {
|
func (controller *OAuthController) oauthURLHandler(c *gin.Context) {
|
||||||
var req OAuthRequest
|
var req OAuthRequest
|
||||||
|
|
||||||
@@ -119,7 +118,6 @@ func (controller *OAuthController) oauthURLHandler(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/oauth/callback GET
|
|
||||||
func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) {
|
func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) {
|
||||||
var req OAuthRequest
|
var req OAuthRequest
|
||||||
|
|
||||||
|
|||||||
@@ -367,7 +367,6 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/oidc/token POST
|
|
||||||
func (controller *OIDCController) Token(c *gin.Context) {
|
func (controller *OIDCController) Token(c *gin.Context) {
|
||||||
if controller.oidc == nil {
|
if controller.oidc == nil {
|
||||||
controller.log.App.Warn().Msg("Received OIDC request but OIDC server is not configured")
|
controller.log.App.Warn().Msg("Received OIDC request but OIDC server is not configured")
|
||||||
@@ -539,7 +538,6 @@ func (controller *OIDCController) Token(c *gin.Context) {
|
|||||||
c.JSON(200, tokenResponse)
|
c.JSON(200, tokenResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/oidc/userinfo GET,POST
|
|
||||||
func (controller *OIDCController) Userinfo(c *gin.Context) {
|
func (controller *OIDCController) Userinfo(c *gin.Context) {
|
||||||
if controller.oidc == nil {
|
if controller.oidc == nil {
|
||||||
controller.log.App.Warn().Msg("Received OIDC userinfo request but OIDC server is not configured")
|
controller.log.App.Warn().Msg("Received OIDC userinfo request but OIDC server is not configured")
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ func NewResourcesController(i ResourcesControllerInput) *ResourcesController {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /resources GET
|
|
||||||
func (controller *ResourcesController) resourcesHandler(c *gin.Context) {
|
func (controller *ResourcesController) resourcesHandler(c *gin.Context) {
|
||||||
if controller.config.Resources.Path == "" {
|
if controller.config.Resources.Path == "" {
|
||||||
c.JSON(404, gin.H{
|
c.JSON(404, gin.H{
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ func NewUserController(i UserControllerInput) *UserController {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /api/user/login POST
|
|
||||||
func (controller *UserController) loginHandler(c *gin.Context) {
|
func (controller *UserController) loginHandler(c *gin.Context) {
|
||||||
var req LoginRequest
|
var req LoginRequest
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ func NewWellKnownController(i WellKnownControllerInput) *WellKnownController {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /.well-known/openid-configuration GET
|
|
||||||
func (controller *WellKnownController) OpenIDConnectConfiguration(c *gin.Context) {
|
func (controller *WellKnownController) OpenIDConnectConfiguration(c *gin.Context) {
|
||||||
if controller.oidc == nil {
|
if controller.oidc == nil {
|
||||||
c.JSON(500, gin.H{
|
c.JSON(500, gin.H{
|
||||||
@@ -95,7 +94,6 @@ func (controller *WellKnownController) OpenIDConnectConfiguration(c *gin.Context
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /.well-known/jwks.json GET
|
|
||||||
func (controller *WellKnownController) JWKS(c *gin.Context) {
|
func (controller *WellKnownController) JWKS(c *gin.Context) {
|
||||||
if controller.oidc == nil {
|
if controller.oidc == nil {
|
||||||
c.JSON(500, gin.H{
|
c.JSON(500, gin.H{
|
||||||
@@ -124,7 +122,6 @@ func (controller *WellKnownController) JWKS(c *gin.Context) {
|
|||||||
c.Status(http.StatusOK)
|
c.Status(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
//context:ignore /.well-known/webfinger GET
|
|
||||||
func (controller *WellKnownController) WebFinger(c *gin.Context) {
|
func (controller *WellKnownController) WebFinger(c *gin.Context) {
|
||||||
c.Header("Content-Type", "application/jrd+json")
|
c.Header("Content-Type", "application/jrd+json")
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
c.Header("Access-Control-Allow-Origin", "*")
|
||||||
|
|||||||
@@ -16,6 +16,26 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Gin won't let us set a middleware on a specific route (at least it doesn't work,
|
||||||
|
// see https://github.com/gin-gonic/gin/issues/531) so we have to do some hackery
|
||||||
|
var (
|
||||||
|
contextSkipPathsPrefix = []string{
|
||||||
|
"GET /api/context/app",
|
||||||
|
"GET /api/healthz",
|
||||||
|
"HEAD /api/healthz",
|
||||||
|
"GET /api/oauth/url",
|
||||||
|
"GET /api/oauth/callback",
|
||||||
|
"GET /api/oidc/clients",
|
||||||
|
"POST /api/oidc/token",
|
||||||
|
"GET /api/oidc/userinfo",
|
||||||
|
"POST /api/oidc/userinfo",
|
||||||
|
"GET /resources",
|
||||||
|
"POST /api/user/login",
|
||||||
|
"GET /.well-known/openid-configuration",
|
||||||
|
"GET /.well-known/jwks.json",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
type ContextMiddleware struct {
|
type ContextMiddleware struct {
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
runtime *model.RuntimeConfig
|
runtime *model.RuntimeConfig
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
// Code generated by gen/context_paths. DO NOT EDIT.
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
var contextSkipPathsPrefix = []string{
|
|
||||||
"GET /api/context/app",
|
|
||||||
"GET /api/healthz",
|
|
||||||
"HEAD /api/healthz",
|
|
||||||
"GET /api/oauth/url",
|
|
||||||
"GET /api/oauth/callback",
|
|
||||||
"POST /api/oidc/token",
|
|
||||||
"GET /api/oidc/userinfo",
|
|
||||||
"POST /api/oidc/userinfo",
|
|
||||||
"GET /resources",
|
|
||||||
"POST /api/user/login",
|
|
||||||
"GET /.well-known/openid-configuration",
|
|
||||||
"GET /.well-known/jwks.json",
|
|
||||||
"GET /.well-known/webfinger",
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package middleware
|
|
||||||
|
|
||||||
//go:generate go run github.com/tinyauthapp/tinyauth/gen/context_paths
|
|
||||||
+48
-18
@@ -1,8 +1,27 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
type RuntimeEnv int
|
||||||
|
|
||||||
|
const (
|
||||||
|
RuntimeEnvUnknown RuntimeEnv = iota
|
||||||
|
RuntimeEnvDocker
|
||||||
|
)
|
||||||
|
|
||||||
|
func DetectRuntimeEnv() RuntimeEnv {
|
||||||
|
env := os.Getenv("RUNTIME_ENV")
|
||||||
|
switch env {
|
||||||
|
case "docker":
|
||||||
|
return RuntimeEnvDocker
|
||||||
|
default:
|
||||||
|
return RuntimeEnvUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Default configuration
|
// Default configuration
|
||||||
func NewDefaultConfiguration() *Config {
|
func NewDefaultConfiguration(runtimeEnv RuntimeEnv) *Config {
|
||||||
return &Config{
|
cfg := &Config{
|
||||||
Database: DatabaseConfig{
|
Database: DatabaseConfig{
|
||||||
Driver: "sqlite",
|
Driver: "sqlite",
|
||||||
Path: "./tinyauth.db",
|
Path: "./tinyauth.db",
|
||||||
@@ -67,25 +86,36 @@ func NewDefaultConfiguration() *Config {
|
|||||||
},
|
},
|
||||||
LabelProvider: "auto",
|
LabelProvider: "auto",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply path overrides for docker runtime
|
||||||
|
if runtimeEnv == RuntimeEnvDocker {
|
||||||
|
cfg.Database.Path = "/data/tinyauth.db"
|
||||||
|
cfg.Resources.Path = "/data/resources"
|
||||||
|
cfg.OIDC.PrivateKeyPath = "/data/oidc/key.pem"
|
||||||
|
cfg.OIDC.PublicKeyPath = "/data/oidc/key.pub"
|
||||||
|
cfg.Tailscale.Dir = "/data/tailscale"
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
||||||
Database DatabaseConfig `description:"Database configuration." yaml:"database"`
|
Database DatabaseConfig `description:"Database configuration." yaml:"database"`
|
||||||
Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"`
|
Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"`
|
||||||
Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"`
|
Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"`
|
||||||
Server ServerConfig `description:"Server configuration." yaml:"server"`
|
Server ServerConfig `description:"Server configuration." yaml:"server"`
|
||||||
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
|
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
|
||||||
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
|
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
|
||||||
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
|
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
|
||||||
OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"`
|
OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"`
|
||||||
UI UIConfig `description:"UI customization." yaml:"ui"`
|
UI UIConfig `description:"UI customization." yaml:"ui"`
|
||||||
LDAP LDAPConfig `description:"LDAP configuration." yaml:"ldap"`
|
LDAP LDAPConfig `description:"LDAP configuration." yaml:"ldap"`
|
||||||
Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
|
// Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
|
||||||
LabelProvider string `description:"Label provider to use for ACLs (auto, docker, kubernetes or none to disable). auto detects the environment." yaml:"labelProvider"`
|
LabelProvider string `description:"Label provider to use for ACLs (auto, docker, kubernetes or none to disable). auto detects the environment." yaml:"labelProvider"`
|
||||||
Log LogConfig `description:"Logging configuration." yaml:"log"`
|
Log LogConfig `description:"Logging configuration." yaml:"log"`
|
||||||
Tailscale TailscaleConfig `description:"Tailscale configuration." yaml:"tailscale"`
|
Tailscale TailscaleConfig `description:"Tailscale configuration." yaml:"tailscale"`
|
||||||
ConfigFile string `description:"Path to config file." yaml:"-"`
|
ConfigFile string `description:"Path to config file." yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseConfig struct {
|
type DatabaseConfig struct {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package postgres
|
package postgres
|
||||||
|
|
||||||
//go:generate go run github.com/tinyauthapp/tinyauth/gen/sqlc_wrapper -pkg github.com/tinyauthapp/tinyauth/internal/repository/postgres
|
//go:generate go run github.com/tinyauthapp/tinyauth/gen/sqlc-wrapper -pkg github.com/tinyauthapp/tinyauth/internal/repository/postgres
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Code generated by cmd/gen/sqlc_wrapper. DO NOT EDIT.
|
// Code generated by cmd/gen/sqlc-wrapper. DO NOT EDIT.
|
||||||
package postgres
|
package postgres
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package sqlite
|
package sqlite
|
||||||
|
|
||||||
//go:generate go run github.com/tinyauthapp/tinyauth/gen/sqlc_wrapper -pkg github.com/tinyauthapp/tinyauth/internal/repository/sqlite
|
//go:generate go run github.com/tinyauthapp/tinyauth/gen/sqlc-wrapper -pkg github.com/tinyauthapp/tinyauth/internal/repository/sqlite
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Code generated by cmd/gen/sqlc_wrapper. DO NOT EDIT.
|
// Code generated by cmd/gen/sqlc-wrapper. DO NOT EDIT.
|
||||||
package sqlite
|
package sqlite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
Reference in New Issue
Block a user