github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/r/demo/keystore/keystore.gno (about) 1 package keystore 2 3 import ( 4 "std" 5 "strings" 6 7 "gno.land/p/demo/avl" 8 "gno.land/p/demo/ufmt" 9 ) 10 11 var data avl.Tree 12 13 const ( 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 23 func init() { 24 data = avl.Tree{} // user -> avl.Tree 25 } 26 27 // KeyStore stores the owner-specific avl.Tree 28 type 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) 35 func Set(k, v string) string { 36 origOwner := std.GetOrigCaller() 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) 42 func set(owner, k, v string) string { 43 origOwner := std.GetOrigCaller() 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) 64 func Remove(k string) string { 65 origOwner := std.GetOrigCaller() 66 return remove(origOwner.String(), k) 67 } 68 69 // remove (private) removes a key 70 // requires write-access (original owner must be caller) 71 func remove(owner, k string) string { 72 origOwner := std.GetOrigCaller() 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 96 func Get(k string) string { 97 origOwner := std.GetOrigCaller() 98 return remove(origOwner.String(), k) 99 } 100 101 // get (private) returns a value for a key 102 // read-only 103 func 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 118 func Size() string { 119 origOwner := std.GetOrigCaller() 120 return size(origOwner.String()) 121 } 122 123 func 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 137 func 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 interface{}) 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 interface{}) 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 }