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  }