github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/client/cli/user/user.go (about)

     1  // Package user handles the user cli command
     2  package user
     3  
     4  import (
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"syscall"
     9  
    10  	"github.com/tickoalcantara12/micro/v3/client/cli/token"
    11  	"github.com/tickoalcantara12/micro/v3/client/cli/util"
    12  	"github.com/tickoalcantara12/micro/v3/cmd"
    13  	pb "github.com/tickoalcantara12/micro/v3/proto/auth"
    14  	"github.com/tickoalcantara12/micro/v3/service/auth"
    15  	"github.com/tickoalcantara12/micro/v3/service/client"
    16  	"github.com/tickoalcantara12/micro/v3/service/context"
    17  	"github.com/tickoalcantara12/micro/v3/util/config"
    18  	"github.com/urfave/cli/v2"
    19  	"golang.org/x/crypto/ssh/terminal"
    20  )
    21  
    22  func init() {
    23  	cmd.Register(
    24  		&cli.Command{
    25  			Name:   "user",
    26  			Usage:  "Print the current logged in user",
    27  			Action: user,
    28  			Subcommands: []*cli.Command{
    29  				// config as a sub command,
    30  				{
    31  					Name:        "config",
    32  					Usage:       "{set, get, delete} [key] [value]",
    33  					Description: "Manage user related config like id, token, namespace, etc",
    34  					Action:      current,
    35  					Subcommands: config.Commands,
    36  				},
    37  				{
    38  					Name:   "token",
    39  					Usage:  "Get the current user token",
    40  					Action: getToken,
    41  				},
    42  				{
    43  					Name:   "namespace",
    44  					Usage:  "Get the current namespace",
    45  					Action: getNamespace,
    46  					Subcommands: []*cli.Command{
    47  						{
    48  							Name:   "set",
    49  							Usage:  "Set namespace in the current environment",
    50  							Action: setNamespace,
    51  						},
    52  					},
    53  				},
    54  				{
    55  					Name:  "set",
    56  					Usage: "Set various user based properties, eg. password",
    57  					Subcommands: []*cli.Command{
    58  						{
    59  							Name:   "password",
    60  							Usage:  "Set password",
    61  							Action: changePassword,
    62  							Flags: []cli.Flag{
    63  								&cli.StringFlag{
    64  									Name:  "email",
    65  									Usage: "Email to use for password change",
    66  								},
    67  								&cli.StringFlag{
    68  									Name:  "old-password",
    69  									Usage: "Existing password, the one that is used currently.",
    70  								},
    71  								&cli.StringFlag{
    72  									Name:  "new-password",
    73  									Usage: "New password you want to set.",
    74  								},
    75  							},
    76  						},
    77  					},
    78  				},
    79  			},
    80  		},
    81  	)
    82  }
    83  
    84  // get current user settings
    85  func changePassword(ctx *cli.Context) error {
    86  	email := ctx.String("email")
    87  	if len(email) == 0 {
    88  		token, err := token.Get(ctx)
    89  		if err != nil {
    90  			return err
    91  		}
    92  
    93  		// Inspect the token
    94  		acc, err := auth.Inspect(token.AccessToken)
    95  		if err != nil {
    96  			fmt.Println("You are not logged in")
    97  			return err
    98  		}
    99  		email = acc.ID
   100  	}
   101  
   102  	oldPassword := ctx.String("old-password")
   103  	newPassword := ctx.String("new-password")
   104  
   105  	if len(oldPassword) == 0 {
   106  		fmt.Print("Enter current password: ")
   107  		bytePw, _ := terminal.ReadPassword(int(syscall.Stdin))
   108  		pw := string(bytePw)
   109  		pw = strings.TrimSpace(pw)
   110  		fmt.Println()
   111  		oldPassword = pw
   112  	}
   113  
   114  	if len(newPassword) == 0 {
   115  		for {
   116  			fmt.Print("Enter a new password: ")
   117  			bytePw, _ := terminal.ReadPassword(int(syscall.Stdin))
   118  			pw := string(bytePw)
   119  			pw = strings.TrimSpace(pw)
   120  			fmt.Println()
   121  
   122  			fmt.Print("Verify your password: ")
   123  			bytePwVer, _ := terminal.ReadPassword(int(syscall.Stdin))
   124  			pwVer := string(bytePwVer)
   125  			pwVer = strings.TrimSpace(pwVer)
   126  			fmt.Println()
   127  
   128  			if pw != pwVer {
   129  				fmt.Println("Passwords do not match. Please try again.")
   130  				continue
   131  			}
   132  			newPassword = pw
   133  			break
   134  		}
   135  	}
   136  	ns, err := currNamespace(ctx)
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	accountService := pb.NewAccountsService("auth", client.DefaultClient)
   142  	_, err = accountService.ChangeSecret(context.DefaultContext, &pb.ChangeSecretRequest{
   143  		Id:        email,
   144  		OldSecret: oldPassword,
   145  		NewSecret: newPassword,
   146  		Options:   &pb.Options{Namespace: ns},
   147  	}, client.WithAuthToken())
   148  	return err
   149  }
   150  
   151  // get current user settings
   152  func current(ctx *cli.Context) error {
   153  	env, err := util.GetEnv(ctx)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	envName := env.Name
   158  	if len(envName) == 0 {
   159  		envName = "n/a"
   160  	}
   161  
   162  	ns, err := config.Get(config.Path("namespaces", env.Name, "current"))
   163  	if err != nil || len(ns) == 0 {
   164  		ns = "n/a"
   165  	}
   166  
   167  	token, err := token.Get(ctx)
   168  	if err != nil {
   169  		return err
   170  	}
   171  
   172  	gitcreds, err := config.Get(config.Path("git", "credentials"))
   173  	if err != nil {
   174  		return err
   175  	}
   176  	if len(gitcreds) > 0 {
   177  		gitcreds = "[hidden]"
   178  	} else {
   179  		gitcreds = "n/a"
   180  	}
   181  
   182  	id := "n/a"
   183  
   184  	// Inspect the token
   185  	acc, err := auth.Inspect(token.AccessToken)
   186  	if err == nil {
   187  		id = acc.Name
   188  		if len(id) == 0 {
   189  			id = acc.ID
   190  		}
   191  	}
   192  
   193  	baseURL, _ := config.Get(config.Path("git", env.Name, "baseurl"))
   194  	if len(baseURL) == 0 {
   195  		baseURL, _ = config.Get(config.Path("git", "baseurl"))
   196  	}
   197  	if len(baseURL) == 0 {
   198  		baseURL = "n/a"
   199  	}
   200  
   201  	fmt.Println("user:", id)
   202  	fmt.Println("namespace:", ns)
   203  	fmt.Println("environment:", envName)
   204  	fmt.Println("git.credentials:", gitcreds)
   205  	fmt.Println("git.baseurl:", baseURL)
   206  	return nil
   207  }
   208  
   209  // get token for current env
   210  func getToken(ctx *cli.Context) error {
   211  	token, err := token.Get(ctx)
   212  	if err != nil {
   213  		return err
   214  	}
   215  	fmt.Println(token.AccessToken)
   216  	return nil
   217  }
   218  
   219  // get namespace in current env
   220  func getNamespace(ctx *cli.Context) error {
   221  	namespace, err := currNamespace(ctx)
   222  	if err != nil {
   223  		return err
   224  	}
   225  	fmt.Println(namespace)
   226  	return nil
   227  }
   228  
   229  func currNamespace(ctx *cli.Context) (string, error) {
   230  	env, err := config.Get("env")
   231  	if err != nil {
   232  		return "", err
   233  	}
   234  	namespace, err := config.Get(config.Path("namespaces", env, "current"))
   235  	if err != nil {
   236  		return "", err
   237  	}
   238  	return namespace, nil
   239  }
   240  
   241  // set namespace in current env
   242  func setNamespace(ctx *cli.Context) error {
   243  	if len(ctx.Args().First()) == 0 {
   244  		return errors.New("No namespace specified")
   245  	}
   246  	env, err := config.Get("env")
   247  	if err != nil {
   248  		return err
   249  	}
   250  	return config.Set(config.Path("namespaces", env, "current"), ctx.Args().First())
   251  }
   252  
   253  // user returns info about the logged in user
   254  func user(ctx *cli.Context) error {
   255  
   256  	notLoggedIn := errors.New("You are not logged in")
   257  	// Get the token from micro config
   258  	token, err := token.Get(ctx)
   259  	if err != nil {
   260  		return notLoggedIn
   261  	}
   262  
   263  	// Inspect the token
   264  	acc, err := auth.Inspect(token.AccessToken)
   265  	if err != nil {
   266  		return err
   267  	}
   268  	// backward compatibility
   269  	user := acc.Name
   270  	if len(user) == 0 {
   271  		user = acc.ID
   272  	}
   273  	fmt.Println(user)
   274  	return nil
   275  }