-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
101 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Package utils contains utility functions for the application | ||
package utils | ||
|
||
import ( | ||
"math/rand" | ||
"regexp" | ||
"time" | ||
|
||
"github.com/oklog/ulid/v2" | ||
) | ||
|
||
// IsULID checks if the given string is a valid ULID | ||
// ULID pattern: | ||
// | ||
// 01AN4Z07BY 79KA1307SR9X4MV3 | ||
// |----------| |----------------| | ||
// Timestamp Randomness | ||
// | ||
// 10 characters 16 characters | ||
// Crockford's Base32 is used (excludes I, L, O, and U to avoid confusion and abuse) | ||
func isULID(s string) bool { | ||
|
||
ulidRegex := `^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$` | ||
matched, _ := regexp.MatchString(ulidRegex, s) | ||
return matched | ||
} | ||
|
||
// ValidID checks if the given id is valid | ||
func ValidID(id string) bool { | ||
_, err := ulid.Parse(id) | ||
|
||
return err == nil && isULID(id) | ||
} | ||
|
||
// GenerateID generates a new universal ID | ||
func GenerateID() string { | ||
ts := ulid.Timestamp(time.Now()) | ||
source := rand.NewSource(time.Now().UnixNano()) | ||
entropy := rand.New(source) | ||
|
||
return ulid.MustNew(ts, entropy).String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package utils | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
) | ||
|
||
// TestValidID tests the ValidID function with both valid and invalid inputs. | ||
func TestValidID(t *testing.T) { | ||
// Generate a valid ULID for testing. | ||
validULID := GenerateID() | ||
|
||
tests := []struct { | ||
id string | ||
expected bool | ||
}{ | ||
{validULID, true}, | ||
{"0", false}, | ||
{"invalidulid", false}, | ||
{"invalidulid", false}, | ||
{"01B4E6BXY0PRJ5G420D25MWQY!", false}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.id, func(t *testing.T) { | ||
if got := ValidID(tt.id); got != tt.expected { | ||
t.Errorf("ValidID(%s) = %v; want %v", tt.id, got, tt.expected) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestGenerateID(t *testing.T) { | ||
id := GenerateID() | ||
if !ValidID(id) { | ||
t.Errorf("Generated ID is not a valid ULID: %s", id) | ||
} | ||
|
||
if len(id) != 26 { | ||
t.Errorf("Generated ID does not have the correct length: got %v want %v", len(id), 26) | ||
} | ||
|
||
if strings.ContainsAny(id, "ilou") { | ||
t.Errorf("Generated ID contains invalid characters: %s", id) | ||
} | ||
} |