github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/terminal/command_sudo.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2024, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package terminal
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"sync"
    25  
    26  	"github.com/spf13/cobra"
    27  
    28  	"github.com/e154/smart-home/common/events"
    29  )
    30  
    31  type CommandSudo struct {
    32  	Out *bytes.Buffer
    33  	*sync.Mutex
    34  	cmd      *cobra.Command
    35  	password *string
    36  }
    37  
    38  func NewCommandSudo() *CommandSudo {
    39  	buf := new(bytes.Buffer)
    40  
    41  	command := &CommandSudo{
    42  		Out:      buf,
    43  		password: new(string),
    44  		Mutex:    &sync.Mutex{},
    45  	}
    46  
    47  	cmdMode := &cobra.Command{
    48  		Use:               "sudo",
    49  		DisableAutoGenTag: true,
    50  		Short:             "get superuser access rights",
    51  		Run: func(cmd *cobra.Command, args []string) {
    52  			var password = cmd.Flag("password").Value.String()
    53  
    54  			//log.Debugf("password: %s", password)
    55  
    56  			ctx := cmd.Context()
    57  			command, ok := ctx.Value("Command").(events.CommandTerminal)
    58  			if !ok {
    59  				cmd.OutOrStdout().Write([]byte("request rejected"))
    60  				return
    61  			}
    62  
    63  			options, ok := ctx.Value("Options").(CommandOptions)
    64  			if !ok {
    65  				cmd.OutOrStdout().Write([]byte("request rejected"))
    66  				return
    67  			}
    68  
    69  			if options.config.RootSecret == "" || options.config.RootSecret != password {
    70  				cmd.OutOrStdout().Write([]byte("request rejected"))
    71  				return
    72  			}
    73  
    74  			accessToken, err := options.jwtManager.Generate(command.User, true)
    75  			if err != nil {
    76  				cmd.OutOrStdout().Write([]byte("request rejected"))
    77  				log.Error(err.Error())
    78  				return
    79  			}
    80  
    81  			cmd.OutOrStdout().Write([]byte("request processed successfully"))
    82  			options.eventBus.Publish("system/dashboard", events.EventDirectMessage{
    83  				UserID:    command.User.Id,
    84  				SessionID: command.SessionID,
    85  				Query:     "update_access_token",
    86  				Message: UpdateAccessTokenMessage{
    87  					AccessToken: accessToken,
    88  				},
    89  			})
    90  		},
    91  	}
    92  
    93  	cmdMode.SetOut(command.Out)
    94  	cmdMode.SetErr(command.Out)
    95  	command.cmd = cmdMode
    96  
    97  	return command
    98  }
    99  
   100  func (c *CommandSudo) Execute(ctx context.Context, args ...string) (out string, err error) {
   101  	c.Lock()
   102  	defer c.Unlock()
   103  	c.Out.Reset()
   104  	c.cmd.ResetFlags()
   105  	c.cmd.Flags().StringVarP(c.password, "password", "p", "", "see the root_secret in configuration file or ROOT_SECRET in your environment")
   106  	c.cmd.SetArgs(args)
   107  	err = c.cmd.ExecuteContext(ctx)
   108  	out = c.Out.String()
   109  	return
   110  }
   111  
   112  func (c *CommandSudo) Help(ctx context.Context) (out string, err error) {
   113  	err = c.cmd.Help()
   114  	out = c.Out.String()
   115  	return
   116  }