mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-03-02 21:02:03 +00:00
Compare commits
10 Commits
nightly
...
v5.0.0-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
189ad7115a | ||
|
|
2f2556d480 | ||
|
|
f1512f45b7 | ||
|
|
cd410b6cdf | ||
|
|
24c5b35bdf | ||
|
|
0d7daafa35 | ||
|
|
414fab11fb | ||
|
|
ced28a0045 | ||
|
|
c48181a8d8 | ||
|
|
06a26e976b |
31
.env.example
31
.env.example
@@ -4,14 +4,23 @@
|
||||
|
||||
# The base URL where the app is hosted.
|
||||
TINYAUTH_APPURL=
|
||||
|
||||
# database config
|
||||
|
||||
# The path to the database, including file name.
|
||||
TINYAUTH_DATABASE_PATH="./tinyauth.db"
|
||||
|
||||
# analytics config
|
||||
|
||||
# Enable periodic version information collection.
|
||||
TINYAUTH_ANALYTICS_ENABLED=true
|
||||
|
||||
# resources config
|
||||
|
||||
# Enable the resources server.
|
||||
TINYAUTH_RESOURCES_ENABLED=true
|
||||
# The directory where resources are stored.
|
||||
TINYAUTH_RESOURCESDIR="./resources"
|
||||
# The path to the database file.
|
||||
TINYAUTH_DATABASEPATH="./tinyauth.db"
|
||||
# Disable analytics.
|
||||
TINYAUTH_DISABLEANALYTICS=false
|
||||
# Disable resources server.
|
||||
TINYAUTH_DISABLERESOURCES=false
|
||||
TINYAUTH_RESOURCES_PATH="./resources"
|
||||
|
||||
# server config
|
||||
|
||||
@@ -107,9 +116,9 @@ TINYAUTH_OAUTH_PROVIDERS_name_NAME=
|
||||
|
||||
# oidc config
|
||||
|
||||
# Path to the private key file.
|
||||
# Path to the private key file, including file name.
|
||||
TINYAUTH_OIDC_PRIVATEKEYPATH="./tinyauth_oidc_key"
|
||||
# Path to the public key file.
|
||||
# Path to the public key file, including file name.
|
||||
TINYAUTH_OIDC_PUBLICKEYPATH="./tinyauth_oidc_key.pub"
|
||||
# OIDC client ID.
|
||||
TINYAUTH_OIDC_CLIENTS_name_CLIENTID=
|
||||
@@ -130,8 +139,8 @@ TINYAUTH_UI_TITLE="Tinyauth"
|
||||
TINYAUTH_UI_FORGOTPASSWORDMESSAGE="You can change your password by changing the configuration."
|
||||
# Path to the background image.
|
||||
TINYAUTH_UI_BACKGROUNDIMAGE="/background.jpg"
|
||||
# Disable UI warnings.
|
||||
TINYAUTH_UI_DISABLEWARNINGS=false
|
||||
# Enable UI warnings.
|
||||
TINYAUTH_UI_WARNINGSENABLED=true
|
||||
|
||||
# ldap config
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ EXPOSE 3000
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
||||
ENV TINYAUTH_DATABASEPATH=/data/tinyauth.db
|
||||
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db
|
||||
|
||||
ENV TINYAUTH_RESOURCESDIR=/data/resources
|
||||
ENV TINYAUTH_RESOURCES_PATH=/data/resources
|
||||
|
||||
ENV PATH=$PATH:/tinyauth
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ COPY ./air.toml ./
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV TINYAUTH_DATABASEPATH=/data/tinyauth.db
|
||||
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db
|
||||
|
||||
ENV TINYAUTH_RESOURCESDIR=/data/resources
|
||||
ENV TINYAUTH_RESOURCES_PATH=/data/resources
|
||||
|
||||
ENTRYPOINT ["air", "-c", "air.toml"]
|
||||
|
||||
@@ -60,9 +60,9 @@ EXPOSE 3000
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
||||
ENV TINYAUTH_DATABASEPATH=/data/tinyauth.db
|
||||
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db
|
||||
|
||||
ENV TINYAUTH_RESOURCESDIR=/data/resources
|
||||
ENV TINYAUTH_RESOURCES_PATH=/data/resources
|
||||
|
||||
ENV PATH=$PATH:/tinyauth
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"axios": "^1.13.5",
|
||||
"axios": "^1.13.6",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"i18next": "^25.8.13",
|
||||
"i18next-browser-languagedetector": "^8.2.1",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"input-otp": "^1.4.2",
|
||||
"lucide-react": "^0.575.0",
|
||||
"lucide-react": "^0.576.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"radix-ui": "^1.4.3",
|
||||
"react": "^19.2.4",
|
||||
@@ -37,14 +37,14 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@tanstack/eslint-plugin-query": "^5.91.4",
|
||||
"@types/node": "^25.3.2",
|
||||
"@types/node": "^25.3.3",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"eslint": "^10.0.2",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"globals": "^17.3.0",
|
||||
"globals": "^17.4.0",
|
||||
"prettier": "3.8.1",
|
||||
"rollup-plugin-visualizer": "^7.0.0",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
@@ -417,7 +417,7 @@
|
||||
|
||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||
|
||||
"@types/node": ["@types/node@25.3.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-RpV6r/ij22zRRdyBPcxDeKAzH43phWVKEjL2iksqo1Vz3CuBUrgmPpPhALKiRfU7OMCmeeO9vECBMsV0hMTG8Q=="],
|
||||
"@types/node": ["@types/node@25.3.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||
|
||||
@@ -463,7 +463,7 @@
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],
|
||||
"axios": ["axios@1.13.6", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ=="],
|
||||
|
||||
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
|
||||
|
||||
@@ -613,7 +613,7 @@
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"globals": ["globals@17.3.0", "", {}, "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw=="],
|
||||
"globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
@@ -723,7 +723,7 @@
|
||||
|
||||
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
"lucide-react": ["lucide-react@0.575.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg=="],
|
||||
"lucide-react": ["lucide-react@0.576.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-koNxU14BXrxUfZQ9cUaP0ES1uyPZKYDjk31FQZB6dQ/x+tXk979sVAn9ppZ/pVeJJyOxVM8j1E+8QEuSc02Vug=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"axios": "^1.13.5",
|
||||
"axios": "^1.13.6",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"i18next": "^25.8.13",
|
||||
"i18next-browser-languagedetector": "^8.2.1",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"input-otp": "^1.4.2",
|
||||
"lucide-react": "^0.575.0",
|
||||
"lucide-react": "^0.576.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"radix-ui": "^1.4.3",
|
||||
"react": "^19.2.4",
|
||||
@@ -43,14 +43,14 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@tanstack/eslint-plugin-query": "^5.91.4",
|
||||
"@types/node": "^25.3.2",
|
||||
"@types/node": "^25.3.3",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"eslint": "^10.0.2",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"globals": "^17.3.0",
|
||||
"globals": "^17.4.0",
|
||||
"prettier": "3.8.1",
|
||||
"rollup-plugin-visualizer": "^7.0.0",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
|
||||
@@ -43,7 +43,7 @@ export const LoginForm = (props: Props) => {
|
||||
<FormLabel className="mb-2">{t("loginUsername")}</FormLabel>
|
||||
<FormControl className="mb-1">
|
||||
<Input
|
||||
placeholder={t("loginUsername")}
|
||||
placeholder={t("loginUsername").toLocaleLowerCase()}
|
||||
disabled={loading}
|
||||
autoComplete="username"
|
||||
{...field}
|
||||
@@ -62,7 +62,7 @@ export const LoginForm = (props: Props) => {
|
||||
<FormLabel className="mb-2">{t("loginPassword")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder={t("loginPassword")}
|
||||
placeholder={t("loginPassword").toLowerCase()}
|
||||
type="password"
|
||||
disabled={loading}
|
||||
autoComplete="current-password"
|
||||
|
||||
@@ -31,7 +31,7 @@ const BaseLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
};
|
||||
|
||||
export const Layout = () => {
|
||||
const { appUrl, disableUiWarnings } = useAppContext();
|
||||
const { appUrl, warningsEnabled } = useAppContext();
|
||||
const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(() => {
|
||||
return window.sessionStorage.getItem("ignoreDomainWarning") === "true";
|
||||
});
|
||||
@@ -42,7 +42,7 @@ export const Layout = () => {
|
||||
setIgnoreDomainWarning(true);
|
||||
}, [setIgnoreDomainWarning]);
|
||||
|
||||
if (!ignoreDomainWarning && !disableUiWarnings && appUrl !== currentUrl) {
|
||||
if (!ignoreDomainWarning && warningsEnabled && appUrl !== currentUrl) {
|
||||
return (
|
||||
<BaseLayout>
|
||||
<DomainWarning
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
"invalidInput": "Ongeldige invoer",
|
||||
"domainWarningTitle": "Ongeldig domein",
|
||||
"domainWarningSubtitle": "Deze instantie is geconfigureerd voor toegang tot <code>{{appUrl}}</code>, maar <code>{{currentUrl}}</code> wordt gebruikt. Als je doorgaat, kun je problemen ondervinden met authenticatie.",
|
||||
"domainWarningCurrent": "Current:",
|
||||
"domainWarningExpected": "Expected:",
|
||||
"domainWarningCurrent": "Huidige:",
|
||||
"domainWarningExpected": "Verwachte:",
|
||||
"ignoreTitle": "Negeren",
|
||||
"goToCorrectDomainTitle": "Ga naar het juiste domein",
|
||||
"authorizeTitle": "Autoriseren",
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
"invalidInput": "Nieprawidłowe dane wejściowe",
|
||||
"domainWarningTitle": "Nieprawidłowa domena",
|
||||
"domainWarningSubtitle": "Ta instancja jest skonfigurowana do uzyskania dostępu z <code>{{appUrl}}</code>, ale <code>{{currentUrl}}</code> jest w użyciu. Jeśli będziesz kontynuować, mogą wystąpić problemy z uwierzytelnianiem.",
|
||||
"domainWarningCurrent": "Current:",
|
||||
"domainWarningExpected": "Expected:",
|
||||
"domainWarningCurrent": "Bieżąca:",
|
||||
"domainWarningExpected": "Oczekiwana:",
|
||||
"ignoreTitle": "Zignoruj",
|
||||
"goToCorrectDomainTitle": "Przejdź do prawidłowej domeny",
|
||||
"authorizeTitle": "Autoryzuj",
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
"invalidInput": "Неисправан унос",
|
||||
"domainWarningTitle": "Неисправан домен",
|
||||
"domainWarningSubtitle": "Ова инстанца је подешена да јој се приступа са <code>{{appUrl}}</code>, али се користи <code>{{currentUrl}}</code>. Ако наставите, можете искусити проблеме са аутентификацијом.",
|
||||
"domainWarningCurrent": "Current:",
|
||||
"domainWarningExpected": "Expected:",
|
||||
"domainWarningCurrent": "Тренутни:",
|
||||
"domainWarningExpected": "Очекивани:",
|
||||
"ignoreTitle": "Игнориши",
|
||||
"goToCorrectDomainTitle": "Иди на исправан домен",
|
||||
"authorizeTitle": "Ауторизуј",
|
||||
|
||||
@@ -155,7 +155,7 @@ export const AuthorizePage = () => {
|
||||
<Card>
|
||||
<CardHeader className="mb-2">
|
||||
<div className="flex flex-col gap-3 items-center justify-center text-center">
|
||||
<div className="bg-accent-foreground text-muted text-xl font-bold font-sans rounded-lg px-4 py-3">
|
||||
<div className="bg-accent-foreground box-content text-muted text-xl font-bold font-sans rounded-lg size-10 p-2 flex items-center justify-center">
|
||||
{getClientInfo.data?.name.slice(0, 1)}
|
||||
</div>
|
||||
<CardTitle className="text-xl">
|
||||
@@ -170,8 +170,8 @@ export const AuthorizePage = () => {
|
||||
</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="mb-2">
|
||||
{scopes.includes("openid") && (
|
||||
{scopes.includes("openid") && (
|
||||
<CardContent className="mb-2">
|
||||
<div className="flex flex-wrap gap-2 items-center justify-center">
|
||||
{scopes.map((id) => {
|
||||
const scope = scopeMap.find((s) => s.id === id);
|
||||
@@ -189,8 +189,8 @@ export const AuthorizePage = () => {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</CardContent>
|
||||
)}
|
||||
<CardFooter className="flex flex-col items-stretch gap-3">
|
||||
<Button
|
||||
onClick={() => authorizeMutation.mutate()}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useRedirectUri } from "@/lib/hooks/redirect-uri";
|
||||
|
||||
export const ContinuePage = () => {
|
||||
const { cookieDomain, disableUiWarnings } = useAppContext();
|
||||
const { cookieDomain, warningsEnabled } = useAppContext();
|
||||
const { isLoggedIn } = useUserContext();
|
||||
const { search } = useLocation();
|
||||
const { t } = useTranslation();
|
||||
@@ -35,10 +35,9 @@ export const ContinuePage = () => {
|
||||
const urlHref = url?.href;
|
||||
|
||||
const hasValidRedirect = valid && allowedProto;
|
||||
const showUntrustedWarning =
|
||||
hasValidRedirect && !trusted && !disableUiWarnings;
|
||||
const showUntrustedWarning = hasValidRedirect && !trusted && warningsEnabled;
|
||||
const showInsecureWarning =
|
||||
hasValidRedirect && httpsDowngrade && !disableUiWarnings;
|
||||
hasValidRedirect && httpsDowngrade && warningsEnabled;
|
||||
const shouldAutoRedirect =
|
||||
isLoggedIn &&
|
||||
hasValidRedirect &&
|
||||
|
||||
@@ -258,13 +258,13 @@ export const LoginPage = () => {
|
||||
/>
|
||||
)}
|
||||
{providers.length == 0 && (
|
||||
<p className="text-center text-red-600 max-w-sm">
|
||||
<pre className="break-normal! text-sm text-red-600">
|
||||
{t("failedToFetchProvidersTitle")}
|
||||
</p>
|
||||
</pre>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
{userAuthConfigured && (
|
||||
{userAuthConfigured && (
|
||||
<CardFooter>
|
||||
<Button
|
||||
className="w-full"
|
||||
type="submit"
|
||||
@@ -273,8 +273,8 @@ export const LoginPage = () => {
|
||||
>
|
||||
{t("loginSubmit")}
|
||||
</Button>
|
||||
)}
|
||||
</CardFooter>
|
||||
</CardFooter>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ export const appContextSchema = z.object({
|
||||
forgotPasswordMessage: z.string(),
|
||||
backgroundImage: z.string(),
|
||||
oauthAutoRedirect: z.string(),
|
||||
disableUiWarnings: z.boolean(),
|
||||
warningsEnabled: z.boolean(),
|
||||
});
|
||||
|
||||
export type AppContextSchema = z.infer<typeof appContextSchema>;
|
||||
|
||||
30
go.mod
30
go.mod
@@ -1,8 +1,6 @@
|
||||
module github.com/steveiliop56/tinyauth
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.3
|
||||
go 1.25.0
|
||||
|
||||
replace github.com/traefik/paerser v0.2.2 => ./paerser
|
||||
|
||||
@@ -10,7 +8,7 @@ require (
|
||||
github.com/cenkalti/backoff/v5 v5.0.3
|
||||
github.com/charmbracelet/huh v0.8.0
|
||||
github.com/docker/docker v28.5.2+incompatible
|
||||
github.com/gin-gonic/gin v1.11.0
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/go-jose/go-jose/v4 v4.1.3
|
||||
github.com/go-ldap/ldap/v3 v3.4.12
|
||||
github.com/golang-migrate/migrate/v4 v4.19.1
|
||||
@@ -38,8 +36,9 @@ require (
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.2 // indirect
|
||||
github.com/bytedance/sonic v1.14.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/catppuccin/go v0.3.0 // indirect
|
||||
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7 // indirect
|
||||
github.com/charmbracelet/bubbletea v1.3.6 // indirect
|
||||
@@ -59,16 +58,16 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.28.0 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
@@ -98,27 +97,28 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.57.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/arch v0.22.0 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/term v0.40.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.67.6 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
|
||||
60
go.sum
60
go.sum
@@ -26,10 +26,12 @@ github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
|
||||
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY=
|
||||
github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
@@ -95,12 +97,12 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
||||
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
||||
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||
@@ -118,12 +120,12 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
|
||||
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
|
||||
github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE=
|
||||
@@ -236,8 +238,8 @@ github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
||||
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.57.0 h1:AsSSrrMs4qI/hLrKlTH/TGQeTMY0ib1pAOX7vA3AdqE=
|
||||
github.com/quic-go/quic-go v0.57.0/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
|
||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -259,23 +261,27 @@ github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qq
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/weppos/publicsuffix-go v0.50.2 h1:KsJFc8IEKTJovM46SRCnGNsM+rFShxcs6VEHjOJcXzE=
|
||||
github.com/weppos/publicsuffix-go v0.50.2/go.mod h1:CbQCKDtXF8UcT7hrxeMa0MDjwhpOI9iYOU7cfq+yo8k=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
@@ -296,10 +302,10 @@ go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mx
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
@@ -314,8 +320,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
|
||||
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -360,8 +366,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
|
||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
||||
@@ -124,7 +124,7 @@ func (app *BootstrapApp) Setup() error {
|
||||
tlog.App.Trace().Str("redirectCookieName", app.context.redirectCookieName).Msg("Redirect cookie name")
|
||||
|
||||
// Database
|
||||
db, err := app.SetupDatabase(app.config.DatabasePath)
|
||||
db, err := app.SetupDatabase(app.config.Database.Path)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to setup database: %w", err)
|
||||
@@ -193,7 +193,7 @@ func (app *BootstrapApp) Setup() error {
|
||||
go app.dbCleanup(queries)
|
||||
|
||||
// If analytics are not disabled, start heartbeat
|
||||
if !app.config.DisableAnalytics {
|
||||
if app.config.Analytics.Enabled {
|
||||
tlog.App.Debug().Msg("Starting heartbeat routine")
|
||||
go app.heartbeat()
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
|
||||
ForgotPasswordMessage: app.config.UI.ForgotPasswordMessage,
|
||||
BackgroundImage: app.config.UI.BackgroundImage,
|
||||
OAuthAutoRedirect: app.config.OAuth.AutoRedirect,
|
||||
DisableUIWarnings: app.config.UI.DisableWarnings,
|
||||
WarningsEnabled: app.config.UI.WarningsEnabled,
|
||||
}, apiRouter)
|
||||
|
||||
contextController.SetupRoutes()
|
||||
@@ -103,8 +103,8 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
|
||||
userController.SetupRoutes()
|
||||
|
||||
resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{
|
||||
ResourcesDir: app.config.ResourcesDir,
|
||||
ResourcesDisabled: app.config.DisableResources,
|
||||
Path: app.config.Resources.Path,
|
||||
Enabled: app.config.Resources.Enabled,
|
||||
}, &engine.RouterGroup)
|
||||
|
||||
resourcesController.SetupRoutes()
|
||||
|
||||
@@ -3,8 +3,16 @@ package config
|
||||
// Default configuration
|
||||
func NewDefaultConfiguration() *Config {
|
||||
return &Config{
|
||||
ResourcesDir: "./resources",
|
||||
DatabasePath: "./tinyauth.db",
|
||||
Database: DatabaseConfig{
|
||||
Path: "./tinyauth.db",
|
||||
},
|
||||
Analytics: AnalyticsConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
Resources: ResourcesConfig{
|
||||
Enabled: true,
|
||||
Path: "./resources",
|
||||
},
|
||||
Server: ServerConfig{
|
||||
Port: 3000,
|
||||
Address: "0.0.0.0",
|
||||
@@ -19,6 +27,7 @@ func NewDefaultConfiguration() *Config {
|
||||
Title: "Tinyauth",
|
||||
ForgotPasswordMessage: "You can change your password by changing the configuration.",
|
||||
BackgroundImage: "/background.jpg",
|
||||
WarningsEnabled: true,
|
||||
},
|
||||
Ldap: LdapConfig{
|
||||
Insecure: false,
|
||||
@@ -68,20 +77,32 @@ var RedirectCookieName = "tinyauth-redirect"
|
||||
// Main app config
|
||||
|
||||
type Config struct {
|
||||
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
||||
ResourcesDir string `description:"The directory where resources are stored." yaml:"resourcesDir"`
|
||||
DatabasePath string `description:"The path to the database file." yaml:"databasePath"`
|
||||
DisableAnalytics bool `description:"Disable analytics." yaml:"disableAnalytics"`
|
||||
DisableResources bool `description:"Disable resources server." yaml:"disableResources"`
|
||||
Server ServerConfig `description:"Server configuration." yaml:"server"`
|
||||
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
|
||||
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
|
||||
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
|
||||
OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"`
|
||||
UI UIConfig `description:"UI customization." yaml:"ui"`
|
||||
Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"`
|
||||
Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
|
||||
Log LogConfig `description:"Logging configuration." yaml:"log"`
|
||||
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
||||
Database DatabaseConfig `description:"Database configuration." yaml:"database"`
|
||||
Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"`
|
||||
Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"`
|
||||
Server ServerConfig `description:"Server configuration." yaml:"server"`
|
||||
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
|
||||
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
|
||||
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
|
||||
OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"`
|
||||
UI UIConfig `description:"UI customization." yaml:"ui"`
|
||||
Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"`
|
||||
Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
|
||||
Log LogConfig `description:"Logging configuration." yaml:"log"`
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Path string `description:"The path to the database, including file name." yaml:"path"`
|
||||
}
|
||||
|
||||
type AnalyticsConfig struct {
|
||||
Enabled bool `description:"Enable periodic version information collection." yaml:"enabled"`
|
||||
}
|
||||
|
||||
type ResourcesConfig struct {
|
||||
Enabled bool `description:"Enable the resources server." yaml:"enabled"`
|
||||
Path string `description:"The directory where resources are stored." yaml:"path"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
@@ -114,8 +135,8 @@ type OAuthConfig struct {
|
||||
}
|
||||
|
||||
type OIDCConfig struct {
|
||||
PrivateKeyPath string `description:"Path to the private key file." yaml:"privateKeyPath"`
|
||||
PublicKeyPath string `description:"Path to the public key file." yaml:"publicKeyPath"`
|
||||
PrivateKeyPath string `description:"Path to the private key file, including file name." yaml:"privateKeyPath"`
|
||||
PublicKeyPath string `description:"Path to the public key file, including file name." yaml:"publicKeyPath"`
|
||||
Clients map[string]OIDCClientConfig `description:"OIDC clients configuration." yaml:"clients"`
|
||||
}
|
||||
|
||||
@@ -123,7 +144,7 @@ type UIConfig struct {
|
||||
Title string `description:"The title of the UI." yaml:"title"`
|
||||
ForgotPasswordMessage string `description:"Message displayed on the forgot password page." yaml:"forgotPasswordMessage"`
|
||||
BackgroundImage string `description:"Path to the background image." yaml:"backgroundImage"`
|
||||
DisableWarnings bool `description:"Disable UI warnings." yaml:"disableWarnings"`
|
||||
WarningsEnabled bool `description:"Enable UI warnings." yaml:"warningsEnabled"`
|
||||
}
|
||||
|
||||
type LdapConfig struct {
|
||||
|
||||
@@ -33,7 +33,7 @@ type AppContextResponse struct {
|
||||
ForgotPasswordMessage string `json:"forgotPasswordMessage"`
|
||||
BackgroundImage string `json:"backgroundImage"`
|
||||
OAuthAutoRedirect string `json:"oauthAutoRedirect"`
|
||||
DisableUIWarnings bool `json:"disableUiWarnings"`
|
||||
WarningsEnabled bool `json:"warningsEnabled"`
|
||||
}
|
||||
|
||||
type Provider struct {
|
||||
@@ -50,7 +50,7 @@ type ContextControllerConfig struct {
|
||||
ForgotPasswordMessage string
|
||||
BackgroundImage string
|
||||
OAuthAutoRedirect string
|
||||
DisableUIWarnings bool
|
||||
WarningsEnabled bool
|
||||
}
|
||||
|
||||
type ContextController struct {
|
||||
@@ -59,7 +59,7 @@ type ContextController struct {
|
||||
}
|
||||
|
||||
func NewContextController(config ContextControllerConfig, router *gin.RouterGroup) *ContextController {
|
||||
if config.DisableUIWarnings {
|
||||
if !config.WarningsEnabled {
|
||||
tlog.App.Warn().Msg("UI warnings are disabled. This may expose users to security risks. Proceed with caution.")
|
||||
}
|
||||
|
||||
@@ -124,6 +124,6 @@ func (controller *ContextController) appContextHandler(c *gin.Context) {
|
||||
ForgotPasswordMessage: controller.config.ForgotPasswordMessage,
|
||||
BackgroundImage: controller.config.BackgroundImage,
|
||||
OAuthAutoRedirect: controller.config.OAuthAutoRedirect,
|
||||
DisableUIWarnings: controller.config.DisableUIWarnings,
|
||||
WarningsEnabled: controller.config.WarningsEnabled,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ var contextControllerCfg = controller.ContextControllerConfig{
|
||||
ForgotPasswordMessage: "Contact admin to reset your password.",
|
||||
BackgroundImage: "/assets/bg.jpg",
|
||||
OAuthAutoRedirect: "google",
|
||||
DisableUIWarnings: false,
|
||||
WarningsEnabled: true,
|
||||
}
|
||||
|
||||
var contextCtrlTestContext = config.UserContext{
|
||||
@@ -82,7 +82,7 @@ func TestAppContextHandler(t *testing.T) {
|
||||
ForgotPasswordMessage: contextControllerCfg.ForgotPasswordMessage,
|
||||
BackgroundImage: contextControllerCfg.BackgroundImage,
|
||||
OAuthAutoRedirect: contextControllerCfg.OAuthAutoRedirect,
|
||||
DisableUIWarnings: contextControllerCfg.DisableUIWarnings,
|
||||
WarningsEnabled: contextControllerCfg.WarningsEnabled,
|
||||
}
|
||||
|
||||
router, recorder := setupContextController(nil)
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
)
|
||||
|
||||
type ResourcesControllerConfig struct {
|
||||
ResourcesDir string
|
||||
ResourcesDisabled bool
|
||||
Path string
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
type ResourcesController struct {
|
||||
@@ -18,7 +18,7 @@ type ResourcesController struct {
|
||||
}
|
||||
|
||||
func NewResourcesController(config ResourcesControllerConfig, router *gin.RouterGroup) *ResourcesController {
|
||||
fileServer := http.StripPrefix("/resources", http.FileServer(http.Dir(config.ResourcesDir)))
|
||||
fileServer := http.StripPrefix("/resources", http.FileServer(http.Dir(config.Path)))
|
||||
|
||||
return &ResourcesController{
|
||||
config: config,
|
||||
@@ -32,14 +32,14 @@ func (controller *ResourcesController) SetupRoutes() {
|
||||
}
|
||||
|
||||
func (controller *ResourcesController) resourcesHandler(c *gin.Context) {
|
||||
if controller.config.ResourcesDir == "" {
|
||||
if controller.config.Path == "" {
|
||||
c.JSON(404, gin.H{
|
||||
"status": 404,
|
||||
"message": "Resources not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
if controller.config.ResourcesDisabled {
|
||||
if !controller.config.Enabled {
|
||||
c.JSON(403, gin.H{
|
||||
"status": 403,
|
||||
"message": "Resources are disabled",
|
||||
|
||||
@@ -18,7 +18,8 @@ func TestResourcesHandler(t *testing.T) {
|
||||
group := router.Group("/")
|
||||
|
||||
ctrl := controller.NewResourcesController(controller.ResourcesControllerConfig{
|
||||
ResourcesDir: "/tmp/tinyauth",
|
||||
Path: "/tmp/tinyauth",
|
||||
Enabled: true,
|
||||
}, group)
|
||||
ctrl.SetupRoutes()
|
||||
|
||||
|
||||
@@ -41,11 +41,15 @@ var (
|
||||
)
|
||||
|
||||
type ClaimSet struct {
|
||||
Iss string `json:"iss"`
|
||||
Aud string `json:"aud"`
|
||||
Sub string `json:"sub"`
|
||||
Iat int64 `json:"iat"`
|
||||
Exp int64 `json:"exp"`
|
||||
Iss string `json:"iss"`
|
||||
Aud string `json:"aud"`
|
||||
Sub string `json:"sub"`
|
||||
Iat int64 `json:"iat"`
|
||||
Exp int64 `json:"exp"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
PreferredUsername string `json:"preferred_username,omitempty"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
type UserinfoResponse struct {
|
||||
@@ -53,7 +57,7 @@ type UserinfoResponse struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
PreferredUsername string `json:"preferred_username"`
|
||||
Groups []string `json:"groups"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
|
||||
@@ -349,7 +353,7 @@ func (service *OIDCService) GetCodeEntry(c *gin.Context, codeHash string) (repos
|
||||
return oidcCode, nil
|
||||
}
|
||||
|
||||
func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, sub string) (string, error) {
|
||||
func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, user repository.OidcUserinfo, scope string) (string, error) {
|
||||
createdAt := time.Now().Unix()
|
||||
expiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry) * time.Second).Unix()
|
||||
|
||||
@@ -367,12 +371,18 @@ func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, sub
|
||||
return "", err
|
||||
}
|
||||
|
||||
userInfo := service.CompileUserinfo(user, scope)
|
||||
|
||||
claims := ClaimSet{
|
||||
Iss: service.issuer,
|
||||
Aud: client.ClientID,
|
||||
Sub: sub,
|
||||
Iat: createdAt,
|
||||
Exp: expiresAt,
|
||||
Iss: service.issuer,
|
||||
Aud: client.ClientID,
|
||||
Sub: user.Sub,
|
||||
Iat: createdAt,
|
||||
Exp: expiresAt,
|
||||
Name: userInfo.Name,
|
||||
Email: userInfo.Email,
|
||||
PreferredUsername: userInfo.PreferredUsername,
|
||||
Groups: userInfo.Groups,
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(claims)
|
||||
@@ -397,7 +407,13 @@ func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, sub
|
||||
}
|
||||
|
||||
func (service *OIDCService) GenerateAccessToken(c *gin.Context, client config.OIDCClientConfig, sub string, scope string) (TokenResponse, error) {
|
||||
idToken, err := service.generateIDToken(client, sub)
|
||||
user, err := service.GetUserinfo(c, sub)
|
||||
|
||||
if err != nil {
|
||||
return TokenResponse{}, err
|
||||
}
|
||||
|
||||
idToken, err := service.generateIDToken(client, user, scope)
|
||||
|
||||
if err != nil {
|
||||
return TokenResponse{}, err
|
||||
@@ -456,9 +472,15 @@ func (service *OIDCService) RefreshAccessToken(c *gin.Context, refreshToken stri
|
||||
return TokenResponse{}, ErrInvalidClient
|
||||
}
|
||||
|
||||
user, err := service.GetUserinfo(c, entry.Sub)
|
||||
|
||||
if err != nil {
|
||||
return TokenResponse{}, err
|
||||
}
|
||||
|
||||
idToken, err := service.generateIDToken(config.OIDCClientConfig{
|
||||
ClientID: entry.ClientID,
|
||||
}, entry.Sub)
|
||||
}, user, entry.Scope)
|
||||
|
||||
if err != nil {
|
||||
return TokenResponse{}, err
|
||||
|
||||
Reference in New Issue
Block a user