Compare commits

..

2 Commits

Author SHA1 Message Date
Stavros
902574e501 refactor: don't create new client everytime 2025-09-19 14:39:24 +03:00
Stavros
aac19d4d5a feat: version info analytics 2025-09-18 19:21:01 +03:00
13 changed files with 37 additions and 58 deletions

View File

@@ -4,6 +4,20 @@ APP_URL=http://localhost:3000
USERS=your_user_password_hash USERS=your_user_password_hash
USERS_FILE=users_file USERS_FILE=users_file
SECURE_COOKIE=false SECURE_COOKIE=false
GITHUB_CLIENT_ID=github_client_id
GITHUB_CLIENT_SECRET=github_client_secret
GITHUB_CLIENT_SECRET_FILE=github_client_secret_file
GOOGLE_CLIENT_ID=google_client_id
GOOGLE_CLIENT_SECRET=google_client_secret
GOOGLE_CLIENT_SECRET_FILE=google_client_secret_file
GENERIC_CLIENT_ID=generic_client_id
GENERIC_CLIENT_SECRET=generic_client_secret
GENERIC_CLIENT_SECRET_FILE=generic_client_secret_file
GENERIC_SCOPES=generic_scopes
GENERIC_AUTH_URL=generic_auth_url
GENERIC_TOKEN_URL=generic_token_url
GENERIC_USER_URL=generic_user_url
DISABLE_CONTINUE=false
OAUTH_WHITELIST= OAUTH_WHITELIST=
GENERIC_NAME=My OAuth GENERIC_NAME=My OAuth
SESSION_EXPIRY=7200 SESSION_EXPIRY=7200
@@ -16,7 +30,4 @@ OAUTH_AUTO_REDIRECT=none
BACKGROUND_IMAGE=some_image_url BACKGROUND_IMAGE=some_image_url
GENERIC_SKIP_SSL=false GENERIC_SKIP_SSL=false
RESOURCES_DIR=/data/resources RESOURCES_DIR=/data/resources
DATABASE_PATH=/data/tinyauth.db DATABASE_PATH=/data/tinyauth.db
DISABLE_ANALYTICS=false
DISABLE_RESOURCES=false
TRUSTED_PROXIES=

View File

@@ -80,7 +80,7 @@ jobs:
- name: Build - name: Build
run: | run: |
cp -r frontend/dist internal/assets/dist cp -r frontend/dist internal/assets/dist
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64 go build -ldflags "-s -w -X tinyauth/internal/constants.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/constants.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/constants.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64
env: env:
CGO_ENABLED: 0 CGO_ENABLED: 0
@@ -126,7 +126,7 @@ jobs:
- name: Build - name: Build
run: | run: |
cp -r frontend/dist internal/assets/dist cp -r frontend/dist internal/assets/dist
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64 go build -ldflags "-s -w -X tinyauth/internal/constants.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/constants.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/constants.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64
env: env:
CGO_ENABLED: 0 CGO_ENABLED: 0

View File

@@ -58,7 +58,7 @@ jobs:
- name: Build - name: Build
run: | run: |
cp -r frontend/dist internal/assets/dist cp -r frontend/dist internal/assets/dist
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64 go build -ldflags "-s -w -X tinyauth/internal/constants.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/constants.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/constants.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64
env: env:
CGO_ENABLED: 0 CGO_ENABLED: 0
@@ -101,7 +101,7 @@ jobs:
- name: Build - name: Build
run: | run: |
cp -r frontend/dist internal/assets/dist cp -r frontend/dist internal/assets/dist
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64 go build -ldflags "-s -w -X tinyauth/internal/constants.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/constants.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/constants.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64
env: env:
CGO_ENABLED: 0 CGO_ENABLED: 0

View File

@@ -38,7 +38,7 @@ 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 CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}" RUN CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/constants.Version=${VERSION} -X tinyauth/internal/constants.CommitHash=${COMMIT_HASH} -X tinyauth/internal/constants.BuildTimestamp=${BUILD_TIMESTAMP}"
# Runner # Runner
FROM alpine:3.22 AS runner FROM alpine:3.22 AS runner

View File

@@ -95,7 +95,6 @@ func init() {
{"database-path", "/data/tinyauth.db", "Path to the Sqlite database file."}, {"database-path", "/data/tinyauth.db", "Path to the Sqlite database file."},
{"trusted-proxies", "", "Comma separated list of trusted proxies (IP addresses or CIDRs) for correct client IP detection."}, {"trusted-proxies", "", "Comma separated list of trusted proxies (IP addresses or CIDRs) for correct client IP detection."},
{"disable-analytics", false, "Disable anonymous version collection."}, {"disable-analytics", false, "Disable anonymous version collection."},
{"disable-resources", false, "Disable the resources server."},
} }
for _, opt := range configOptions { for _, opt := range configOptions {

View File

@@ -70,7 +70,7 @@ var VerifyCmd = &cobra.Command{
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(iPassword)) err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(iPassword))
if err != nil { if err != nil {
log.Fatal().Msg("Password is incorrect") log.Fatal().Msg("Ppassword is incorrect")
} }
if user.TotpSecret == "" { if user.TotpSecret == "" {

View File

@@ -34,10 +34,6 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
args:
- VERSION=development
- COMMIT_HASH=development
- BUILD_TIMESTAMP=000-00-00T00:00:00Z
env_file: .env env_file: .env
volumes: volumes:
- ./internal:/tinyauth/internal - ./internal:/tinyauth/internal

View File

@@ -188,18 +188,14 @@ func (app *BootstrapApp) Setup() error {
} }
// Create engine // Create engine
if config.Version != "development" {
gin.SetMode(gin.ReleaseMode)
}
engine := gin.New() engine := gin.New()
if len(app.config.TrustedProxies) > 0 { if len(app.config.TrustedProxies) > 0 {
err := engine.SetTrustedProxies(strings.Split(app.config.TrustedProxies, ",")) engine.SetTrustedProxies(strings.Split(app.config.TrustedProxies, ","))
}
if err != nil { if config.Version != "development" {
return fmt.Errorf("failed to set trusted proxies: %w", err) gin.SetMode(gin.ReleaseMode)
}
} }
// Create middlewares // Create middlewares
@@ -255,8 +251,7 @@ func (app *BootstrapApp) Setup() error {
}, apiRouter, authService) }, apiRouter, authService)
resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{ resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{
ResourcesDir: app.config.ResourcesDir, ResourcesDir: app.config.ResourcesDir,
ResourcesDisabled: app.config.DisableResources,
}, mainRouter) }, mainRouter)
healthController := controller.NewHealthController(apiRouter) healthController := controller.NewHealthController(apiRouter)
@@ -338,8 +333,8 @@ func (app *BootstrapApp) heartbeat() {
res.Body.Close() res.Body.Close()
if res.StatusCode != 200 && res.StatusCode != 201 { if res.StatusCode != 200 {
log.Debug().Str("status", res.Status).Msg("Heartbeat returned non-200/201 status") log.Debug().Str("status", res.Status).Msg("Heartbeat returned non-200 status")
} }
} }
} }

View File

@@ -3,8 +3,8 @@ package config
// Version information, set at build time // Version information, set at build time
var Version = "development" var Version = "development"
var CommitHash = "development" var CommitHash = "n/a"
var BuildTimestamp = "0000-00-00T00:00:00Z" var BuildTimestamp = "n/a"
// Cookie name templates // Cookie name templates
@@ -40,7 +40,6 @@ type Config struct {
DatabasePath string `mapstructure:"database-path" validate:"required"` DatabasePath string `mapstructure:"database-path" validate:"required"`
TrustedProxies string `mapstructure:"trusted-proxies"` TrustedProxies string `mapstructure:"trusted-proxies"`
DisableAnalytics bool `mapstructure:"disable-analytics"` DisableAnalytics bool `mapstructure:"disable-analytics"`
DisableResources bool `mapstructure:"disable-resources"`
} }
// OAuth/OIDC config // OAuth/OIDC config

View File

@@ -7,8 +7,7 @@ import (
) )
type ResourcesControllerConfig struct { type ResourcesControllerConfig struct {
ResourcesDir string ResourcesDir string
ResourcesDisabled bool
} }
type ResourcesController struct { type ResourcesController struct {
@@ -39,12 +38,5 @@ func (controller *ResourcesController) resourcesHandler(c *gin.Context) {
}) })
return return
} }
if controller.config.ResourcesDisabled {
c.JSON(403, gin.H{
"status": 403,
"message": "Resources are disabled",
})
return
}
controller.fileServer.ServeHTTP(c.Writer, c.Request) controller.fileServer.ServeHTTP(c.Writer, c.Request)
} }

View File

@@ -50,7 +50,7 @@ func (broker *OAuthBrokerService) Init() error {
log.Error().Err(err).Msgf("Failed to initialize OAuth service: %T", name) log.Error().Err(err).Msgf("Failed to initialize OAuth service: %T", name)
return err return err
} }
log.Info().Str("service", service.GetName()).Msg("Initialized OAuth service") log.Info().Msgf("Initialized OAuth service: %T", name)
} }
return nil return nil

View File

@@ -18,14 +18,10 @@ func NormalizeKeys(keys map[string]string, rootName string, sep string) map[stri
finalKey = append(finalKey, rootName) finalKey = append(finalKey, rootName)
finalKey = append(finalKey, "providers") finalKey = append(finalKey, "providers")
lowerKey := strings.ToLower(k) cebabKey := strings.ToLower(k)
if !strings.HasPrefix(lowerKey, "providers"+sep) {
continue
}
for _, known := range knownKeys { for _, known := range knownKeys {
if strings.HasSuffix(lowerKey, strings.ReplaceAll(known, "-", sep)) { if strings.HasSuffix(cebabKey, strings.ReplaceAll(known, "-", sep)) {
suffix = known suffix = known
break break
} }
@@ -35,11 +31,7 @@ func NormalizeKeys(keys map[string]string, rootName string, sep string) map[stri
continue continue
} }
if strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(lowerKey, "providers"+sep), strings.ReplaceAll(suffix, "-", sep))) == "" { clientNameParts := strings.Split(strings.TrimPrefix(strings.TrimSuffix(cebabKey, sep+strings.ReplaceAll(suffix, "-", sep)), "providers"+sep), sep)
continue
}
clientNameParts := strings.Split(strings.TrimPrefix(strings.TrimSuffix(lowerKey, sep+strings.ReplaceAll(suffix, "-", sep)), "providers"+sep), sep)
for i, p := range clientNameParts { for i, p := range clientNameParts {
if i == 0 { if i == 0 {
@@ -54,9 +46,9 @@ func NormalizeKeys(keys map[string]string, rootName string, sep string) map[stri
finalKey = append(finalKey, camelClientName) finalKey = append(finalKey, camelClientName)
fieldParts := strings.Split(suffix, "-") filedParts := strings.Split(suffix, "-")
for i, p := range fieldParts { for i, p := range filedParts {
if i == 0 { if i == 0 {
camelField += p camelField += p
continue continue

View File

@@ -14,8 +14,6 @@ func TestNormalizeKeys(t *testing.T) {
"PROVIDERS_CLIENT1_CLIENT_SECRET": "my-client-secret", "PROVIDERS_CLIENT1_CLIENT_SECRET": "my-client-secret",
"PROVIDERS_MY_AWESOME_CLIENT_CLIENT_ID": "my-awesome-client-id", "PROVIDERS_MY_AWESOME_CLIENT_CLIENT_ID": "my-awesome-client-id",
"PROVIDERS_MY_AWESOME_CLIENT_CLIENT_SECRET_FILE": "/path/to/secret", "PROVIDERS_MY_AWESOME_CLIENT_CLIENT_SECRET_FILE": "/path/to/secret",
"I_LOOK_LIKE_A_KEY_CLIENT_ID": "should-not-appear",
"PROVIDERS_CLIENT_ID": "should-not-appear",
} }
expected := map[string]string{ expected := map[string]string{
"tinyauth.providers.client1.clientId": "my-client-id", "tinyauth.providers.client1.clientId": "my-client-id",
@@ -33,9 +31,6 @@ func TestNormalizeKeys(t *testing.T) {
"providers-client1-client-secret": "my-client-secret", "providers-client1-client-secret": "my-client-secret",
"providers-my-awesome-client-client-id": "my-awesome-client-id", "providers-my-awesome-client-client-id": "my-awesome-client-id",
"providers-my-awesome-client-client-secret-file": "/path/to/secret", "providers-my-awesome-client-client-secret-file": "/path/to/secret",
"providers-should-not-appear-client": "should-not-appear",
"i-look-like-a-key-client-id": "should-not-appear",
"providers-client-id": "should-not-appear",
} }
expected = map[string]string{ expected = map[string]string{
"tinyauth.providers.client1.clientId": "my-client-id", "tinyauth.providers.client1.clientId": "my-client-id",