mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
79 lines
2.2 KiB
Go
79 lines
2.2 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
user_model "github.com/hanzoai/git/models/user"
|
|
"github.com/hanzoai/git/modules/auth/password"
|
|
"github.com/hanzoai/git/modules/optional"
|
|
"github.com/hanzoai/git/modules/setting"
|
|
user_service "github.com/hanzoai/git/services/user"
|
|
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
func microcmdUserChangePassword() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "change-password",
|
|
Usage: "Change a user's password",
|
|
Action: runChangePassword,
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "username",
|
|
Aliases: []string{"u"},
|
|
Usage: "The user to change password for",
|
|
Required: true,
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "password",
|
|
Aliases: []string{"p"},
|
|
Usage: "New password to set for user",
|
|
Required: true,
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "must-change-password",
|
|
Usage: "User must change password (can be disabled by --must-change-password=false)",
|
|
Value: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func runChangePassword(ctx context.Context, c *cli.Command) error {
|
|
if !setting.IsInTesting {
|
|
if err := initDB(ctx); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
user, err := user_model.GetUserByName(ctx, c.String("username"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
opts := &user_service.UpdateAuthOptions{
|
|
Password: optional.Some(c.String("password")),
|
|
MustChangePassword: optional.Some(c.Bool("must-change-password")),
|
|
}
|
|
if err := user_service.UpdateAuth(ctx, user, opts); err != nil {
|
|
switch {
|
|
case errors.Is(err, password.ErrMinLength):
|
|
return fmt.Errorf("password is not long enough, needs to be at least %d characters", setting.MinPasswordLength)
|
|
case errors.Is(err, password.ErrComplexity):
|
|
return errors.New("password does not meet complexity requirements")
|
|
case errors.Is(err, password.ErrIsPwned):
|
|
return errors.New("the password is in a list of stolen passwords previously exposed in public data breaches, please try again with a different password, to see more details: https://haveibeenpwned.com/Passwords")
|
|
default:
|
|
return err
|
|
}
|
|
}
|
|
|
|
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
|
|
return nil
|
|
}
|