Compare commits

...

2 Commits

Author SHA1 Message Date
Niko Abeler 2acca40afe verifying password 2022-11-03 20:30:05 +01:00
Niko Abeler 7165e4c30a setting user password 2022-11-03 20:25:53 +01:00
7 changed files with 102 additions and 7 deletions

52
cmd/owl/reset_password.go Normal file
View File

@ -0,0 +1,52 @@
package main
import (
"fmt"
"h4kor/owl-blogs"
"math/rand"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(resetPasswordCmd)
}
var resetPasswordCmd = &cobra.Command{
Use: "reset-password",
Short: "Reset the password for a user",
Long: `Reset the password for a user`,
Run: func(cmd *cobra.Command, args []string) {
if user == "" {
println("Username is required")
return
}
repo, err := owl.OpenRepository(repoPath)
if err != nil {
println("Error opening repository: ", err.Error())
return
}
user, err := repo.GetUser(user)
if err != nil {
println("Error getting user: ", err.Error())
return
}
// generate a random password and print it
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, 16)
for i := range b {
b[i] = chars[rand.Intn(len(chars))]
}
password := string(b)
user.ResetPassword(password)
fmt.Println("User: ", user.Name())
fmt.Println("New Password: ", password)
},
}

3
go.mod
View File

@ -6,11 +6,12 @@ require (
github.com/julienschmidt/httprouter v1.3.0
github.com/spf13/cobra v1.5.0
github.com/yuin/goldmark v1.4.13
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
golang.org/x/net v0.1.0
gopkg.in/yaml.v2 v2.4.0
)
require (
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.1.0 // indirect
)

4
go.sum
View File

@ -11,8 +11,12 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

View File

@ -21,7 +21,7 @@ func TestCanRenderPost(t *testing.T) {
func TestRenderOneMe(t *testing.T) {
user := getTestUser()
config, _ := user.Config()
config := user.Config()
config.Me = append(config.Me, owl.UserMe{
Name: "Twitter",
Url: "https://twitter.com/testhandle",
@ -38,7 +38,7 @@ func TestRenderOneMe(t *testing.T) {
func TestRenderTwoMe(t *testing.T) {
user := getTestUser()
config, _ := user.Config()
config := user.Config()
config.Me = append(config.Me, owl.UserMe{
Name: "Twitter",
Url: "https://twitter.com/testhandle",

2
rss.go
View File

@ -29,7 +29,7 @@ type RSSItem struct {
func RenderRSSFeed(user User) (string, error) {
config, _ := user.Config()
config := user.Config()
rss := RSS{
Version: "2.0",

25
user.go
View File

@ -8,6 +8,7 @@ import (
"sort"
"time"
"golang.org/x/crypto/bcrypt"
"gopkg.in/yaml.v2"
)
@ -22,6 +23,7 @@ type UserConfig struct {
HeaderColor string `yaml:"header_color"`
AuthorName string `yaml:"author_name"`
Me []UserMe `yaml:"me"`
PassworHash string `yaml:"password_hash"`
}
type UserMe struct {
@ -207,10 +209,10 @@ func (user User) Template() (string, error) {
return string(base_html), nil
}
func (user User) Config() (UserConfig, error) {
func (user User) Config() UserConfig {
meta := UserConfig{}
err := loadFromYaml(user.ConfigFile(), &meta)
return meta, err
loadFromYaml(user.ConfigFile(), &meta)
return meta
}
func (user User) SetConfig(new_config UserConfig) error {
@ -233,3 +235,20 @@ func (user User) PostAliases() (map[string]*Post, error) {
}
return post_aliases, nil
}
func (user User) ResetPassword(password string) error {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil {
return err
}
config := user.Config()
config.PassworHash = string(bytes)
return user.SetConfig(config)
}
func (user User) VerifyPassword(password string) bool {
err := bcrypt.CompareHashAndPassword(
[]byte(user.Config().PassworHash), []byte(password),
)
return err == nil
}

View File

@ -295,3 +295,22 @@ func TestFaviconSetIfFileExist(t *testing.T) {
os.WriteFile(path.Join(user.MediaDir(), "favicon.ico"), []byte("test"), 0644)
assertions.Assert(t, user.FaviconUrl() != "", "Favicon should not be empty")
}
func TestResetUserPassword(t *testing.T) {
user := getTestUser()
user.ResetPassword("test")
assertions.Assert(t, user.Config().PassworHash != "", "Password Hash should not be empty")
assertions.Assert(t, user.Config().PassworHash != "test", "Password Hash should not be test")
}
func TestVerifyPassword(t *testing.T) {
user := getTestUser()
user.ResetPassword("test")
assertions.Assert(t, user.VerifyPassword("test"), "Password should be correct")
assertions.Assert(t, !user.VerifyPassword("test2"), "Password should be incorrect")
assertions.Assert(t, !user.VerifyPassword(""), "Password should be incorrect")
assertions.Assert(t, !user.VerifyPassword("Test"), "Password should be incorrect")
assertions.Assert(t, !user.VerifyPassword("TEST"), "Password should be incorrect")
assertions.Assert(t, !user.VerifyPassword("0000000"), "Password should be incorrect")
}