750b7abcd5
- .claude/CLAUDE.md - .claude/agents/fn-recopilador/SKILL.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - bash/functions/infra/build_cpp_windows.sh - cpp/CMakeLists.txt - cpp/PATTERNS.md - cpp/framework/app_base.cpp - cpp/framework/app_base.h - dev/issues/README.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
31 lines
866 B
Go
31 lines
866 B
Go
package infra
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
// BcryptHtpasswd genera una linea formato htpasswd para basicAuth de Traefik
|
|
// usando bcrypt. Si cost es 0 usa el default 10.
|
|
// Output: "<user>:<bcrypt_hash>" (sin escapado $$ — eso es solo para Docker labels en compose).
|
|
func BcryptHtpasswd(user, password string, cost int) (string, error) {
|
|
if user == "" {
|
|
return "", fmt.Errorf("user cannot be empty")
|
|
}
|
|
if password == "" {
|
|
return "", fmt.Errorf("password cannot be empty")
|
|
}
|
|
if cost == 0 {
|
|
cost = 10
|
|
}
|
|
if cost < bcrypt.MinCost || cost > bcrypt.MaxCost {
|
|
return "", fmt.Errorf("cost %d out of range [%d, %d]", cost, bcrypt.MinCost, bcrypt.MaxCost)
|
|
}
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(password), cost)
|
|
if err != nil {
|
|
return "", fmt.Errorf("bcrypt: %w", err)
|
|
}
|
|
return fmt.Sprintf("%s:%s", user, hash), nil
|
|
}
|