mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-11-03 23:55:44 +00:00 
			
		
		
		
	Compare commits
	
		
			13 Commits
		
	
	
		
			cbe31d442d
			...
			docs/updat
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f79c3f6ca1 | ||
| 
						 | 
					5a4855c12c | ||
| 
						 | 
					05d4dbd68e | ||
| 
						 | 
					ae8347fd28 | ||
| 
						 | 
					76f2014444 | ||
| 
						 | 
					5b7bda3378 | ||
| 
						 | 
					e878516130 | ||
| 
						 | 
					e5f1df03c4 | ||
| 
						 | 
					c77da30d87 | ||
| 
						 | 
					287c6f975f | ||
| 
						 | 
					0255e954f7 | ||
| 
						 | 
					c5d70d7c93 | ||
| 
						 | 
					adffb4ac0a | 
							
								
								
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -23,7 +23,7 @@ jobs:
 | 
				
			|||||||
      - name: Install frontend dependencies
 | 
					      - name: Install frontend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          cd frontend
 | 
					          cd frontend
 | 
				
			||||||
          bun install
 | 
					          bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set version
 | 
					      - name: Set version
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							@@ -66,7 +66,7 @@ jobs:
 | 
				
			|||||||
      - name: Install frontend dependencies
 | 
					      - name: Install frontend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          cd frontend
 | 
					          cd frontend
 | 
				
			||||||
          bun install
 | 
					          bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Install backend dependencies
 | 
					      - name: Install backend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
@@ -112,7 +112,7 @@ jobs:
 | 
				
			|||||||
      - name: Install frontend dependencies
 | 
					      - name: Install frontend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          cd frontend
 | 
					          cd frontend
 | 
				
			||||||
          bun install
 | 
					          bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Install backend dependencies
 | 
					      - name: Install backend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
@@ -396,6 +396,8 @@ jobs:
 | 
				
			|||||||
        uses: docker/metadata-action@v5
 | 
					        uses: docker/metadata-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
					          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
				
			||||||
 | 
					          flavor: |
 | 
				
			||||||
 | 
					            latest=false
 | 
				
			||||||
          tags: |
 | 
					          tags: |
 | 
				
			||||||
            type=raw,nightly
 | 
					            type=raw,nightly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -433,6 +435,8 @@ jobs:
 | 
				
			|||||||
        uses: docker/metadata-action@v5
 | 
					        uses: docker/metadata-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
					          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
				
			||||||
 | 
					          flavor: |
 | 
				
			||||||
 | 
					            latest=false
 | 
				
			||||||
          tags: |
 | 
					          tags: |
 | 
				
			||||||
            type=raw,nightly-distroless
 | 
					            type=raw,nightly-distroless
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -44,7 +44,7 @@ jobs:
 | 
				
			|||||||
      - name: Install frontend dependencies
 | 
					      - name: Install frontend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          cd frontend
 | 
					          cd frontend
 | 
				
			||||||
          bun install
 | 
					          bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Install backend dependencies
 | 
					      - name: Install backend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
@@ -87,7 +87,7 @@ jobs:
 | 
				
			|||||||
      - name: Install frontend dependencies
 | 
					      - name: Install frontend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          cd frontend
 | 
					          cd frontend
 | 
				
			||||||
          bun install
 | 
					          bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Install backend dependencies
 | 
					      - name: Install backend dependencies
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
@@ -359,10 +359,13 @@ jobs:
 | 
				
			|||||||
        uses: docker/metadata-action@v5
 | 
					        uses: docker/metadata-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
					          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
				
			||||||
 | 
					          flavor: |
 | 
				
			||||||
 | 
					            latest=true
 | 
				
			||||||
 | 
					            prefix=v,onlatest=false
 | 
				
			||||||
          tags: |
 | 
					          tags: |
 | 
				
			||||||
            type=semver,pattern={{version}},prefix=v
 | 
					            type=semver,pattern={{version}}
 | 
				
			||||||
            type=semver,pattern={{major}},prefix=v
 | 
					            type=semver,pattern={{major}}
 | 
				
			||||||
            type=semver,pattern={{major}}.{{minor}},prefix=v
 | 
					            type=semver,pattern={{major}}.{{minor}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Create manifest list and push
 | 
					      - name: Create manifest list and push
 | 
				
			||||||
        working-directory: ${{ runner.temp }}/digests
 | 
					        working-directory: ${{ runner.temp }}/digests
 | 
				
			||||||
@@ -398,10 +401,14 @@ jobs:
 | 
				
			|||||||
        uses: docker/metadata-action@v5
 | 
					        uses: docker/metadata-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
					          images: ghcr.io/${{ github.repository_owner }}/tinyauth
 | 
				
			||||||
 | 
					          flavor: |
 | 
				
			||||||
 | 
					            latest=false
 | 
				
			||||||
 | 
					            prefix=v,onlatest=false
 | 
				
			||||||
 | 
					            suffix=-distroless,onlatest=false
 | 
				
			||||||
          tags: |
 | 
					          tags: |
 | 
				
			||||||
            type=semver,pattern={{version}},prefix=v,suffix=-distroless
 | 
					            type=semver,pattern={{version}}
 | 
				
			||||||
            type=semver,pattern={{major}},prefix=v,suffix=-distroless
 | 
					            type=semver,pattern={{major}}
 | 
				
			||||||
            type=semver,pattern={{major}}.{{minor}},prefix=v,suffix=-distroless
 | 
					            type=semver,pattern={{major}}.{{minor}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Create manifest list and push
 | 
					      - name: Create manifest list and push
 | 
				
			||||||
        working-directory: ${{ runner.temp }}/digests
 | 
					        working-directory: ${{ runner.temp }}/digests
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -6,7 +6,7 @@ WORKDIR /frontend
 | 
				
			|||||||
COPY ./frontend/package.json ./
 | 
					COPY ./frontend/package.json ./
 | 
				
			||||||
COPY ./frontend/bun.lock ./
 | 
					COPY ./frontend/bun.lock ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN bun install
 | 
					RUN bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY ./frontend/public ./public
 | 
					COPY ./frontend/public ./public
 | 
				
			||||||
COPY ./frontend/src ./src
 | 
					COPY ./frontend/src ./src
 | 
				
			||||||
@@ -47,10 +47,16 @@ WORKDIR /tinyauth
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
COPY --from=builder /tinyauth/tinyauth ./
 | 
					COPY --from=builder /tinyauth/tinyauth ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN mkdir -p /data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPOSE 3000
 | 
					EXPOSE 3000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VOLUME ["/data"]
 | 
					VOLUME ["/data"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 CMD ["/tinyauth/tinyauth", "healthcheck"]
 | 
					ENV GIN_MODE=release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRYPOINT ["/tinyauth/tinyauth"]
 | 
					ENV PATH=$PATH:/tinyauth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 CMD ["tinyauth", "healthcheck"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTRYPOINT ["tinyauth"]
 | 
				
			||||||
@@ -6,7 +6,7 @@ WORKDIR /frontend
 | 
				
			|||||||
COPY ./frontend/package.json ./
 | 
					COPY ./frontend/package.json ./
 | 
				
			||||||
COPY ./frontend/bun.lock ./
 | 
					COPY ./frontend/bun.lock ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN bun install
 | 
					RUN bun install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY ./frontend/public ./public
 | 
					COPY ./frontend/public ./public
 | 
				
			||||||
COPY ./frontend/src ./src
 | 
					COPY ./frontend/src ./src
 | 
				
			||||||
@@ -38,6 +38,8 @@ 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 "-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/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}" 
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
# Runner
 | 
					# Runner
 | 
				
			||||||
@@ -47,10 +49,17 @@ 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
 | 
				
			||||||
 | 
					COPY --from=builder /tinyauth/data /data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPOSE 3000
 | 
					EXPOSE 3000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VOLUME ["/data"]
 | 
					VOLUME ["/data"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 CMD ["/tinyauth/tinyauth", "healthcheck"]
 | 
					ENV GIN_MODE=release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRYPOINT ["/tinyauth/tinyauth"]
 | 
					ENV PATH=$PATH:/tinyauth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 CMD ["tinyauth", "healthcheck"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTRYPOINT ["tinyauth"]
 | 
				
			||||||
@@ -53,7 +53,7 @@ Tinyauth is licensed under the GNU General Public License v3.0. TL;DR — You ma
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
A big thank you to the following people for providing me with more coffee:
 | 
					A big thank you to the following people for providing me with more coffee:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- sponsors --><a href="https://github.com/erwinkramer"><img src="https://github.com/erwinkramer.png" width="64px" alt="User avatar: erwinkramer" /></a>  <a href="https://github.com/nicotsx"><img src="https://github.com/nicotsx.png" width="64px" alt="User avatar: nicotsx" /></a>  <a href="https://github.com/SimpleHomelab"><img src="https://github.com/SimpleHomelab.png" width="64px" alt="User avatar: SimpleHomelab" /></a>  <a href="https://github.com/jmadden91"><img src="https://github.com/jmadden91.png" width="64px" alt="User avatar: jmadden91" /></a>  <a href="https://github.com/tribor"><img src="https://github.com/tribor.png" width="64px" alt="User avatar: tribor" /></a>  <a href="https://github.com/eliasbenb"><img src="https://github.com/eliasbenb.png" width="64px" alt="User avatar: eliasbenb" /></a>  <a href="https://github.com/afunworm"><img src="https://github.com/afunworm.png" width="64px" alt="User avatar: afunworm" /></a>  <!-- sponsors -->
 | 
					<!-- sponsors --><a href="https://github.com/erwinkramer"><img src="https://github.com/erwinkramer.png" width="64px" alt="User avatar: erwinkramer" /></a>  <a href="https://github.com/nicotsx"><img src="https://github.com/nicotsx.png" width="64px" alt="User avatar: nicotsx" /></a>  <a href="https://github.com/SimpleHomelab"><img src="https://github.com/SimpleHomelab.png" width="64px" alt="User avatar: SimpleHomelab" /></a>  <a href="https://github.com/jmadden91"><img src="https://github.com/jmadden91.png" width="64px" alt="User avatar: jmadden91" /></a>  <a href="https://github.com/tribor"><img src="https://github.com/tribor.png" width="64px" alt="User avatar: tribor" /></a>  <a href="https://github.com/eliasbenb"><img src="https://github.com/eliasbenb.png" width="64px" alt="User avatar: eliasbenb" /></a>  <a href="https://github.com/afunworm"><img src="https://github.com/afunworm.png" width="64px" alt="User avatar: afunworm" /></a>  <a href="https://github.com/chip-well"><img src="https://github.com/chip-well.png" width="64px" alt="User avatar: chip-well" /></a>  <a href="https://github.com/Lancelot-Enguerrand"><img src="https://github.com/Lancelot-Enguerrand.png" width="64px" alt="User avatar: Lancelot-Enguerrand" /></a>  <!-- sponsors -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Acknowledgements
 | 
					## Acknowledgements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								air.toml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								air.toml
									
									
									
									
									
								
							@@ -2,7 +2,7 @@ root = "/tinyauth"
 | 
				
			|||||||
tmp_dir = "tmp"
 | 
					tmp_dir = "tmp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[build]
 | 
					[build]
 | 
				
			||||||
pre_cmd = ["mkdir -p internal/assets/dist", "echo 'backend running' > internal/assets/dist/index.html", "go install github.com/go-delve/delve/cmd/dlv@v1.25.0"]
 | 
					pre_cmd = ["mkdir -p internal/assets/dist", "mkdir -p /data", "echo 'backend running' > internal/assets/dist/index.html", "go install github.com/go-delve/delve/cmd/dlv@v1.25.0"]
 | 
				
			||||||
cmd = "CGO_ENABLED=0 go build -gcflags=\"all=-N -l\" -o tmp/tinyauth ."
 | 
					cmd = "CGO_ENABLED=0 go build -gcflags=\"all=-N -l\" -o tmp/tinyauth ."
 | 
				
			||||||
bin = "/go/bin/dlv --listen :4000 --headless=true --api-version=2 --accept-multiclient --log=true exec tmp/tinyauth --continue --check-go-version=false"
 | 
					bin = "/go/bin/dlv --listen :4000 --headless=true --api-version=2 --accept-multiclient --log=true exec tmp/tinyauth --continue --check-go-version=false"
 | 
				
			||||||
include_ext = ["go"]
 | 
					include_ext = ["go"]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
    <link rel="shortcut icon" href="/favicon.ico" />
 | 
					    <link rel="shortcut icon" href="/favicon.ico" />
 | 
				
			||||||
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
 | 
					    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
 | 
				
			||||||
    <meta name="apple-mobile-web-app-title" content="Tinyauth" />
 | 
					    <meta name="apple-mobile-web-app-title" content="Tinyauth" />
 | 
				
			||||||
    <meta name="robots" content="none" />
 | 
					    <meta name="robots" content="nofollow, noindex" />
 | 
				
			||||||
    <link rel="manifest" href="/site.webmanifest" />
 | 
					    <link rel="manifest" href="/site.webmanifest" />
 | 
				
			||||||
    <title>Tinyauth</title>
 | 
					    <title>Tinyauth</title>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,15 @@
 | 
				
			|||||||
import { useAppContext } from "@/context/app-context";
 | 
					import { useAppContext } from "@/context/app-context";
 | 
				
			||||||
import { LanguageSelector } from "../language/language";
 | 
					import { LanguageSelector } from "../language/language";
 | 
				
			||||||
import { Outlet } from "react-router";
 | 
					import { Outlet } from "react-router";
 | 
				
			||||||
import { useCallback, useState } from "react";
 | 
					import { useCallback, useEffect, useState } from "react";
 | 
				
			||||||
import { DomainWarning } from "../domain-warning/domain-warning";
 | 
					import { DomainWarning } from "../domain-warning/domain-warning";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const BaseLayout = ({ children }: { children: React.ReactNode }) => {
 | 
					const BaseLayout = ({ children }: { children: React.ReactNode }) => {
 | 
				
			||||||
  const { backgroundImage } = useAppContext();
 | 
					  const { backgroundImage, title } = useAppContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    document.title = title;
 | 
				
			||||||
 | 
					  }, [title]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div
 | 
					    <div
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -150,18 +150,6 @@ func (app *BootstrapApp) Setup() error {
 | 
				
			|||||||
	configuredProviders := make([]controller.Provider, 0)
 | 
						configuredProviders := make([]controller.Provider, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for id, provider := range oauthProviders {
 | 
						for id, provider := range oauthProviders {
 | 
				
			||||||
		if id == "" {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if provider.Name == "" {
 | 
					 | 
				
			||||||
			if name, ok := config.OverrideProviders[id]; ok {
 | 
					 | 
				
			||||||
				provider.Name = name
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				provider.Name = utils.Capitalize(id)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		configuredProviders = append(configuredProviders, controller.Provider{
 | 
							configuredProviders = append(configuredProviders, controller.Provider{
 | 
				
			||||||
			Name:  provider.Name,
 | 
								Name:  provider.Name,
 | 
				
			||||||
			ID:    id,
 | 
								ID:    id,
 | 
				
			||||||
@@ -184,10 +172,6 @@ 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 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,12 @@
 | 
				
			|||||||
package middleware
 | 
					package middleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io/fs"
 | 
						"io/fs"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
	"tinyauth/internal/assets"
 | 
						"tinyauth/internal/assets"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
@@ -27,14 +29,16 @@ func (m *UIMiddleware) Init() error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.uiFs = ui
 | 
						m.uiFs = ui
 | 
				
			||||||
	m.uiFileServer = http.FileServer(http.FS(ui))
 | 
						m.uiFileServer = http.FileServerFS(ui)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *UIMiddleware) Middleware() gin.HandlerFunc {
 | 
					func (m *UIMiddleware) Middleware() gin.HandlerFunc {
 | 
				
			||||||
	return func(c *gin.Context) {
 | 
						return func(c *gin.Context) {
 | 
				
			||||||
		switch strings.Split(c.Request.URL.Path, "/")[1] {
 | 
							path := strings.TrimPrefix(c.Request.URL.Path, "/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch strings.SplitN(path, "/", 2)[0] {
 | 
				
			||||||
		case "api":
 | 
							case "api":
 | 
				
			||||||
			c.Next()
 | 
								c.Next()
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -42,12 +46,19 @@ func (m *UIMiddleware) Middleware() gin.HandlerFunc {
 | 
				
			|||||||
			c.Next()
 | 
								c.Next()
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			_, err := fs.Stat(m.uiFs, strings.TrimPrefix(c.Request.URL.Path, "/"))
 | 
								_, err := fs.Stat(m.uiFs, path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Enough for one authentication flow
 | 
				
			||||||
 | 
								maxAge := 15 * time.Minute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if os.IsNotExist(err) {
 | 
								if os.IsNotExist(err) {
 | 
				
			||||||
				c.Request.URL.Path = "/"
 | 
									c.Request.URL.Path = "/"
 | 
				
			||||||
 | 
								} else if strings.HasPrefix(path, "assets/") {
 | 
				
			||||||
 | 
									// assets are named with a hash and can be cached for a long time
 | 
				
			||||||
 | 
									maxAge = 30 * 24 * time.Hour
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								c.Writer.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", int(maxAge.Seconds())))
 | 
				
			||||||
			m.uiFileServer.ServeHTTP(c.Writer, c.Request)
 | 
								m.uiFileServer.ServeHTTP(c.Writer, c.Request)
 | 
				
			||||||
			c.Abort()
 | 
								c.Abort()
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@ import (
 | 
				
			|||||||
type DockerService struct {
 | 
					type DockerService struct {
 | 
				
			||||||
	client      *client.Client
 | 
						client      *client.Client
 | 
				
			||||||
	context     context.Context
 | 
						context     context.Context
 | 
				
			||||||
 | 
						isConnected bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewDockerService() *DockerService {
 | 
					func NewDockerService() *DockerService {
 | 
				
			||||||
@@ -31,10 +32,24 @@ func (docker *DockerService) Init() error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	docker.client = client
 | 
						docker.client = client
 | 
				
			||||||
	docker.context = ctx
 | 
						docker.context = ctx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = docker.client.Ping(docker.context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Debug().Err(err).Msg("Docker not connected")
 | 
				
			||||||
 | 
							docker.isConnected = false
 | 
				
			||||||
 | 
							docker.client = nil
 | 
				
			||||||
 | 
							docker.context = nil
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						docker.isConnected = true
 | 
				
			||||||
 | 
						log.Debug().Msg("Docker connected")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (docker *DockerService) GetContainers() ([]container.Summary, error) {
 | 
					func (docker *DockerService) getContainers() ([]container.Summary, error) {
 | 
				
			||||||
	containers, err := docker.client.ContainerList(docker.context, container.ListOptions{})
 | 
						containers, err := docker.client.ContainerList(docker.context, container.ListOptions{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -42,7 +57,7 @@ func (docker *DockerService) GetContainers() ([]container.Summary, error) {
 | 
				
			|||||||
	return containers, nil
 | 
						return containers, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (docker *DockerService) InspectContainer(containerId string) (container.InspectResponse, error) {
 | 
					func (docker *DockerService) inspectContainer(containerId string) (container.InspectResponse, error) {
 | 
				
			||||||
	inspect, err := docker.client.ContainerInspect(docker.context, containerId)
 | 
						inspect, err := docker.client.ContainerInspect(docker.context, containerId)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return container.InspectResponse{}, err
 | 
							return container.InspectResponse{}, err
 | 
				
			||||||
@@ -50,35 +65,26 @@ func (docker *DockerService) InspectContainer(containerId string) (container.Ins
 | 
				
			|||||||
	return inspect, nil
 | 
						return inspect, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (docker *DockerService) DockerConnected() bool {
 | 
					 | 
				
			||||||
	_, err := docker.client.Ping(docker.context)
 | 
					 | 
				
			||||||
	return err == nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (docker *DockerService) GetLabels(appDomain string) (config.App, error) {
 | 
					func (docker *DockerService) GetLabels(appDomain string) (config.App, error) {
 | 
				
			||||||
	isConnected := docker.DockerConnected()
 | 
						if !docker.isConnected {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !isConnected {
 | 
					 | 
				
			||||||
		log.Debug().Msg("Docker not connected, returning empty labels")
 | 
							log.Debug().Msg("Docker not connected, returning empty labels")
 | 
				
			||||||
		return config.App{}, nil
 | 
							return config.App{}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	containers, err := docker.GetContainers()
 | 
						containers, err := docker.getContainers()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return config.App{}, err
 | 
							return config.App{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, ctr := range containers {
 | 
						for _, ctr := range containers {
 | 
				
			||||||
		inspect, err := docker.InspectContainer(ctr.ID)
 | 
							inspect, err := docker.inspectContainer(ctr.ID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Warn().Str("id", ctr.ID).Err(err).Msg("Error inspecting container, skipping")
 | 
								return config.App{}, err
 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		labels, err := decoders.DecodeLabels(inspect.Config.Labels)
 | 
							labels, err := decoders.DecodeLabels(inspect.Config.Labels)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Warn().Str("id", ctr.ID).Err(err).Msg("Error getting container labels, skipping")
 | 
								return config.App{}, err
 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for appName, appLabels := range labels.Apps {
 | 
							for appName, appLabels := range labels.Apps {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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().Str("service", name).Msg("Initialized OAuth service")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -184,7 +184,6 @@ func GetOAuthProvidersConfig(env []string, args []string, appUrl string) (map[st
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If we have google/github providers and no redirect URL then set a default
 | 
						// If we have google/github providers and no redirect URL then set a default
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for id := range config.OverrideProviders {
 | 
						for id := range config.OverrideProviders {
 | 
				
			||||||
		if provider, exists := providers[id]; exists {
 | 
							if provider, exists := providers[id]; exists {
 | 
				
			||||||
			if provider.RedirectURL == "" {
 | 
								if provider.RedirectURL == "" {
 | 
				
			||||||
@@ -194,6 +193,18 @@ func GetOAuthProvidersConfig(env []string, args []string, appUrl string) (map[st
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set names
 | 
				
			||||||
 | 
						for id, provider := range providers {
 | 
				
			||||||
 | 
							if provider.Name == "" {
 | 
				
			||||||
 | 
								if name, ok := config.OverrideProviders[id]; ok {
 | 
				
			||||||
 | 
									provider.Name = name
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									provider.Name = Capitalize(id)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							providers[id] = provider
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Return combined providers
 | 
						// Return combined providers
 | 
				
			||||||
	return providers, nil
 | 
						return providers, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -210,10 +210,12 @@ func TestGetOAuthProvidersConfig(t *testing.T) {
 | 
				
			|||||||
		"client1": {
 | 
							"client1": {
 | 
				
			||||||
			ClientID:     "client1-id",
 | 
								ClientID:     "client1-id",
 | 
				
			||||||
			ClientSecret: "client1-secret",
 | 
								ClientSecret: "client1-secret",
 | 
				
			||||||
 | 
								Name:         "Client1",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"client2": {
 | 
							"client2": {
 | 
				
			||||||
			ClientID:     "client2-id",
 | 
								ClientID:     "client2-id",
 | 
				
			||||||
			ClientSecret: "client2-secret",
 | 
								ClientSecret: "client2-secret",
 | 
				
			||||||
 | 
								Name:         "Client2",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -247,6 +249,7 @@ func TestGetOAuthProvidersConfig(t *testing.T) {
 | 
				
			|||||||
		"client1": {
 | 
							"client1": {
 | 
				
			||||||
			ClientID:     "client1-id",
 | 
								ClientID:     "client1-id",
 | 
				
			||||||
			ClientSecret: "file content",
 | 
								ClientSecret: "file content",
 | 
				
			||||||
 | 
								Name:         "Client1",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -262,6 +265,7 @@ func TestGetOAuthProvidersConfig(t *testing.T) {
 | 
				
			|||||||
			ClientID:     "google-id",
 | 
								ClientID:     "google-id",
 | 
				
			||||||
			ClientSecret: "google-secret",
 | 
								ClientSecret: "google-secret",
 | 
				
			||||||
			RedirectURL:  "http://app.url/api/oauth/callback/google",
 | 
								RedirectURL:  "http://app.url/api/oauth/callback/google",
 | 
				
			||||||
 | 
								Name:         "Google",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user