keystore.gno

4.11 Kb ยท 184 lines
  1package keystore
  2
  3import (
  4	"std"
  5	"strings"
  6
  7	"gno.land/p/demo/avl"
  8	"gno.land/p/demo/ufmt"
  9)
 10
 11var data avl.Tree
 12
 13const (
 14	BaseURL               = "/r/demo/keystore"
 15	StatusOK              = "ok"
 16	StatusNoUser          = "user not found"
 17	StatusNotFound        = "key not found"
 18	StatusNoWriteAccess   = "no write access"
 19	StatusCouldNotExecute = "could not execute"
 20	StatusNoDatabases     = "no databases"
 21)
 22
 23func init() {
 24	data = avl.Tree{} // user -> avl.Tree
 25}
 26
 27// KeyStore stores the owner-specific avl.Tree
 28type KeyStore struct {
 29	Owner std.Address
 30	Data  avl.Tree
 31}
 32
 33// Set will set a value to a key
 34// requires write-access (original caller must be caller)
 35func Set(k, v string) string {
 36	origOwner := std.OriginCaller()
 37	return set(origOwner.String(), k, v)
 38}
 39
 40// set (private) will set a key to value
 41// requires write-access (original caller must be caller)
 42func set(owner, k, v string) string {
 43	origOwner := std.OriginCaller()
 44	if origOwner.String() != owner {
 45		return StatusNoWriteAccess
 46	}
 47	var keystore *KeyStore
 48	keystoreInterface, exists := data.Get(owner)
 49	if !exists {
 50		keystore = &KeyStore{
 51			Owner: origOwner,
 52			Data:  avl.Tree{},
 53		}
 54		data.Set(owner, keystore)
 55	} else {
 56		keystore = keystoreInterface.(*KeyStore)
 57	}
 58	keystore.Data.Set(k, v)
 59	return StatusOK
 60}
 61
 62// Remove removes a key
 63// requires write-access (original owner must be caller)
 64func Remove(k string) string {
 65	origOwner := std.OriginCaller()
 66	return remove(origOwner.String(), k)
 67}
 68
 69// remove (private) removes a key
 70// requires write-access (original owner must be caller)
 71func remove(owner, k string) string {
 72	origOwner := std.OriginCaller()
 73	if origOwner.String() != owner {
 74		return StatusNoWriteAccess
 75	}
 76	var keystore *KeyStore
 77	keystoreInterface, exists := data.Get(owner)
 78	if !exists {
 79		keystore = &KeyStore{
 80			Owner: origOwner,
 81			Data:  avl.Tree{},
 82		}
 83		data.Set(owner, keystore)
 84	} else {
 85		keystore = keystoreInterface.(*KeyStore)
 86	}
 87	_, removed := keystore.Data.Remove(k)
 88	if !removed {
 89		return StatusCouldNotExecute
 90	}
 91	return StatusOK
 92}
 93
 94// Get returns a value for a key
 95// read-only
 96func Get(k string) string {
 97	origOwner := std.OriginCaller()
 98	return remove(origOwner.String(), k)
 99}
100
101// get (private) returns a value for a key
102// read-only
103func get(owner, k string) string {
104	keystoreInterface, exists := data.Get(owner)
105	if !exists {
106		return StatusNoUser
107	}
108	keystore := keystoreInterface.(*KeyStore)
109	val, found := keystore.Data.Get(k)
110	if !found {
111		return StatusNotFound
112	}
113	return val.(string)
114}
115
116// Size returns size of database
117// read-only
118func Size() string {
119	origOwner := std.OriginCaller()
120	return size(origOwner.String())
121}
122
123func size(owner string) string {
124	keystoreInterface, exists := data.Get(owner)
125	if !exists {
126		return StatusNoUser
127	}
128	keystore := keystoreInterface.(*KeyStore)
129	return ufmt.Sprintf("%d", keystore.Data.Size())
130}
131
132// Render provides read-only url access to the functions of the keystore
133// "" -> show all keystores listed by owner
134// "owner" -> show all keys for that owner's keystore
135// "owner:size" -> returns size of owner's keystore
136// "owner:get:key" -> show value for that key in owner's keystore
137func Render(p string) string {
138	var response string
139	args := strings.Split(p, ":")
140	numArgs := len(args)
141	if p == "" {
142		numArgs = 0
143	}
144	switch numArgs {
145	case 0:
146		if data.Size() == 0 {
147			return StatusNoDatabases
148		}
149		data.Iterate("", "", func(key string, value any) bool {
150			ks := value.(*KeyStore)
151			response += ufmt.Sprintf("- [%s](%s:%s) (%d keys)\n", ks.Owner, BaseURL, ks.Owner, ks.Data.Size())
152			return false
153		})
154	case 1:
155		owner := args[0]
156		keystoreInterface, exists := data.Get(owner)
157		if !exists {
158			return StatusNoUser
159		}
160		ks := keystoreInterface.(*KeyStore)
161		i := 0
162		response += ufmt.Sprintf("# %s database\n\n", ks.Owner)
163		ks.Data.Iterate("", "", func(key string, value any) bool {
164			response += ufmt.Sprintf("- %d [%s](%s:%s:get:%s)\n", i, key, BaseURL, ks.Owner, key)
165			i++
166			return false
167		})
168	case 2:
169		owner := args[0]
170		cmd := args[1]
171		if cmd == "size" {
172			return size(owner)
173		}
174	case 3:
175		owner := args[0]
176		cmd := args[1]
177		key := args[2]
178		if cmd == "get" {
179			return get(owner, key)
180		}
181	}
182
183	return response
184}