owl-blogs/app/author_service.go

87 lines
2.0 KiB
Go

package app
import (
"crypto/sha256"
"fmt"
"owl-blogs/app/repository"
"owl-blogs/domain/model"
"strings"
"golang.org/x/crypto/bcrypt"
)
type AuthorService struct {
repo repository.AuthorRepository
siteConfigRepo repository.SiteConfigRepository
}
func NewAuthorService(repo repository.AuthorRepository, siteConfigRepo repository.SiteConfigRepository) *AuthorService {
return &AuthorService{repo: repo, siteConfigRepo: siteConfigRepo}
}
func hashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil {
return "", err
}
return string(bytes), nil
}
func (s *AuthorService) Create(name string, password string) (*model.Author, error) {
hash, err := hashPassword(password)
if err != nil {
return nil, err
}
return s.repo.Create(name, hash)
}
func (s *AuthorService) FindByName(name string) (*model.Author, error) {
return s.repo.FindByName(name)
}
func (s *AuthorService) Authenticate(name string, password string) bool {
author, err := s.repo.FindByName(name)
if err != nil {
return false
}
err = bcrypt.CompareHashAndPassword([]byte(author.PasswordHash), []byte(password))
return err == nil
}
func (s *AuthorService) getSecretKey() string {
config, err := s.siteConfigRepo.Get()
if err != nil {
panic(err)
}
if config.Secret == "" {
config.Secret = RandStringRunes(64)
err = s.siteConfigRepo.Update(config)
if err != nil {
panic(err)
}
}
return config.Secret
}
func (s *AuthorService) CreateToken(name string) (string, error) {
hash := sha256.New()
_, err := hash.Write([]byte(name + s.getSecretKey()))
if err != nil {
return "", err
}
return fmt.Sprintf("%s.%x", name, hash.Sum(nil)), nil
}
func (s *AuthorService) ValidateToken(token string) (bool, string) {
parts := strings.Split(token, ".")
witness := parts[len(parts)-1]
name := strings.Join(parts[:len(parts)-1], ".")
hash := sha256.New()
_, err := hash.Write([]byte(name + s.getSecretKey()))
if err != nil {
return false, ""
}
return fmt.Sprintf("%x", hash.Sum(nil)) == witness, name
}