mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-31 14:15:50 +00:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			v3.5.0-alp
			...
			v3.6.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | fe440a6f2e | ||
|   | 0ace88a877 | ||
|   | 476ed6964d | ||
|   | b3dca0429f | ||
|   | 9e4b68112c | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 364f0e221e | ||
|   | 09635666aa | ||
|   | 9f02710114 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -11,8 +11,7 @@ docker-compose.test* | |||||||
| users.txt | users.txt | ||||||
|  |  | ||||||
| # secret test file | # secret test file | ||||||
| secret.txt | secret* | ||||||
| secret_oauth.txt |  | ||||||
|  |  | ||||||
| # vscode | # vscode | ||||||
| .vscode | .vscode | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
|         "class-variance-authority": "^0.7.1", |         "class-variance-authority": "^0.7.1", | ||||||
|         "clsx": "^2.1.1", |         "clsx": "^2.1.1", | ||||||
|         "dompurify": "^3.2.6", |         "dompurify": "^3.2.6", | ||||||
|         "i18next": "^25.3.1", |         "i18next": "^25.3.2", | ||||||
|         "i18next-browser-languagedetector": "^8.2.0", |         "i18next-browser-languagedetector": "^8.2.0", | ||||||
|         "i18next-resources-to-backend": "^1.2.1", |         "i18next-resources-to-backend": "^1.2.1", | ||||||
|         "input-otp": "^1.4.2", |         "input-otp": "^1.4.2", | ||||||
| @@ -30,12 +30,12 @@ | |||||||
|         "sonner": "^2.0.6", |         "sonner": "^2.0.6", | ||||||
|         "tailwind-merge": "^3.3.1", |         "tailwind-merge": "^3.3.1", | ||||||
|         "tailwindcss": "^4.1.11", |         "tailwindcss": "^4.1.11", | ||||||
|         "zod": "^3.25.75", |         "zod": "^3.25.76", | ||||||
|       }, |       }, | ||||||
|       "devDependencies": { |       "devDependencies": { | ||||||
|         "@eslint/js": "^9.30.1", |         "@eslint/js": "^9.30.1", | ||||||
|         "@tanstack/eslint-plugin-query": "^5.81.2", |         "@tanstack/eslint-plugin-query": "^5.81.2", | ||||||
|         "@types/node": "^24.0.10", |         "@types/node": "^24.0.12", | ||||||
|         "@types/react": "^19.1.8", |         "@types/react": "^19.1.8", | ||||||
|         "@types/react-dom": "^19.1.6", |         "@types/react-dom": "^19.1.6", | ||||||
|         "@vitejs/plugin-react": "^4.6.0", |         "@vitejs/plugin-react": "^4.6.0", | ||||||
| @@ -354,7 +354,7 @@ | |||||||
|  |  | ||||||
|     "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], |     "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], | ||||||
|  |  | ||||||
|     "@types/node": ["@types/node@24.0.10", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA=="], |     "@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="], | ||||||
|  |  | ||||||
|     "@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="], |     "@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="], | ||||||
|  |  | ||||||
| @@ -582,7 +582,7 @@ | |||||||
|  |  | ||||||
|     "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], |     "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], | ||||||
|  |  | ||||||
|     "i18next": ["i18next@25.3.1", "", { "dependencies": { "@babel/runtime": "^7.27.6" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-S4CPAx8LfMOnURnnJa8jFWvur+UX/LWcl6+61p9VV7SK2m0445JeBJ6tLD0D5SR0H29G4PYfWkEhivKG5p4RDg=="], |     "i18next": ["i18next@25.3.2", "", { "dependencies": { "@babel/runtime": "^7.27.6" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-JSnbZDxRVbphc5jiptxr3o2zocy5dEqpVm9qCGdJwRNO+9saUJS0/u4LnM/13C23fUEWxAylPqKU/NpMV/IjqA=="], | ||||||
|  |  | ||||||
|     "i18next-browser-languagedetector": ["i18next-browser-languagedetector@8.2.0", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g=="], |     "i18next-browser-languagedetector": ["i18next-browser-languagedetector@8.2.0", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g=="], | ||||||
|  |  | ||||||
| @@ -912,7 +912,7 @@ | |||||||
|  |  | ||||||
|     "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], |     "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], | ||||||
|  |  | ||||||
|     "zod": ["zod@3.25.75", "", {}, "sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg=="], |     "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], | ||||||
|  |  | ||||||
|     "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], |     "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ | |||||||
|     "class-variance-authority": "^0.7.1", |     "class-variance-authority": "^0.7.1", | ||||||
|     "clsx": "^2.1.1", |     "clsx": "^2.1.1", | ||||||
|     "dompurify": "^3.2.6", |     "dompurify": "^3.2.6", | ||||||
|     "i18next": "^25.3.1", |     "i18next": "^25.3.2", | ||||||
|     "i18next-browser-languagedetector": "^8.2.0", |     "i18next-browser-languagedetector": "^8.2.0", | ||||||
|     "i18next-resources-to-backend": "^1.2.1", |     "i18next-resources-to-backend": "^1.2.1", | ||||||
|     "input-otp": "^1.4.2", |     "input-otp": "^1.4.2", | ||||||
| @@ -36,12 +36,12 @@ | |||||||
|     "sonner": "^2.0.6", |     "sonner": "^2.0.6", | ||||||
|     "tailwind-merge": "^3.3.1", |     "tailwind-merge": "^3.3.1", | ||||||
|     "tailwindcss": "^4.1.11", |     "tailwindcss": "^4.1.11", | ||||||
|     "zod": "^3.25.75" |     "zod": "^3.25.76" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@eslint/js": "^9.30.1", |     "@eslint/js": "^9.30.1", | ||||||
|     "@tanstack/eslint-plugin-query": "^5.81.2", |     "@tanstack/eslint-plugin-query": "^5.81.2", | ||||||
|     "@types/node": "^24.0.10", |     "@types/node": "^24.0.12", | ||||||
|     "@types/react": "^19.1.8", |     "@types/react": "^19.1.8", | ||||||
|     "@types/react-dom": "^19.1.6", |     "@types/react-dom": "^19.1.6", | ||||||
|     "@vitejs/plugin-react": "^4.6.0", |     "@vitejs/plugin-react": "^4.6.0", | ||||||
|   | |||||||
| @@ -27,8 +27,8 @@ export const languages = { | |||||||
|   "tr-TR": "Türkçe", |   "tr-TR": "Türkçe", | ||||||
|   "uk-UA": "Українська", |   "uk-UA": "Українська", | ||||||
|   "vi-VN": "Tiếng Việt", |   "vi-VN": "Tiếng Việt", | ||||||
|   "zh-CN": "中文", |   "zh-CN": "简体中文", | ||||||
|   "zh-TW": "中文", |   "zh-TW": "繁體中文(台灣)", | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export type SupportedLanguage = keyof typeof languages; | export type SupportedLanguage = keyof typeof languages; | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|     "loginTitle": "مرحبا بعودتك، قم بتسجيل الدخول باستخدام", |     "loginTitle": "مرحبا بعودتك، ادخل باستخدام", | ||||||
|     "loginTitleSimple": "Welcome back, please login", |     "loginTitleSimple": "مرحبا بعودتك، سجل دخولك", | ||||||
|     "loginDivider": "Or", |     "loginDivider": "أو", | ||||||
|     "loginUsername": "اسم المستخدم", |     "loginUsername": "اسم المستخدم", | ||||||
|     "loginPassword": "كلمة المرور", |     "loginPassword": "كلمة المرور", | ||||||
|     "loginSubmit": "تسجيل الدخول", |     "loginSubmit": "تسجيل الدخول", | ||||||
| @@ -10,8 +10,8 @@ | |||||||
|     "loginFailRateLimit": "You failed to login too many times. Please try again later", |     "loginFailRateLimit": "You failed to login too many times. Please try again later", | ||||||
|     "loginSuccessTitle": "تم تسجيل الدخول", |     "loginSuccessTitle": "تم تسجيل الدخول", | ||||||
|     "loginSuccessSubtitle": "مرحبا بعودتك!", |     "loginSuccessSubtitle": "مرحبا بعودتك!", | ||||||
|     "loginOauthFailTitle": "An error occurred", |     "loginOauthFailTitle": "حدث خطأ", | ||||||
|     "loginOauthFailSubtitle": "فشل في الحصول على رابط OAuth", |     "loginOauthFailSubtitle": "أخفق الحصول على رابط OAuth", | ||||||
|     "loginOauthSuccessTitle": "إعادة توجيه", |     "loginOauthSuccessTitle": "إعادة توجيه", | ||||||
|     "loginOauthSuccessSubtitle": "إعادة توجيه إلى مزود OAuth الخاص بك", |     "loginOauthSuccessSubtitle": "إعادة توجيه إلى مزود OAuth الخاص بك", | ||||||
|     "continueRedirectingTitle": "إعادة توجيه...", |     "continueRedirectingTitle": "إعادة توجيه...", | ||||||
| @@ -19,7 +19,7 @@ | |||||||
|     "continueInvalidRedirectTitle": "إعادة توجيه غير صالحة", |     "continueInvalidRedirectTitle": "إعادة توجيه غير صالحة", | ||||||
|     "continueInvalidRedirectSubtitle": "رابط إعادة التوجيه غير صالح", |     "continueInvalidRedirectSubtitle": "رابط إعادة التوجيه غير صالح", | ||||||
|     "continueInsecureRedirectTitle": "إعادة توجيه غير آمنة", |     "continueInsecureRedirectTitle": "إعادة توجيه غير آمنة", | ||||||
|     "continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code> which is not secure. Are you sure you want to continue?", |     "continueInsecureRedirectSubtitle": "أنت تحاول إعادة التوجيه من <code>https</code> إلى <code>http</code>، هل أنت متأكد أنك تريد المتابعة؟", | ||||||
|     "continueTitle": "متابعة", |     "continueTitle": "متابعة", | ||||||
|     "continueSubtitle": "انقر الزر للمتابعة إلى التطبيق الخاص بك.", |     "continueSubtitle": "انقر الزر للمتابعة إلى التطبيق الخاص بك.", | ||||||
|     "logoutFailTitle": "فشل تسجيل الخروج", |     "logoutFailTitle": "فشل تسجيل الخروج", | ||||||
| @@ -32,7 +32,7 @@ | |||||||
|     "notFoundTitle": "الصفحة غير موجودة", |     "notFoundTitle": "الصفحة غير موجودة", | ||||||
|     "notFoundSubtitle": "الصفحة التي تبحث عنها غير موجودة.", |     "notFoundSubtitle": "الصفحة التي تبحث عنها غير موجودة.", | ||||||
|     "notFoundButton": "انتقل إلى الرئيسية", |     "notFoundButton": "انتقل إلى الرئيسية", | ||||||
|     "totpFailTitle": "فشل في التحقق من الرمز", |     "totpFailTitle": "أخفق التحقق من الرمز", | ||||||
|     "totpFailSubtitle": "الرجاء التحقق من الرمز الخاص بك وحاول مرة أخرى", |     "totpFailSubtitle": "الرجاء التحقق من الرمز الخاص بك وحاول مرة أخرى", | ||||||
|     "totpSuccessTitle": "تم التحقق", |     "totpSuccessTitle": "تم التحقق", | ||||||
|     "totpSuccessSubtitle": "إعادة توجيه إلى تطبيقك", |     "totpSuccessSubtitle": "إعادة توجيه إلى تطبيقك", | ||||||
| @@ -44,11 +44,11 @@ | |||||||
|     "unauthorizedGroupsSubtitle": "The user with username <code>{{username}}</code> is not in the groups required by the resource <code>{{resource}}</code>.", |     "unauthorizedGroupsSubtitle": "The user with username <code>{{username}}</code> is not in the groups required by the resource <code>{{resource}}</code>.", | ||||||
|     "unauthorizedIpSubtitle": "Your IP address <code>{{ip}}</code> is not authorized to access the resource <code>{{resource}}</code>.", |     "unauthorizedIpSubtitle": "Your IP address <code>{{ip}}</code> is not authorized to access the resource <code>{{resource}}</code>.", | ||||||
|     "unauthorizedButton": "حاول مجددا", |     "unauthorizedButton": "حاول مجددا", | ||||||
|     "untrustedRedirectTitle": "Untrusted redirect", |     "untrustedRedirectTitle": "إعادة توجيه غير موثوقة", | ||||||
|     "untrustedRedirectSubtitle": "You are trying to redirect to a domain that does not match your configured domain (<code>{{domain}}</code>). Are you sure you want to continue?", |     "untrustedRedirectSubtitle": "أنت تحاول إعادة التوجيه إلى نطاق لا يتطابق مع النطاق المكون الخاص بك (<code>{{domain}}</code>). هل أنت متأكد من أنك تريد المتابعة؟", | ||||||
|     "cancelTitle": "إلغاء", |     "cancelTitle": "إلغاء", | ||||||
|     "forgotPasswordTitle": "Forgot your password?", |     "forgotPasswordTitle": "نسيت كلمة المرور؟", | ||||||
|     "failedToFetchProvidersTitle": "Failed to load authentication providers. Please check your configuration.", |     "failedToFetchProvidersTitle": "Failed to load authentication providers. Please check your configuration.", | ||||||
|     "errorTitle": "An error occurred", |     "errorTitle": "حدث خطأ", | ||||||
|     "errorSubtitle": "An error occurred while trying to perform this action. Please check the console for more information." |     "errorSubtitle": "An error occurred while trying to perform this action. Please check the console for more information." | ||||||
| } | } | ||||||
| @@ -42,7 +42,7 @@ | |||||||
|     "unauthorizedResourceSubtitle": "Brugeren med brugernavnet <code>{{username}}</code> har ikke tilladelse til at tilgå ressourcen <code>{{resource}}</code>.", |     "unauthorizedResourceSubtitle": "Brugeren med brugernavnet <code>{{username}}</code> har ikke tilladelse til at tilgå ressourcen <code>{{resource}}</code>.", | ||||||
|     "unauthorizedLoginSubtitle": "Brugeren med brugernavnet <code>{{username}}</code> har ikke tilladelse til at logge ind.", |     "unauthorizedLoginSubtitle": "Brugeren med brugernavnet <code>{{username}}</code> har ikke tilladelse til at logge ind.", | ||||||
|     "unauthorizedGroupsSubtitle": "Brugeren med brugernavnet <code>{{username}}</code> er ikke i de grupper, som ressourcen <code>{{resource}}</code> kræver.", |     "unauthorizedGroupsSubtitle": "Brugeren med brugernavnet <code>{{username}}</code> er ikke i de grupper, som ressourcen <code>{{resource}}</code> kræver.", | ||||||
|     "unauthorizedIpSubtitle": "Your IP address <code>{{ip}}</code> is not authorized to access the resource <code>{{resource}}</code>.", |     "unauthorizedIpSubtitle": "Din IP adresse <code>{{ip}}</code> er ikke autoriseret til at tilgå ressourcen <code>{{resource}}</code>.", | ||||||
|     "unauthorizedButton": "Prøv igen", |     "unauthorizedButton": "Prøv igen", | ||||||
|     "untrustedRedirectTitle": "Usikker omdirigering", |     "untrustedRedirectTitle": "Usikker omdirigering", | ||||||
|     "untrustedRedirectSubtitle": "Du forsøger at omdirigere til et domæne, der ikke matcher dit konfigurerede domæne (<code>{{domain}}</code>). Er du sikker på, at du vil fortsætte?", |     "untrustedRedirectSubtitle": "Du forsøger at omdirigere til et domæne, der ikke matcher dit konfigurerede domæne (<code>{{domain}}</code>). Er du sikker på, at du vil fortsætte?", | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ | |||||||
|     "unauthorizedResourceSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν έχει άδεια πρόσβασης στον πόρο <code>{{resource}}</code>.", |     "unauthorizedResourceSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν έχει άδεια πρόσβασης στον πόρο <code>{{resource}}</code>.", | ||||||
|     "unauthorizedLoginSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι εξουσιοδοτημένος να συνδεθεί.", |     "unauthorizedLoginSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι εξουσιοδοτημένος να συνδεθεί.", | ||||||
|     "unauthorizedGroupsSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι στις ομάδες που απαιτούνται από τον πόρο <code>{{resource}}</code>.", |     "unauthorizedGroupsSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι στις ομάδες που απαιτούνται από τον πόρο <code>{{resource}}</code>.", | ||||||
|     "unauthorizedIpSubtitle": "Your IP address <code>{{ip}}</code> is not authorized to access the resource <code>{{resource}}</code>.", |     "unauthorizedIpSubtitle": "Η διεύθυνση IP σας <code>{{ip}}</code> δεν είναι εξουσιοδοτημένη να έχει πρόσβαση στον πόρο <code>{{resource}}</code>.", | ||||||
|     "unauthorizedButton": "Προσπαθήστε ξανά", |     "unauthorizedButton": "Προσπαθήστε ξανά", | ||||||
|     "untrustedRedirectTitle": "Μη έμπιστη ανακατεύθυνση", |     "untrustedRedirectTitle": "Μη έμπιστη ανακατεύθυνση", | ||||||
|     "untrustedRedirectSubtitle": "Προσπαθείτε να ανακατευθύνετε σε ένα domain που δεν ταιριάζει με τον ρυθμισμένο domain σας (<code>{{domain}}</code>). Είστε βέβαιοι ότι θέλετε να συνεχίσετε;", |     "untrustedRedirectSubtitle": "Προσπαθείτε να ανακατευθύνετε σε ένα domain που δεν ταιριάζει με τον ρυθμισμένο domain σας (<code>{{domain}}</code>). Είστε βέβαιοι ότι θέλετε να συνεχίσετε;", | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|     "loginFailRateLimit": "You failed to login too many times. Please try again later", |     "loginFailRateLimit": "You failed to login too many times. Please try again later", | ||||||
|     "loginSuccessTitle": "Connecté", |     "loginSuccessTitle": "Connecté", | ||||||
|     "loginSuccessSubtitle": "Bienvenue!", |     "loginSuccessSubtitle": "Bienvenue!", | ||||||
|     "loginOauthFailTitle": "An error occurred", |     "loginOauthFailTitle": "Une erreur s'est produite", | ||||||
|     "loginOauthFailSubtitle": "Impossible d'obtenir l'URL OAuth", |     "loginOauthFailSubtitle": "Impossible d'obtenir l'URL OAuth", | ||||||
|     "loginOauthSuccessTitle": "Redirection", |     "loginOauthSuccessTitle": "Redirection", | ||||||
|     "loginOauthSuccessSubtitle": "Redirection vers votre fournisseur OAuth", |     "loginOauthSuccessSubtitle": "Redirection vers votre fournisseur OAuth", | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|     "loginTitle": "Witaj ponownie, zaloguj się przez", |     "loginTitle": "Witaj ponownie, zaloguj się przez", | ||||||
|     "loginTitleSimple": "Witaj ponownie, zaloguj się", |     "loginTitleSimple": "Witaj ponownie, zaloguj się", | ||||||
|     "loginDivider": "lub", |     "loginDivider": "Lub", | ||||||
|     "loginUsername": "Nazwa użytkownika", |     "loginUsername": "Nazwa użytkownika", | ||||||
|     "loginPassword": "Hasło", |     "loginPassword": "Hasło", | ||||||
|     "loginSubmit": "Zaloguj się", |     "loginSubmit": "Zaloguj się", | ||||||
|   | |||||||
| @@ -1,54 +1,54 @@ | |||||||
| { | { | ||||||
|     "loginTitle": "Welcome back, login with", |     "loginTitle": "歡迎回來,請用以下方式登入", | ||||||
|     "loginTitleSimple": "Welcome back, please login", |     "loginTitleSimple": "歡迎回來,請登入", | ||||||
|     "loginDivider": "Or", |     "loginDivider": "或", | ||||||
|     "loginUsername": "Username", |     "loginUsername": "帳號", | ||||||
|     "loginPassword": "Password", |     "loginPassword": "密碼", | ||||||
|     "loginSubmit": "Login", |     "loginSubmit": "登入", | ||||||
|     "loginFailTitle": "Failed to log in", |     "loginFailTitle": "登入失敗", | ||||||
|     "loginFailSubtitle": "Please check your username and password", |     "loginFailSubtitle": "請檢查您的帳號與密碼", | ||||||
|     "loginFailRateLimit": "You failed to login too many times. Please try again later", |     "loginFailRateLimit": "登入失敗次數過多,請稍後再試", | ||||||
|     "loginSuccessTitle": "Logged in", |     "loginSuccessTitle": "登入成功", | ||||||
|     "loginSuccessSubtitle": "Welcome back!", |     "loginSuccessSubtitle": "歡迎回來!", | ||||||
|     "loginOauthFailTitle": "An error occurred", |     "loginOauthFailTitle": "發生錯誤", | ||||||
|     "loginOauthFailSubtitle": "Failed to get OAuth URL", |     "loginOauthFailSubtitle": "無法取得 OAuth 網址", | ||||||
|     "loginOauthSuccessTitle": "Redirecting", |     "loginOauthSuccessTitle": "重新導向中", | ||||||
|     "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider", |     "loginOauthSuccessSubtitle": "正在將您重新導向至 OAuth 供應商", | ||||||
|     "continueRedirectingTitle": "Redirecting...", |     "continueRedirectingTitle": "重新導向中...", | ||||||
|     "continueRedirectingSubtitle": "You should be redirected to the app soon", |     "continueRedirectingSubtitle": "您即將被重新導向至應用程式", | ||||||
|     "continueInvalidRedirectTitle": "Invalid redirect", |     "continueInvalidRedirectTitle": "無效的重新導向", | ||||||
|     "continueInvalidRedirectSubtitle": "The redirect URL is invalid", |     "continueInvalidRedirectSubtitle": "重新導向的網址無效", | ||||||
|     "continueInsecureRedirectTitle": "Insecure redirect", |     "continueInsecureRedirectTitle": "不安全的重新導向", | ||||||
|     "continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code> which is not secure. Are you sure you want to continue?", |     "continueInsecureRedirectSubtitle": "您正嘗試從安全的 <code>https</code> 重新導向至不安全的 <code>http</code>。您確定要繼續嗎?", | ||||||
|     "continueTitle": "Continue", |     "continueTitle": "繼續", | ||||||
|     "continueSubtitle": "Click the button to continue to your app.", |     "continueSubtitle": "點擊按鈕以繼續前往您的應用程式。", | ||||||
|     "logoutFailTitle": "Failed to log out", |     "logoutFailTitle": "登出失敗", | ||||||
|     "logoutFailSubtitle": "Please try again", |     "logoutFailSubtitle": "請再試一次", | ||||||
|     "logoutSuccessTitle": "Logged out", |     "logoutSuccessTitle": "登出成功", | ||||||
|     "logoutSuccessSubtitle": "You have been logged out", |     "logoutSuccessSubtitle": "您已成功登出", | ||||||
|     "logoutTitle": "Logout", |     "logoutTitle": "登出", | ||||||
|     "logoutUsernameSubtitle": "You are currently logged in as <code>{{username}}</code>. Click the button below to logout.", |     "logoutUsernameSubtitle": "您目前以 <code>{{username}}</code> 的身分登入。點擊下方按鈕以登出。", | ||||||
|     "logoutOauthSubtitle": "You are currently logged in as <code>{{username}}</code> using the {{provider}} OAuth provider. Click the button below to logout.", |     "logoutOauthSubtitle": "您目前使用 {{provider}} OAuth 供應商並以 <code>{{username}}</code> 的身分登入。點擊下方按鈕以登出。", | ||||||
|     "notFoundTitle": "Page not found", |     "notFoundTitle": "找不到頁面", | ||||||
|     "notFoundSubtitle": "The page you are looking for does not exist.", |     "notFoundSubtitle": "您要尋找的頁面不存在。", | ||||||
|     "notFoundButton": "Go home", |     "notFoundButton": "回到首頁", | ||||||
|     "totpFailTitle": "Failed to verify code", |     "totpFailTitle": "驗證失敗", | ||||||
|     "totpFailSubtitle": "Please check your code and try again", |     "totpFailSubtitle": "請檢查您的驗證碼並再試一次", | ||||||
|     "totpSuccessTitle": "Verified", |     "totpSuccessTitle": "驗證成功", | ||||||
|     "totpSuccessSubtitle": "Redirecting to your app", |     "totpSuccessSubtitle": "正在重新導向至您的應用程式", | ||||||
|     "totpTitle": "Enter your TOTP code", |     "totpTitle": "輸入您的 TOTP 驗證碼", | ||||||
|     "totpSubtitle": "Please enter the code from your authenticator app.", |     "totpSubtitle": "請輸入您驗證器應用程式中的代碼。", | ||||||
|     "unauthorizedTitle": "Unauthorized", |     "unauthorizedTitle": "未經授權", | ||||||
|     "unauthorizedResourceSubtitle": "The user with username <code>{{username}}</code> is not authorized to access the resource <code>{{resource}}</code>.", |     "unauthorizedResourceSubtitle": "使用者 <code>{{username}}</code> 未被授權存取資源 <code>{{resource}}</code>。", | ||||||
|     "unauthorizedLoginSubtitle": "The user with username <code>{{username}}</code> is not authorized to login.", |     "unauthorizedLoginSubtitle": "使用者 <code>{{username}}</code> 未被授權登入。", | ||||||
|     "unauthorizedGroupsSubtitle": "The user with username <code>{{username}}</code> is not in the groups required by the resource <code>{{resource}}</code>.", |     "unauthorizedGroupsSubtitle": "使用者 <code>{{username}}</code> 不在存取資源 <code>{{resource}}</code> 所需的群組中。", | ||||||
|     "unauthorizedIpSubtitle": "Your IP address <code>{{ip}}</code> is not authorized to access the resource <code>{{resource}}</code>.", |     "unauthorizedIpSubtitle": "您的 IP 位址 <code>{{ip}}</code> 未被授權存取資源 <code>{{resource}}</code>。", | ||||||
|     "unauthorizedButton": "Try again", |     "unauthorizedButton": "再試一次", | ||||||
|     "untrustedRedirectTitle": "Untrusted redirect", |     "untrustedRedirectTitle": "不受信任的重新導向", | ||||||
|     "untrustedRedirectSubtitle": "You are trying to redirect to a domain that does not match your configured domain (<code>{{domain}}</code>). Are you sure you want to continue?", |     "untrustedRedirectSubtitle": "您正嘗試重新導向至的網域與您設定的網域 (<code>{{domain}}</code>) 不符。您確定要繼續嗎?", | ||||||
|     "cancelTitle": "Cancel", |     "cancelTitle": "取消", | ||||||
|     "forgotPasswordTitle": "Forgot your password?", |     "forgotPasswordTitle": "忘記密碼?", | ||||||
|     "failedToFetchProvidersTitle": "Failed to load authentication providers. Please check your configuration.", |     "failedToFetchProvidersTitle": "載入驗證供應商失敗。請檢查您的設定。", | ||||||
|     "errorTitle": "An error occurred", |     "errorTitle": "發生錯誤", | ||||||
|     "errorSubtitle": "An error occurred while trying to perform this action. Please check the console for more information." |     "errorSubtitle": "執行此操作時發生錯誤。請檢查主控台以獲取更多資訊。" | ||||||
| } | } | ||||||
| @@ -233,8 +233,8 @@ func (auth *Auth) RecordLoginAttempt(identifier string, success bool) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (auth *Auth) EmailWhitelisted(emailSrc string) bool { | func (auth *Auth) EmailWhitelisted(email string) bool { | ||||||
| 	return utils.CheckWhitelist(auth.Config.OauthWhitelist, emailSrc) | 	return utils.CheckFilter(auth.Config.OauthWhitelist, email) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) error { | func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) error { | ||||||
| @@ -368,13 +368,13 @@ func (auth *Auth) ResourceAllowed(c *gin.Context, context types.UserContext, lab | |||||||
| 	// Check if oauth is allowed | 	// Check if oauth is allowed | ||||||
| 	if context.OAuth { | 	if context.OAuth { | ||||||
| 		log.Debug().Msg("Checking OAuth whitelist") | 		log.Debug().Msg("Checking OAuth whitelist") | ||||||
| 		return utils.CheckWhitelist(labels.OAuth.Whitelist, context.Email) | 		return utils.CheckFilter(labels.OAuth.Whitelist, context.Email) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Check users | 	// Check users | ||||||
| 	log.Debug().Msg("Checking users") | 	log.Debug().Msg("Checking users") | ||||||
|  |  | ||||||
| 	return utils.CheckWhitelist(labels.Users, context.Username) | 	return utils.CheckFilter(labels.Users, context.Username) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (auth *Auth) OAuthGroup(c *gin.Context, context types.UserContext, labels types.Labels) bool { | func (auth *Auth) OAuthGroup(c *gin.Context, context types.UserContext, labels types.Labels) bool { | ||||||
| @@ -394,7 +394,7 @@ func (auth *Auth) OAuthGroup(c *gin.Context, context types.UserContext, labels t | |||||||
|  |  | ||||||
| 	// For every group check if it is in the required groups | 	// For every group check if it is in the required groups | ||||||
| 	for _, group := range oauthGroups { | 	for _, group := range oauthGroups { | ||||||
| 		if utils.CheckWhitelist(labels.OAuth.Groups, group) { | 		if utils.CheckFilter(labels.OAuth.Groups, group) { | ||||||
| 			log.Debug().Str("group", group).Msg("Group is in required groups") | 			log.Debug().Str("group", group).Msg("Group is in required groups") | ||||||
| 			return true | 			return true | ||||||
| 		} | 		} | ||||||
| @@ -452,10 +452,7 @@ func (auth *Auth) GetBasicAuth(c *gin.Context) *types.User { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (auth *Auth) CheckIP(c *gin.Context, labels types.Labels) bool { | func (auth *Auth) CheckIP(labels types.Labels, ip string) bool { | ||||||
| 	// Get the IP address from the request |  | ||||||
| 	ip := c.ClientIP() |  | ||||||
|  |  | ||||||
| 	// Check if the IP is in block list | 	// Check if the IP is in block list | ||||||
| 	for _, blocked := range labels.IP.Block { | 	for _, blocked := range labels.IP.Block { | ||||||
| 		res, err := utils.FilterIP(blocked, ip) | 		res, err := utils.FilterIP(blocked, ip) | ||||||
| @@ -492,3 +489,22 @@ func (auth *Auth) CheckIP(c *gin.Context, labels types.Labels) bool { | |||||||
|  |  | ||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (auth *Auth) BypassedIP(labels types.Labels, ip string) bool { | ||||||
|  | 	// For every IP in the bypass list, check if the IP matches | ||||||
|  | 	for _, bypassed := range labels.IP.Bypass { | ||||||
|  | 		res, err := utils.FilterIP(bypassed, ip) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Warn().Err(err).Str("item", bypassed).Msg("Invalid IP/CIDR in bypass list") | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		if res { | ||||||
|  | 			log.Debug().Str("ip", ip).Str("item", bypassed).Msg("IP is in bypass list, allowing access") | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log.Debug().Str("ip", ip).Msg("IP not in bypass list, continuing with authentication") | ||||||
|  |  | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ func (docker *Docker) DockerConnected() bool { | |||||||
| 	return err == nil | 	return err == nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (docker *Docker) GetLabels(id string, domain string) (types.Labels, error) { | func (docker *Docker) GetLabels(app string, domain string) (types.Labels, error) { | ||||||
| 	// Check if we have access to the Docker API | 	// Check if we have access to the Docker API | ||||||
| 	isConnected := docker.DockerConnected() | 	isConnected := docker.DockerConnected() | ||||||
|  |  | ||||||
| @@ -112,9 +112,16 @@ func (docker *Docker) GetLabels(id string, domain string) (types.Labels, error) | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Check if the labels match the id or the domain | 		// Check if the container matches the ID or domain | ||||||
| 		if strings.TrimPrefix(inspect.Name, "/") == id || labels.Domain == domain { | 		for _, lDomain := range labels.Domain { | ||||||
| 			log.Debug().Str("id", inspect.ID).Msg("Found matching container") | 			if lDomain == domain { | ||||||
|  | 				log.Debug().Str("id", inspect.ID).Msg("Found matching container by domain") | ||||||
|  | 				return labels, nil | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if strings.TrimPrefix(inspect.Name, "/") == app { | ||||||
|  | 			log.Debug().Str("id", inspect.ID).Msg("Found matching container by name") | ||||||
| 			return labels, nil | 			return labels, nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -96,11 +96,29 @@ func (h *Handlers) AuthHandler(c *gin.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Check if the IP is allowed/blocked | 	// Get client IP | ||||||
| 	ip := c.ClientIP() | 	ip := c.ClientIP() | ||||||
| 	if !h.Auth.CheckIP(c, labels) { |  | ||||||
| 		log.Warn().Str("ip", ip).Msg("IP not allowed") |  | ||||||
|  |  | ||||||
|  | 	// Check if the IP is in bypass list | ||||||
|  | 	if h.Auth.BypassedIP(labels, ip) { | ||||||
|  | 		headersParsed := utils.ParseHeaders(labels.Headers) | ||||||
|  | 		for key, value := range headersParsed { | ||||||
|  | 			log.Debug().Str("key", key).Msg("Setting header") | ||||||
|  | 			c.Header(key, value) | ||||||
|  | 		} | ||||||
|  | 		if labels.Basic.Username != "" && utils.GetSecret(labels.Basic.Password.Plain, labels.Basic.Password.File) != "" { | ||||||
|  | 			log.Debug().Str("username", labels.Basic.Username).Msg("Setting basic auth headers") | ||||||
|  | 			c.Header("Authorization", fmt.Sprintf("Basic %s", utils.GetBasicAuth(labels.Basic.Username, utils.GetSecret(labels.Basic.Password.Plain, labels.Basic.Password.File)))) | ||||||
|  | 		} | ||||||
|  | 		c.JSON(200, gin.H{ | ||||||
|  | 			"status":  200, | ||||||
|  | 			"message": "Authenticated", | ||||||
|  | 		}) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Check if the IP is allowed/blocked | ||||||
|  | 	if !h.Auth.CheckIP(labels, ip) { | ||||||
| 		if proxy.Proxy == "nginx" || !isBrowser { | 		if proxy.Proxy == "nginx" || !isBrowser { | ||||||
| 			c.JSON(403, gin.H{ | 			c.JSON(403, gin.H{ | ||||||
| 				"status":  403, | 				"status":  403, | ||||||
|   | |||||||
| @@ -120,8 +120,9 @@ type PassowrdLabels struct { | |||||||
|  |  | ||||||
| // IP labels for a tinyauth protected container | // IP labels for a tinyauth protected container | ||||||
| type IPLabels struct { | type IPLabels struct { | ||||||
| 	Allow []string | 	Allow  []string | ||||||
| 	Block []string | 	Block  []string | ||||||
|  | 	Bypass []string | ||||||
| } | } | ||||||
|  |  | ||||||
| // Labels is a struct that contains the labels for a tinyauth protected container | // Labels is a struct that contains the labels for a tinyauth protected container | ||||||
| @@ -129,7 +130,7 @@ type Labels struct { | |||||||
| 	Users   string | 	Users   string | ||||||
| 	Allowed string | 	Allowed string | ||||||
| 	Headers []string | 	Headers []string | ||||||
| 	Domain  string | 	Domain  []string | ||||||
| 	Basic   BasicLabels | 	Basic   BasicLabels | ||||||
| 	OAuth   OAuthLabels | 	OAuth   OAuthLabels | ||||||
| 	IP      IPLabels | 	IP      IPLabels | ||||||
|   | |||||||
| @@ -292,17 +292,17 @@ func ParseSecretFile(contents string) string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
| // Check if a string matches a regex or a whitelist | // Check if a string matches a regex or if it is included in a comma separated list | ||||||
| func CheckWhitelist(whitelist string, str string) bool { | func CheckFilter(filter string, str string) bool { | ||||||
| 	// Check if the whitelist is empty | 	// Check if the filter is empty | ||||||
| 	if len(strings.TrimSpace(whitelist)) == 0 { | 	if len(strings.TrimSpace(filter)) == 0 { | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Check if the whitelist is a regex | 	// Check if the filter is a regex | ||||||
| 	if strings.HasPrefix(whitelist, "/") && strings.HasSuffix(whitelist, "/") { | 	if strings.HasPrefix(filter, "/") && strings.HasSuffix(filter, "/") { | ||||||
| 		// Create regex | 		// Create regex | ||||||
| 		re, err := regexp.Compile(whitelist[1 : len(whitelist)-1]) | 		re, err := regexp.Compile(filter[1 : len(filter)-1]) | ||||||
|  |  | ||||||
| 		// Check if there was an error | 		// Check if there was an error | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @@ -316,11 +316,11 @@ func CheckWhitelist(whitelist string, str string) bool { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Split the whitelist by comma | 	// Split the filter by comma | ||||||
| 	whitelistSplit := strings.Split(whitelist, ",") | 	filterSplit := strings.Split(filter, ",") | ||||||
|  |  | ||||||
| 	// Loop through the whitelist | 	// Loop through the filter items | ||||||
| 	for _, item := range whitelistSplit { | 	for _, item := range filterSplit { | ||||||
| 		// Check if the item matches with the string | 		// Check if the item matches with the string | ||||||
| 		if strings.TrimSpace(item) == str { | 		if strings.TrimSpace(item) == str { | ||||||
| 			return true | 			return true | ||||||
|   | |||||||
| @@ -377,77 +377,77 @@ func TestParseUser(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Test the whitelist function | // Test the check filter function | ||||||
| func TestCheckWhitelist(t *testing.T) { | func TestCheckFilter(t *testing.T) { | ||||||
| 	t.Log("Testing check whitelist with a comma whitelist") | 	t.Log("Testing check filter with a comma separated list") | ||||||
|  |  | ||||||
| 	// Create variables | 	// Create variables | ||||||
| 	whitelist := "user1,user2,user3" | 	filter := "user1,user2,user3" | ||||||
| 	str := "user1" | 	str := "user1" | ||||||
| 	expected := true | 	expected := true | ||||||
|  |  | ||||||
| 	// Test the check whitelist function | 	// Test the check filter function | ||||||
| 	result := utils.CheckWhitelist(whitelist, str) | 	result := utils.CheckFilter(filter, str) | ||||||
|  |  | ||||||
| 	// Check if the result is equal to the expected | 	// Check if the result is equal to the expected | ||||||
| 	if result != expected { | 	if result != expected { | ||||||
| 		t.Fatalf("Expected %v, got %v", expected, result) | 		t.Fatalf("Expected %v, got %v", expected, result) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	t.Log("Testing check whitelist with a regex whitelist") | 	t.Log("Testing check filter with a regex filter") | ||||||
|  |  | ||||||
| 	// Create variables | 	// Create variables | ||||||
| 	whitelist = "/^user[0-9]+$/" | 	filter = "/^user[0-9]+$/" | ||||||
| 	str = "user1" | 	str = "user1" | ||||||
| 	expected = true | 	expected = true | ||||||
|  |  | ||||||
| 	// Test the check whitelist function | 	// Test the check filter function | ||||||
| 	result = utils.CheckWhitelist(whitelist, str) | 	result = utils.CheckFilter(filter, str) | ||||||
|  |  | ||||||
| 	// Check if the result is equal to the expected | 	// Check if the result is equal to the expected | ||||||
| 	if result != expected { | 	if result != expected { | ||||||
| 		t.Fatalf("Expected %v, got %v", expected, result) | 		t.Fatalf("Expected %v, got %v", expected, result) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	t.Log("Testing check whitelist with an empty whitelist") | 	t.Log("Testing check filter with an empty filter") | ||||||
|  |  | ||||||
| 	// Create variables | 	// Create variables | ||||||
| 	whitelist = "" | 	filter = "" | ||||||
| 	str = "user1" | 	str = "user1" | ||||||
| 	expected = true | 	expected = true | ||||||
|  |  | ||||||
| 	// Test the check whitelist function | 	// Test the check filter function | ||||||
| 	result = utils.CheckWhitelist(whitelist, str) | 	result = utils.CheckFilter(filter, str) | ||||||
|  |  | ||||||
| 	// Check if the result is equal to the expected | 	// Check if the result is equal to the expected | ||||||
| 	if result != expected { | 	if result != expected { | ||||||
| 		t.Fatalf("Expected %v, got %v", expected, result) | 		t.Fatalf("Expected %v, got %v", expected, result) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	t.Log("Testing check whitelist with an invalid regex whitelist") | 	t.Log("Testing check filter with an invalid regex filter") | ||||||
|  |  | ||||||
| 	// Create variables | 	// Create variables | ||||||
| 	whitelist = "/^user[0-9+$/" | 	filter = "/^user[0-9+$/" | ||||||
| 	str = "user1" | 	str = "user1" | ||||||
| 	expected = false | 	expected = false | ||||||
|  |  | ||||||
| 	// Test the check whitelist function | 	// Test the check filter function | ||||||
| 	result = utils.CheckWhitelist(whitelist, str) | 	result = utils.CheckFilter(filter, str) | ||||||
|  |  | ||||||
| 	// Check if the result is equal to the expected | 	// Check if the result is equal to the expected | ||||||
| 	if result != expected { | 	if result != expected { | ||||||
| 		t.Fatalf("Expected %v, got %v", expected, result) | 		t.Fatalf("Expected %v, got %v", expected, result) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	t.Log("Testing check whitelist with a non matching whitelist") | 	t.Log("Testing check filter with a non matching list") | ||||||
|  |  | ||||||
| 	// Create variables | 	// Create variables | ||||||
| 	whitelist = "user1,user2,user3" | 	filter = "user1,user2,user3" | ||||||
| 	str = "user4" | 	str = "user4" | ||||||
| 	expected = false | 	expected = false | ||||||
|  |  | ||||||
| 	// Test the check whitelist function | 	// Test the check filter function | ||||||
| 	result = utils.CheckWhitelist(whitelist, str) | 	result = utils.CheckFilter(filter, str) | ||||||
|  |  | ||||||
| 	// Check if the result is equal to the expected | 	// Check if the result is equal to the expected | ||||||
| 	if result != expected { | 	if result != expected { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user