diff --git a/cmd/ppass/ppass.go b/cmd/ppass/ppass.go index 9d3b471..b36e336 100644 --- a/cmd/ppass/ppass.go +++ b/cmd/ppass/ppass.go @@ -111,9 +111,101 @@ var showCmd = &cobra.Command{ }, } -var printPeerStrCmd = &cobra.Command{ - Use: "peerstring", - Short: "prints your own peerstring", +var namespaceCmd = &cobra.Command{ + Use: "namespace", + Short: "Add, delete or list namespaces", +} + +var addNamespaceCmd = &cobra.Command{ + Use: "add", + Short: "add a namespace", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + dbPath, _ := cmd.Flags().GetString("db") + client, err := rpc.Receive(dbPath) + + if err != nil { + fmt.Printf("dialing: %s\n", err) + return + } + + namespace := args[0] + + var placeholder int + err = client.Call("Query.AddNamespace", &namespace, &placeholder) + + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Namespace %s was added\n", namespace) + }, +} + +var deleteNamespaceCmd = &cobra.Command{ + Use: "delete", + Short: "delete a namespace", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + dbPath, _ := cmd.Flags().GetString("db") + client, err := rpc.Receive(dbPath) + + if err != nil { + fmt.Printf("dialing: %s\n", err) + return + } + + namespace := args[0] + + var placeholder int + err = client.Call("Query.DeleteNamespace", &namespace, &placeholder) + + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Namespace %s was deleted\n", namespace) + }, +} + +var listNamespacesCmd = &cobra.Command{ + Use: "list", + Short: "list all namespaces", + Run: func(cmd *cobra.Command, args []string) { + dbPath, _ := cmd.Flags().GetString("db") + client, err := rpc.Receive(dbPath) + + if err != nil { + fmt.Printf("dialing: %s\n", err) + return + } + + var reply []string + err = client.Call("Query.ListNamespaces", 0, &reply) + + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Namespaces:\n") + for _, ns := range reply { + fmt.Println(ns) + } + }, +} + +var peerCmd = &cobra.Command{ + Use: "peer", + Short: "Add or remove peers. Get your own peering information", +} + + +var infoCmd = &cobra.Command{ + Use: "info", + Short: "print your own peerstring", Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") client, err := rpc.Receive(dbPath) @@ -131,9 +223,9 @@ var printPeerStrCmd = &cobra.Command{ var addPeerCmd = &cobra.Command{ - Use: "addpeer", + Use: "add", Short: "add a peer", - Args: cobra.ExactArgs(1), + Args: cobra.RangeArgs(1, 2), Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") client, err := rpc.Receive(dbPath) @@ -143,10 +235,19 @@ var addPeerCmd = &cobra.Command{ return } - peerString := args[0] + var namespace string + var peerString string + + if len(args) == 1 { + namespace = "root" + peerString = args[0] + } else { + namespace = args[0] + peerString = args[1] + } var success *bool - np := rpc.NamespacePeer{ Namespace: "root", Peer: peerString } + np := rpc.NamespacePeer{ Namespace: namespace, Peer: peerString } err = client.Call("Query.AddPeer", &np, &success) if err != nil { @@ -159,9 +260,9 @@ var addPeerCmd = &cobra.Command{ } var removePeerCmd = &cobra.Command{ - Use: "removepeer", + Use: "remove", Short: "remove a peer", - Args: cobra.ExactArgs(1), + Args: cobra.RangeArgs(1, 2), Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") client, err := rpc.Receive(dbPath) @@ -171,10 +272,19 @@ var removePeerCmd = &cobra.Command{ return } - peerString := args[0] + var namespace string + var peerString string + + if len(args) == 1 { + namespace = "root" + peerString = args[0] + } else { + namespace = args[0] + peerString = args[1] + } var success *bool - np := rpc.NamespacePeer{ Namespace: "root", Peer: peerString } + np := rpc.NamespacePeer{ Namespace: namespace, Peer: peerString } err = client.Call("Query.DeletePeer", &np, &success) if err != nil { @@ -189,7 +299,7 @@ var removePeerCmd = &cobra.Command{ var deleteCmd = &cobra.Command{ Use: "delete", Short: "delete a Password", - Args: cobra.ExactArgs(1), + Args: cobra.RangeArgs(1, 2), Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") client, err := rpc.Receive(dbPath) @@ -199,10 +309,19 @@ var deleteCmd = &cobra.Command{ return } - serviceName := args[0] + var namespace string + var serviceName string + + if len(args) == 1 { + namespace = "root" + serviceName = args[0] + } else { + namespace = args[0] + serviceName = args[1] + } var success *bool - np := rpc.NamespaceService{ Namespace: "root", Service: serviceName } + np := rpc.NamespaceService{ Namespace: namespace, Service: serviceName } err = client.Call("Query.Delete", &np, &success) if err != nil { @@ -215,19 +334,24 @@ var deleteCmd = &cobra.Command{ func init() { - // Add flags to the 'list' command //listCmd.Flags().BoolP("all", "a", false, "List all items") rootCmd.PersistentFlags().String("db", "", "db path") rootCmd.MarkPersistentFlagRequired("db") - // Add subcommands to the root command + peerCmd.AddCommand(addPeerCmd) + peerCmd.AddCommand(removePeerCmd) + peerCmd.AddCommand(infoCmd) + + namespaceCmd.AddCommand(addNamespaceCmd) + namespaceCmd.AddCommand(deleteNamespaceCmd) + namespaceCmd.AddCommand(listNamespacesCmd) + rootCmd.AddCommand(listCmd) rootCmd.AddCommand(generateCmd) rootCmd.AddCommand(showCmd) rootCmd.AddCommand(deleteCmd) - rootCmd.AddCommand(addPeerCmd) - rootCmd.AddCommand(removePeerCmd) - rootCmd.AddCommand(printPeerStrCmd) + rootCmd.AddCommand(peerCmd) + rootCmd.AddCommand(namespaceCmd) } func main() { @@ -235,242 +359,4 @@ func main() { fmt.Println(err) os.Exit(1) } - - //flag.Parse() - - //client, err := rpc.Receive(*dbPath) - - //if err != nil { - // fmt.Printf("dialing: %s\n", err) - // return - //} - - //var names []string - //namespace := "root" - //err = client.Call("Query.GetAllNames", &namespace, &names) - - //if err != nil { - // fmt.Println(err) - //} - - //fmt.Println(names) - - //var password *crypto.Password - //np := rpc.NamespaceService{ Namespace: "root", Service: "Test" } - //err = client.Call("Query.Generate", &np, &password) - - //if err != nil { - // fmt.Println(err) - //} - - //fmt.Println(*password) - - //var success bool - //err = client.Call("Query.Delete", &np, &success) - - //if success == true { - // fmt.Println("Deleted Test") - //} - - //var password2 *crypto.Password - //err = client.Call("Query.Get", &np, &password2) - - //if err != nil { - // fmt.Println(err) - // return - //} - - //fmt.Println(*password2) - -// fmt.Printf(` -//Peer ID: %s -//Listen address: %s -//Topic: %s -//Data Folder: %s -// -//Ready! -// -//Commands: -// -//> list -> list items in the store -//> get -> get value for a key -//> put -> store value on a key -//> exit -> quit -// -// -//`, -// pid, storage.Listen, *topicNameFlag, data, -// ) -// -// if len(os.Args) > 1 && os.Args[1] == "daemon" { -// fmt.Println("Running in daemon mode") -// go func() { -// for { -// fmt.Printf("%s - %d connected peers\n", time.Now().Format(time.Stamp), len(storage.ConnectedPeers(h))) -// time.Sleep(10 * time.Second) -// } -// }() -// signalChan := make(chan os.Signal, 20) -// signal.Notify( -// signalChan, -// syscall.SIGINT, -// syscall.SIGTERM, -// syscall.SIGHUP, -// ) -// <-signalChan -// return -// } -// -// fmt.Printf("> ") -// scanner := bufio.NewScanner(os.Stdin) -// for scanner.Scan() { -// text := scanner.Text() -// fields := strings.Fields(text) -// if len(fields) == 0 { -// fmt.Printf("> ") -// continue -// } -// -// cmd := fields[0] -// -// switch cmd { -// case "exit", "quit": -// return -// case "debug": -// if len(fields) < 2 { -// fmt.Println("debug ") -// } -// st := fields[1] -// switch st { -// case "on": -// logging.SetLogLevel("globaldb", "debug") -// case "off": -// logging.SetLogLevel("globaldb", "error") -// case "peers": -// for _, p := range storage.ConnectedPeers(h) { -// addrs, err := peer.AddrInfoToP2pAddrs(p) -// if err != nil { -// logger.Warn(err) -// continue -// } -// for _, a := range addrs { -// fmt.Println(a) -// } -// } -// } -// case "list": -// if len(fields) < 2 { -// fmt.Printf("Available Namespaces:\n") -// for k := range storageHandler.Namespaces { -// fmt.Printf("%s\n", k) -// } -// continue -// } -// -// namespace := fields[1] -// -// fmt.Printf("Listing content of %s", namespace) -// -// val, ok := storageHandler.Namespaces[namespace] -// -// if !ok { -// fmt.Println("Namespace does not exist") -// continue -// } -// -// val.List() -// case "get": -// if len(fields) < 3 { -// fmt.Println("get ") -// fmt.Println("> ") -// continue -// } -// -// namespace := fields[1] -// -// val, ok := storageHandler.Namespaces[namespace] -// -// if !ok { -// fmt.Println("Namespace does not exist") -// continue -// } -// -// k := fields[2] -// v, err := val.Get(k) -// if err != nil { -// printErr(err) -// continue -// } -// -// fmt.Printf("[%s] -> %s\n", k, string(v)) -// case "generate": -// if len(fields) < 3 { -// fmt.Println("generate ") -// fmt.Println("> ") -// continue -// } -// -// namespace := fields[1] -// -// val, ok := storageHandler.Namespaces[namespace] -// -// if !ok { -// fmt.Println("Namespace does not exist") -// continue -// } -// -// service := fields[2] -// password := crypto.NewPassword() -// password.Service = service -// -// data, err := password.ToJson() -// if err != nil { -// printErr(err) -// continue -// } -// -// encryptedPassword, err := age.Encrypt(data, val.GetRecipients()) -// if err != nil { -// printErr(err) -// continue -// } -// -// //err = val.Put(password.Id.String(), string(encryptedPassword)) -// err = val.Put(password.Service, string(encryptedPassword)) -// if err != nil { -// printErr(err) -// continue -// } -// case "put": -// if len(fields) < 4 { -// fmt.Println("put ") -// fmt.Println("> ") -// continue -// } -// -// namespace := fields[1] -// -// val, ok := storageHandler.Namespaces[namespace] -// -// if !ok { -// fmt.Println("Namespace does not exist") -// continue -// } -// -// -// k := fields[2] -// v := strings.Join(fields[3:], " ") -// err := val.Put(k, v) -// if err != nil { -// printErr(err) -// continue -// } -// } -// fmt.Printf("> ") -// } -} - -func printErr(err error) { - fmt.Println("error:", err) - fmt.Println("> ") } diff --git a/rpc/rpc.go b/rpc/rpc.go index 670e8c7..6c67fa0 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -146,6 +146,21 @@ func (t *Query) Delete(np *NamespaceService, success *bool) error { return nil } +func (t *Query) AddNamespace(namespace *string, _ *int) error { + _, err := StorageHandler.AddNamespace(*namespace) + return err +} + +func (t *Query) DeleteNamespace(namespace *string, _ *int) error { + err := StorageHandler.DeleteNamespace(*namespace) + return err +} + +func (t *Query) ListNamespaces(_ *int, reply *[]string) error { + *reply = StorageHandler.ListNamespaces() + return nil +} + func (t *Query) GetAllNames(namespace *string, reply *[]string) error { fmt.Println("RPC Request: Query::LoadedTriggers") fmt.Printf("Listing content of %s", *namespace) diff --git a/storage/storage.go b/storage/storage.go index 2a92473..13eb443 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -364,8 +364,8 @@ func (n *Namespace) GetAllPasswords() ([]password.Password, error) { } func (n *Namespace) Close() { - n.Datastore.Close() n.CancelFunc() + n.Datastore.Close() } type StorageHandler struct { @@ -380,15 +380,32 @@ type StorageHandler struct { ConfigPath string } +func (s *StorageHandler) GetSelfPeer() Peer { + return Peer { + Id: s.Host.ID().String(), + Key: s.Key.Recipient().String(), + } +} + func (s *StorageHandler) UpdateConfig() { + fmt.Println("Updating Config...") s.recreateConfig() s.writeConfig(s.ConfigPath, s.Config) } func (s *StorageHandler) recreateConfig() { - for idx, namespaceConfig := range s.Config { - s.Config[idx].Peers = s.Namespaces[namespaceConfig.Name].TrustedPeers + var newCfg []NamespaceConfig + for key, val := range s.Namespaces { + newCfg = append(newCfg, NamespaceConfig{ + Name: key, + Id: val.ID, + Peers: val.TrustedPeers, + }) } + s.Config = newCfg + //for idx, namespaceConfig := range s.Config { + // s.Config[idx].Peers = s.Namespaces[namespaceConfig.Name].TrustedPeers + //} } func (s *StorageHandler) writeConfig(filename string, config []NamespaceConfig) error { @@ -454,7 +471,7 @@ func (s *StorageHandler) GetDefaultNamespace(Name string) *Namespace { func (s *StorageHandler) InitNamespaces() { NamespaceMap := make(map[string]*Namespace) for _, nsCfg := range s.Config { - ns1, err := CreateNamespace(nsCfg.Id, *s) + ns1, err := CreateNamespace(nsCfg.Id, s) if err != nil { logger.Fatal(err) @@ -492,7 +509,49 @@ func PrintDBContent(ctx context.Context, store *badger.Datastore) { } } -func CreateNamespace(ID string, storageHandler StorageHandler) (*Namespace, error) { +func (s *StorageHandler) ListNamespaces() []string { + var result []string + for k, _ := range s.Namespaces { + result = append(result, k) + } + + return result +} + +func (s *StorageHandler) DeleteNamespace(ID string) error { + ns, ok := s.Namespaces[ID] + + if !ok { + fmt.Print("DeleteNamespace that does not exists") + return nil + } + + delete(s.Namespaces, ID) + ns.Close() + s.UpdateConfig() + return nil +} + +func (s *StorageHandler) AddNamespace(Name string) (*Namespace, error) { + ns, ok := s.Namespaces[Name] + + if ok { + return ns, nil + } + + result, err := CreateNamespace(uuid.New().String(), s) + + if err != nil { + return nil, err + } + + result.TrustedPeers = append(result.TrustedPeers, s.GetSelfPeer()) + s.Namespaces[Name] = result + s.UpdateConfig() + return result, nil +} + +func CreateNamespace(ID string, storageHandler *StorageHandler) (*Namespace, error) { fmt.Printf("Creating Namespace %s\n", ID) err := storageHandler.PubSub.RegisterTopicValidator( ID, //== topicName @@ -537,7 +596,7 @@ func CreateNamespace(ID string, storageHandler StorageHandler) (*Namespace, erro val, ok := PeerMap[ID] if !ok { - logger.Fatal("namespace config does not contain any peers") + fmt.Println("namespace config does not contain any peers") } return &Namespace{ID: ID, Datastore: crdt, CancelFunc: psubCancel, ctx: storageHandler.Ctx, Key: storageHandler.Key, TrustedPeers: val}, nil