mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-31 06:05:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			276 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package utils_test
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"testing"
 | |
| 	"tinyauth/internal/config"
 | |
| 	"tinyauth/internal/utils"
 | |
| 
 | |
| 	"github.com/gin-gonic/gin"
 | |
| 	"gotest.tools/v3/assert"
 | |
| )
 | |
| 
 | |
| func TestGetRootDomain(t *testing.T) {
 | |
| 	// Normal case
 | |
| 	domain := "http://sub.tinyauth.app"
 | |
| 	expected := "tinyauth.app"
 | |
| 	result, err := utils.GetCookieDomain(domain)
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Domain with multiple subdomains
 | |
| 	domain = "http://b.c.tinyauth.app"
 | |
| 	expected = "c.tinyauth.app"
 | |
| 	result, err = utils.GetCookieDomain(domain)
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Domain with no subdomain
 | |
| 	domain = "http://tinyauth.app"
 | |
| 	expected = "tinyauth.app"
 | |
| 	_, err = utils.GetCookieDomain(domain)
 | |
| 	assert.Error(t, err, "invalid app url, must be at least second level domain")
 | |
| 
 | |
| 	// Invalid domain (only TLD)
 | |
| 	domain = "com"
 | |
| 	_, err = utils.GetCookieDomain(domain)
 | |
| 	assert.ErrorContains(t, err, "invalid app url, must be at least second level domain")
 | |
| 
 | |
| 	// IP address
 | |
| 	domain = "http://10.10.10.10"
 | |
| 	_, err = utils.GetCookieDomain(domain)
 | |
| 	assert.ErrorContains(t, err, "IP addresses not allowed")
 | |
| 
 | |
| 	// Invalid URL
 | |
| 	domain = "http://[::1]:namedport"
 | |
| 	_, err = utils.GetCookieDomain(domain)
 | |
| 	assert.ErrorContains(t, err, "parse \"http://[::1]:namedport\": invalid port \":namedport\" after host")
 | |
| 
 | |
| 	// URL with scheme and path
 | |
| 	domain = "https://sub.tinyauth.app/path"
 | |
| 	expected = "tinyauth.app"
 | |
| 	result, err = utils.GetCookieDomain(domain)
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// URL with port
 | |
| 	domain = "http://sub.tinyauth.app:8080"
 | |
| 	expected = "tinyauth.app"
 | |
| 	result, err = utils.GetCookieDomain(domain)
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Domain managed by ICANN
 | |
| 	domain = "http://example.co.uk"
 | |
| 	_, err = utils.GetCookieDomain(domain)
 | |
| 	assert.Error(t, err, "domain in public suffix list, cannot set cookies")
 | |
| }
 | |
| 
 | |
| func TestParseFileToLine(t *testing.T) {
 | |
| 	// Normal case
 | |
| 	content := "user1\nuser2\nuser3"
 | |
| 	expected := "user1,user2,user3"
 | |
| 	result := utils.ParseFileToLine(content)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Case with empty lines and spaces
 | |
| 	content = " user1 \n\n user2 \n user3 \n"
 | |
| 	expected = "user1,user2,user3"
 | |
| 	result = utils.ParseFileToLine(content)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Case with only empty lines
 | |
| 	content = "\n\n\n"
 | |
| 	expected = ""
 | |
| 	result = utils.ParseFileToLine(content)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Case with single user
 | |
| 	content = "singleuser"
 | |
| 	expected = "singleuser"
 | |
| 	result = utils.ParseFileToLine(content)
 | |
| 	assert.Equal(t, expected, result)
 | |
| 
 | |
| 	// Case with trailing newline
 | |
| 	content = "user1\nuser2\n"
 | |
| 	expected = "user1,user2"
 | |
| 	result = utils.ParseFileToLine(content)
 | |
| 	assert.Equal(t, expected, result)
 | |
| }
 | |
| 
 | |
| func TestFilter(t *testing.T) {
 | |
| 	// Normal case
 | |
| 	slice := []int{1, 2, 3, 4, 5}
 | |
| 	testFunc := func(n int) bool { return n%2 == 0 }
 | |
| 	expected := []int{2, 4}
 | |
| 	result := utils.Filter(slice, testFunc)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with no matches
 | |
| 	slice = []int{1, 3, 5}
 | |
| 	testFunc = func(n int) bool { return n%2 == 0 }
 | |
| 	expected = []int{}
 | |
| 	result = utils.Filter(slice, testFunc)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with all matches
 | |
| 	slice = []int{2, 4, 6}
 | |
| 	testFunc = func(n int) bool { return n%2 == 0 }
 | |
| 	expected = []int{2, 4, 6}
 | |
| 	result = utils.Filter(slice, testFunc)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with empty slice
 | |
| 	slice = []int{}
 | |
| 	testFunc = func(n int) bool { return n%2 == 0 }
 | |
| 	expected = []int{}
 | |
| 	result = utils.Filter(slice, testFunc)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with different type (string)
 | |
| 	sliceStr := []string{"apple", "banana", "cherry"}
 | |
| 	testFuncStr := func(s string) bool { return len(s) > 5 }
 | |
| 	expectedStr := []string{"banana", "cherry"}
 | |
| 	resultStr := utils.Filter(sliceStr, testFuncStr)
 | |
| 	assert.DeepEqual(t, expectedStr, resultStr)
 | |
| }
 | |
| 
 | |
| func TestGetContext(t *testing.T) {
 | |
| 	// Setup
 | |
| 	gin.SetMode(gin.TestMode)
 | |
| 	c, _ := gin.CreateTestContext(nil)
 | |
| 
 | |
| 	// Normal case
 | |
| 	c.Set("context", &config.UserContext{Username: "testuser"})
 | |
| 	result, err := utils.GetContext(c)
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.Equal(t, "testuser", result.Username)
 | |
| 
 | |
| 	// Case with no context
 | |
| 	c.Set("context", nil)
 | |
| 	_, err = utils.GetContext(c)
 | |
| 	assert.Error(t, err, "invalid user context in request")
 | |
| 
 | |
| 	// Case with invalid context type
 | |
| 	c.Set("context", "invalid type")
 | |
| 	_, err = utils.GetContext(c)
 | |
| 	assert.Error(t, err, "invalid user context in request")
 | |
| }
 | |
| 
 | |
| func TestIsRedirectSafe(t *testing.T) {
 | |
| 	// Setup
 | |
| 	domain := "example.com"
 | |
| 
 | |
| 	// Case with no subdomain
 | |
| 	redirectURL := "http://example.com/welcome"
 | |
| 	result := utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, false, result)
 | |
| 
 | |
| 	// Case with different domain
 | |
| 	redirectURL = "http://malicious.com/phishing"
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, false, result)
 | |
| 
 | |
| 	// Case with subdomain
 | |
| 	redirectURL = "http://sub.example.com/page"
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, true, result)
 | |
| 
 | |
| 	// Case with empty redirect URL
 | |
| 	redirectURL = ""
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, false, result)
 | |
| 
 | |
| 	// Case with invalid URL
 | |
| 	redirectURL = "http://[::1]:namedport"
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, false, result)
 | |
| 
 | |
| 	// Case with URL having port
 | |
| 	redirectURL = "http://sub.example.com:8080/page"
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, true, result)
 | |
| 
 | |
| 	// Case with URL having different subdomain
 | |
| 	redirectURL = "http://another.example.com/page"
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, true, result)
 | |
| 
 | |
| 	// Case with URL having different TLD
 | |
| 	redirectURL = "http://example.org/page"
 | |
| 	result = utils.IsRedirectSafe(redirectURL, domain)
 | |
| 	assert.Equal(t, false, result)
 | |
| }
 | |
| 
 | |
| func TestGetOAuthProvidersConfig(t *testing.T) {
 | |
| 	env := []string{"PROVIDERS_CLIENT1_CLIENT_ID=client1-id", "PROVIDERS_CLIENT1_CLIENT_SECRET=client1-secret"}
 | |
| 	args := []string{"/tinyauth/tinyauth", "--providers-client2-client-id=client2-id", "--providers-client2-client-secret=client2-secret"}
 | |
| 
 | |
| 	expected := map[string]config.OAuthServiceConfig{
 | |
| 		"client1": {
 | |
| 			ClientID:     "client1-id",
 | |
| 			ClientSecret: "client1-secret",
 | |
| 			Name:         "Client1",
 | |
| 		},
 | |
| 		"client2": {
 | |
| 			ClientID:     "client2-id",
 | |
| 			ClientSecret: "client2-secret",
 | |
| 			Name:         "Client2",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	result, err := utils.GetOAuthProvidersConfig(env, args, "")
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with no providers
 | |
| 	env = []string{}
 | |
| 	args = []string{"/tinyauth/tinyauth"}
 | |
| 	expected = map[string]config.OAuthServiceConfig{}
 | |
| 
 | |
| 	result, err = utils.GetOAuthProvidersConfig(env, args, "")
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with secret from file
 | |
| 	file, err := os.Create("/tmp/tinyauth_test_file")
 | |
| 	assert.NilError(t, err)
 | |
| 
 | |
| 	_, err = file.WriteString("file content\n")
 | |
| 	assert.NilError(t, err)
 | |
| 
 | |
| 	err = file.Close()
 | |
| 	assert.NilError(t, err)
 | |
| 	defer os.Remove("/tmp/tinyauth_test_file")
 | |
| 
 | |
| 	env = []string{"PROVIDERS_CLIENT1_CLIENT_ID=client1-id", "PROVIDERS_CLIENT1_CLIENT_SECRET_FILE=/tmp/tinyauth_test_file"}
 | |
| 	args = []string{"/tinyauth/tinyauth"}
 | |
| 	expected = map[string]config.OAuthServiceConfig{
 | |
| 		"client1": {
 | |
| 			ClientID:     "client1-id",
 | |
| 			ClientSecret: "file content",
 | |
| 			Name:         "Client1",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	result, err = utils.GetOAuthProvidersConfig(env, args, "")
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| 
 | |
| 	// Case with google provider and no redirect URL
 | |
| 	env = []string{"PROVIDERS_GOOGLE_CLIENT_ID=google-id", "PROVIDERS_GOOGLE_CLIENT_SECRET=google-secret"}
 | |
| 	args = []string{"/tinyauth/tinyauth"}
 | |
| 	expected = map[string]config.OAuthServiceConfig{
 | |
| 		"google": {
 | |
| 			ClientID:     "google-id",
 | |
| 			ClientSecret: "google-secret",
 | |
| 			RedirectURL:  "http://app.url/api/oauth/callback/google",
 | |
| 			Name:         "Google",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	result, err = utils.GetOAuthProvidersConfig(env, args, "http://app.url")
 | |
| 	assert.NilError(t, err)
 | |
| 	assert.DeepEqual(t, expected, result)
 | |
| }
 | 
