mirror of
				https://github.com/photoprism/photoprism.git
				synced 2025-10-31 20:22:55 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			130 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package commands
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"os/signal"
 | |
| 	"strings"
 | |
| 	"syscall"
 | |
| 
 | |
| 	"github.com/photoprism/photoprism/internal/config"
 | |
| 	"github.com/photoprism/photoprism/internal/entity"
 | |
| 	"github.com/photoprism/photoprism/pkg/txt"
 | |
| 	"github.com/urfave/cli"
 | |
| )
 | |
| 
 | |
| // PasswdCommand updates a password.
 | |
| var PasswdCommand = cli.Command{
 | |
| 	Name:   "passwd",
 | |
| 	Usage:  "Changes the admin password",
 | |
| 	Action: passwdAction,
 | |
| }
 | |
| 
 | |
| // passwdAction updates a password.
 | |
| func passwdAction(ctx *cli.Context) error {
 | |
| 	conf := config.NewConfig(ctx)
 | |
| 
 | |
| 	_, cancel := context.WithCancel(context.Background())
 | |
| 	defer cancel()
 | |
| 
 | |
| 	if err := conf.Init(); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	conf.InitDb()
 | |
| 
 | |
| 	user := entity.Admin
 | |
| 
 | |
| 	log.Infof("please enter a new password for %s (at least 6 characters)\n", txt.Quote(user.UserName))
 | |
| 
 | |
| 	newPassword := getPassword("New Password: ")
 | |
| 
 | |
| 	if len(newPassword) < 6 {
 | |
| 		return errors.New("new password is too short, please try again")
 | |
| 	}
 | |
| 
 | |
| 	retypePassword := getPassword("Retype Password: ")
 | |
| 
 | |
| 	if newPassword != retypePassword {
 | |
| 		return errors.New("passwords did not match, please try again")
 | |
| 	}
 | |
| 
 | |
| 	if err := user.SetPassword(newPassword); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	log.Infof("changed password for %s\n", txt.Quote(user.UserName))
 | |
| 
 | |
| 	conf.Shutdown()
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // License: MIT Open Source
 | |
| // Copyright (c) Joe Linoff 2016
 | |
| // Go code to prompt for password using only standard packages by utilizing syscall.ForkExec() and syscall.Wait4().
 | |
| // Correctly resets terminal echo after ^C interrupts.
 | |
| //
 | |
| // techEcho() - turns terminal echo on or off.
 | |
| func termEcho(on bool) {
 | |
| 	// Common settings and variables for both stty calls.
 | |
| 	attrs := syscall.ProcAttr{
 | |
| 		Dir:   "",
 | |
| 		Env:   []string{},
 | |
| 		Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
 | |
| 		Sys:   nil}
 | |
| 	var ws syscall.WaitStatus
 | |
| 	cmd := "echo"
 | |
| 	if on == false {
 | |
| 		cmd = "-echo"
 | |
| 	}
 | |
| 
 | |
| 	// Enable/disable echoing.
 | |
| 	pid, err := syscall.ForkExec(
 | |
| 		"/bin/stty",
 | |
| 		[]string{"stty", cmd},
 | |
| 		&attrs)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	// Wait for the stty process to complete.
 | |
| 	_, err = syscall.Wait4(pid, &ws, 0, nil)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // getPassword - Prompt for password.
 | |
| func getPassword(prompt string) string {
 | |
| 	fmt.Print(prompt)
 | |
| 
 | |
| 	// Catch a ^C interrupt.
 | |
| 	// Make sure that we reset term echo before exiting.
 | |
| 	signalChannel := make(chan os.Signal, 1)
 | |
| 	signal.Notify(signalChannel, os.Interrupt)
 | |
| 	go func() {
 | |
| 		for _ = range signalChannel {
 | |
| 			fmt.Println("")
 | |
| 			termEcho(true)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	// Echo is disabled, now grab the data.
 | |
| 	termEcho(false) // disable terminal echo
 | |
| 	reader := bufio.NewReader(os.Stdin)
 | |
| 	text, err := reader.ReadString('\n')
 | |
| 	termEcho(true) // always re-enable terminal echo
 | |
| 	fmt.Println("")
 | |
| 	if err != nil {
 | |
| 		// The terminal has been reset, go ahead and exit.
 | |
| 		fmt.Println("ERROR:", err.Error())
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| 	return strings.TrimSpace(text)
 | |
| }
 | 
