feature/verified (#61)
* add store methods for verification * add verify rest and auth * lint: fix double conversion of userID key * test for middleware, fix log without auth info * make all scripts with -e
This commit is contained in:
@@ -35,6 +35,7 @@ const (
|
||||
blocksBucketName = "block"
|
||||
infoBucketName = "info"
|
||||
readonlyBucketName = "readonly"
|
||||
verifiedBucketName = "verified"
|
||||
|
||||
// limits
|
||||
lastLimit = 1000
|
||||
@@ -62,7 +63,7 @@ func NewBoltDB(options bolt.Options, sites ...BoltSite) (*BoltDB, error) {
|
||||
|
||||
// make top-level buckets
|
||||
topBuckets := []string{postsBucketName, lastBucketName, userBucketName, blocksBucketName,
|
||||
infoBucketName, readonlyBucketName}
|
||||
infoBucketName, readonlyBucketName, verifiedBucketName}
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
for _, bktName := range topBuckets {
|
||||
if _, e := tx.CreateBucketIfNotExists([]byte(bktName)); e != nil {
|
||||
|
||||
@@ -230,7 +230,7 @@ func (b *BoltDB) SetReadOnly(locator store.Locator, status bool) error {
|
||||
switch status {
|
||||
case true:
|
||||
if e := bucket.Put([]byte(locator.URL), []byte(time.Now().Format(tsNano))); e != nil {
|
||||
return errors.Wrapf(e, "failed to set ro for %s to %s", locator.URL, status)
|
||||
return errors.Wrapf(e, "failed to set ro for %s", locator.URL)
|
||||
}
|
||||
case false:
|
||||
if e := bucket.Delete([]byte(locator.URL)); e != nil {
|
||||
@@ -256,3 +256,42 @@ func (b *BoltDB) IsReadOnly(locator store.Locator) (ro bool) {
|
||||
})
|
||||
return ro
|
||||
}
|
||||
|
||||
// SetVerified makes user verified or reset the flag
|
||||
func (b *BoltDB) SetVerified(siteID string, userID string, status bool) error {
|
||||
bdb, err := b.db(siteID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bdb.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(verifiedBucketName))
|
||||
switch status {
|
||||
case true:
|
||||
if e := bucket.Put([]byte(userID), []byte(time.Now().Format(tsNano))); e != nil {
|
||||
return errors.Wrapf(e, "failed to set verified status for %s", userID)
|
||||
}
|
||||
case false:
|
||||
if e := bucket.Delete([]byte(userID)); e != nil {
|
||||
return errors.Wrapf(e, "failed to clean verified status for %s", userID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// IsVerified checks if user verified
|
||||
func (b *BoltDB) IsVerified(siteID string, userID string) (verified bool) {
|
||||
|
||||
bdb, err := b.db(siteID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
_ = bdb.View(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(verifiedBucketName))
|
||||
verified = bucket.Get([]byte(userID)) != nil
|
||||
return nil
|
||||
})
|
||||
return verified
|
||||
}
|
||||
|
||||
@@ -179,3 +179,22 @@ func TestBoltAdmin_ReadOnly(t *testing.T) {
|
||||
|
||||
assert.False(t, b.IsReadOnly(store.Locator{SiteID: "radio-t-bad", URL: "url-1"}), "nothing blocked on wrong site")
|
||||
}
|
||||
|
||||
func TestBoltAdmin_Verified(t *testing.T) {
|
||||
defer os.Remove(testDb)
|
||||
b := prep(t)
|
||||
|
||||
assert.False(t, b.IsVerified("radio-t", "u1"), "nothing verified")
|
||||
|
||||
assert.NoError(t, b.SetVerified("radio-t", "u1", true))
|
||||
assert.True(t, b.IsVerified("radio-t", "u1"), "u1 verified")
|
||||
|
||||
assert.False(t, b.IsVerified("radio-t", "u2"), "u2 still not verified")
|
||||
assert.NoError(t, b.SetVerified("radio-t", "u1", false))
|
||||
assert.False(t, b.IsVerified("radio-t", "u1"), "u1 not verified anymore")
|
||||
|
||||
assert.EqualError(t, b.SetVerified("bad", "u1", true), `site "bad" not found`)
|
||||
assert.NoError(t, b.SetVerified("radio-t", "u1xyz", false))
|
||||
|
||||
assert.False(t, b.IsVerified("radio-t-bad", "u1"), "nothing verified on wrong site")
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ type Admin interface {
|
||||
Blocked(siteID string) ([]store.BlockedUser, error) // get list of blocked users
|
||||
SetReadOnly(locator store.Locator, status bool) error // set/reset read-only flag
|
||||
IsReadOnly(locator store.Locator) bool // check if post read-only
|
||||
SetVerified(siteID string, userID string, status bool) error // set/reset verified flag
|
||||
IsVerified(siteID string, userID string) bool // check verified status
|
||||
}
|
||||
|
||||
// sortComments is for engines can't sort data internally
|
||||
|
||||
@@ -150,3 +150,13 @@ func (s *DataStore) ValidateComment(c *store.Comment) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsVerifiedFn returns func to check if user verified or not
|
||||
func (s *DataStore) IsVerifiedFn() func(siteID string, userID string) bool {
|
||||
return func(siteID string, userID string) bool {
|
||||
if siteID == "" {
|
||||
return false
|
||||
}
|
||||
return s.IsVerified(siteID, userID)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -11,12 +11,13 @@ import (
|
||||
|
||||
// User holds user-related info
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
Picture string `json:"picture"`
|
||||
Admin bool `json:"admin"`
|
||||
Blocked bool `json:"block,omitempty"`
|
||||
IP string `json:"ip,omitempty"`
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
Picture string `json:"picture"`
|
||||
Admin bool `json:"admin"`
|
||||
Blocked bool `json:"block,omitempty"`
|
||||
IP string `json:"ip,omitempty"`
|
||||
Verified bool `json:"verified,omitempty"`
|
||||
}
|
||||
|
||||
var reValidSha = regexp.MustCompile("^[a-fA-F0-9]{40}$")
|
||||
|
||||
Reference in New Issue
Block a user