Skip to content

Commit

Permalink
update store
Browse files Browse the repository at this point in the history
  • Loading branch information
leohhhn committed Dec 19, 2024
1 parent 3e99909 commit 7acd8b1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 28 deletions.
6 changes: 5 additions & 1 deletion examples/gno.land/r/sys/users/errors.gno
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package users

import "errors"

const prefix = "r/sys/users:"
const prefix = "r/sys/users: "

var (
ErrUnauthorizedWrite = errors.New(prefix + "not authorized to write to store")
Expand All @@ -17,5 +17,9 @@ var (
ErrUsernameLikeAddress = errors.New(prefix + "username resembles a gno.land address")

ErrAlreadyHasName = errors.New(prefix + "username for this address already registered")
ErrDeletedUser = errors.New(prefix + "cannot register a new username after deleting")
ErrAlreadyDeleted = errors.New(prefix + "cannot delete same user twice")
ErrAliasBeforeName = errors.New(prefix + "cannot register alias before a username")

ErrUserNotExist = errors.New(prefix + "this user has not been registered before")
)
94 changes: 74 additions & 20 deletions examples/gno.land/r/sys/users/store.gno
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ var (
)

const (
maxUsernameLen = 50
WriteUserEvent = "WriteUser"
maxUsernameLen = 50
SetUserEvent = "UserSet"
CreateAliasEvent = "AliasCreated"
deletedUser = "ghost"
)

// WriteUser writes a *new* user to the store
// SetUser writes a *new* user to the store
// Only whitelisted callers can call this function
// Writing to the store can be paused by the admin
func WriteUser(name string, addr std.Address) error {
func SetUser(name string, addr std.Address) error {
if Pausable.IsPaused() {
return pausable.ErrPaused
}
Expand All @@ -36,27 +38,31 @@ func WriteUser(name string, addr std.Address) error {
}

trimmedName := strings.TrimSpace(name)
if err := validate(trimmedName, addr); err != nil {
return err
}

if usernameStore.Has(trimmedName) {
return ErrAlreadyExists
}
// Check if addr is already registered or has been deleted
raw, ok := addressStore.Has(addr.String())
if ok {
if raw.(string) == deletedUser {
return ErrDeletedUser
}

if addressStore.Has(addr.String()) {
return ErrAlreadyHasName // use CreateAlias
}

// Cannot register name which is someone's alias
if aliasStore.Has(trimmedName) {
// Check if name is taken
if usernameStore.Has(trimmedName) || aliasStore.Has(trimmedName) {
return ErrAlreadyExists
}

// Validate fields before writing
if err := validate(trimmedName, addr); err != nil {
return err
}

usernameStore.Set(trimmedName, addr)
addressStore.Set(addr.String(), trimmedName)

std.Emit(WriteUserEvent, "name", name, "address", addr.String())
std.Emit(SetUserEvent, "name", name, "address", addr.String())

return nil
}
Expand All @@ -73,26 +79,74 @@ func CreateAlias(name string, addr std.Address) error {
}

trimmedName := strings.TrimSpace(name)
if err := validate(trimmedName, addr); err != nil {
return err

// Check if addr is already registered or has been deleted
raw, ok := addressStore.Has(addr.String())
if !ok {
return ErrAliasBeforeName // must register beforehand
}

// Cannot register alias without an already registered username
if !addressStore.Has(addr.String()) {
return ErrAliasBeforeName
// Check if user has been deleted
if raw.(string) == deletedUser {
return ErrDeletedUser
}

// Cannot register taken username as alias
if usernameStore.Has(trimmedName) || aliasStore.Has(trimmedName) {
return ErrAlreadyExists
}

// Validate before writing
if err := validate(trimmedName, addr); err != nil {
return err
}

aliasStore.Set(trimmedName, addr)

return nil
}

// XXX: should we have a DeleteUser? Maybe with a separate whitelist?
func DeleteUser(addr std.Address) error {
if Pausable.IsPaused() {
return pausable.ErrPaused
}

if !IsOnWhitelist(std.PrevRealm().Addr()) {
return ErrUnauthorizedWrite
}

// Check if user is registered
raw, ok := addressStore.Get(addr.String())
if !ok {
return ErrUserNotExist
}

username := raw.(string)

// Check if user has already been deleted
if username == deletedUser {
return ErrAlreadyDeleted
}

// Find all aliases to delete
var toDelete []string
aliasStore.Iterate("", "", func(key string, value interface{}) bool {
if value.(std.Address) == addr {
toDelete = append(toDelete, key)
}

return false
})

// Delete user
usernameStore.Set(username, std.Address("")) // todo OR dstore as blacklist
addressStore.Set(addr, deletedUser)
for _, alias := range toDelete {
aliasStore.Set(alias, deletedUser)
}

return nil
}

// IsOnWhitelist checks if the given address has
// permission to write to the user store
Expand Down
12 changes: 6 additions & 6 deletions examples/gno.land/r/sys/users/store_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestWriteUser(t *testing.T) {

std.TestSetRealm(aliceCodeRealm)

uassert.Error(t, WriteUser(aliceUsername, alice), ErrUnauthorizedWrite.Error())
uassert.Error(t, SetUser(aliceUsername, alice), ErrUnauthorizedWrite.Error())
})

// todo tests:
Expand All @@ -40,17 +40,17 @@ func TestWriteUser(t *testing.T) {
std.TestSetRealm(std.NewCodeRealm(gnolandUsers))

// write same user twice
urequire.NoError(t, WriteUser(aliceUsername, alice))
uassert.Error(t, WriteUser(aliceUsername, alice), ErrAlreadyExists.Error())
urequire.NoError(t, SetUser(aliceUsername, alice))
uassert.Error(t, SetUser(aliceUsername, alice), ErrAlreadyExists.Error())
})

t.Run("invalid address", func(t *testing.T) {
t.Parallel()
std.TestSetRealm(std.NewCodeRealm(gnolandUsers))

uassert.Error(t, WriteUser("test123", "invalidaddress"), ErrInvalidAddress.Error())
uassert.Error(t, WriteUser("test123", ""), ErrInvalidAddress.Error())
uassert.Error(t, WriteUser("test123",
uassert.Error(t, SetUser("test123", "invalidaddress"), ErrInvalidAddress.Error())
uassert.Error(t, SetUser("test123", ""), ErrInvalidAddress.Error())
uassert.Error(t, SetUser("test123",
"000000000000000000000000000000000000000000000000"),
ErrInvalidAddress.Error())
})
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/sys/users/users_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ package users
// Address: addr,
// }
//
// urequire.NoError(t, WriteUser(u))
// urequire.NoError(t, SetUser(u))
// uassert.Equal(t, ResolveName("newUsername").Name, "newUsername")
// uassert.Equal(t, ResolveName("newUsername").Address, addr)
// // XXX: ptr for uassert.Equal not supported yet
Expand Down

0 comments on commit 7acd8b1

Please sign in to comment.