Files
filekeeper/utils/utils.go

167 lines
3.3 KiB
Go

package utils
import (
cryptoRand "crypto/rand"
"crypto/sha1"
"encoding/base64"
"fmt"
mathRand "math/rand"
"net/http"
"os"
"strings"
"sync"
"time"
"unicode"
"github.com/fossyy/filekeeper/logger"
"github.com/joho/godotenv"
"golang.org/x/crypto/bcrypt"
)
type Env struct {
value map[string]string
mu sync.Mutex
}
var env *Env
var log *logger.AggregatedLogger
func init() {
env = &Env{value: map[string]string{}}
}
func ClientIP(request *http.Request) string {
ip := request.Header.Get("Cf-Connecting-IP")
if ip != "" {
return ip
}
ip = request.Header.Get("X-Real-IP")
if ip == "" {
ip = request.Header.Get("X-Forwarded-For")
if ip == "" {
ip = request.RemoteAddr
}
}
if strings.Contains(ip, ",") {
ips := strings.Split(ip, ",")
ip = strings.TrimSpace(ips[0])
}
if strings.Contains(ip, ":") {
ips := strings.Split(ip, ":")
ip = ips[0]
}
return ip
}
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
func CheckPasswordHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
func ValidatePassword(password string) bool {
if len(password) < 6 {
return false
}
var (
hasSymbol bool
hasNumber int
hasUppercase bool
)
symbols := []string{"!", "@", "#", "$", "%", "^", "&", "*"}
for _, symbol := range symbols {
if strings.Contains(password, symbol) {
hasSymbol = true
}
}
for _, char := range password {
switch {
case unicode.IsNumber(char):
hasNumber++
case unicode.IsUpper(char):
hasUppercase = true
}
}
return hasSymbol && hasNumber >= 3 && hasUppercase
}
func ConvertFileSize(byte int64) string {
if byte < 1024 {
return fmt.Sprintf("%d B", byte)
} else if byte < 1024*1024 {
return fmt.Sprintf("%d KB", byte/1024)
} else if byte < 1024*1024*1024 {
return fmt.Sprintf("%d MB", byte/(1024*1024))
} else {
return fmt.Sprintf("%d GB", byte/(1024*1024*1024))
}
}
func Getenv(key string) string {
env.mu.Lock()
defer env.mu.Unlock()
if val, ok := env.value[key]; ok {
return val
}
if os.Getenv("HOSTNAME") == "" {
err := godotenv.Load(".env")
if err != nil {
log.Error("Error loading .env file: %s", err)
}
}
val := os.Getenv(key)
env.value[key] = val
return val
}
func GenerateRandomString(length int) string {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
seededRand := mathRand.New(mathRand.NewSource(time.Now().UnixNano() + int64(mathRand.Intn(9999))))
var result strings.Builder
for i := 0; i < length; i++ {
randomIndex := seededRand.Intn(len(charset))
result.WriteString(string(charset[randomIndex]))
}
return result.String()
}
func GenerateCSRFToken() (string, error) {
tokenBytes := make([]byte, 32)
_, err := cryptoRand.Read(tokenBytes)
if err != nil {
return "", err
}
hash := sha1.New()
hash.Write(tokenBytes)
hashedToken := hash.Sum(nil)
csrfToken := base64.URLEncoding.EncodeToString(hashedToken)
return csrfToken, nil
}
func SanitizeFilename(filename string) string {
invalidChars := []string{"\\", "/", ":", "*", "?", "\"", "<", ">", "|"}
for _, char := range invalidChars {
filename = strings.ReplaceAll(filename, char, "_")
}
return filename
}