diff --git a/build.go b/build.go index de828d3ef91..faa014d7619 100644 --- a/build.go +++ b/build.go @@ -73,6 +73,10 @@ func main() { case "setup": setup() + case "build-cli": + clean() + build("grafana-cli", "./pkg/cmd/grafana-cli", []string{}) + case "build": clean() for _, binary := range binaries { diff --git a/pkg/api/user.go b/pkg/api/user.go index 715103aacbd..c3e354f5095 100644 --- a/pkg/api/user.go +++ b/pkg/api/user.go @@ -157,8 +157,9 @@ func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) return ApiError(401, "Invalid old password", nil) } - if len(cmd.NewPassword) < 4 { - return ApiError(400, "New password too short", nil) + password := m.Password(cmd.NewPassword) + if password.IsWeak() { + return ApiError(400, "New password is too short", nil) } cmd.UserId = c.UserId diff --git a/pkg/cmd/grafana-cli/commands/commands.go b/pkg/cmd/grafana-cli/commands/commands.go index b301924d956..8b2ecfcf7f5 100644 --- a/pkg/cmd/grafana-cli/commands/commands.go +++ b/pkg/cmd/grafana-cli/commands/commands.go @@ -1,14 +1,45 @@ package commands import ( + "flag" "os" "github.com/codegangsta/cli" "github.com/fatih/color" "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" + "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/setting" ) -func runCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { +var configFile = flag.String("config", "", "path to config file") +var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory") + +func runDbCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { + return func(context *cli.Context) { + + flag.Parse() + setting.NewConfigContext(&setting.CommandLineArgs{ + Config: *configFile, + HomePath: *homePath, + Args: flag.Args(), + }) + + sqlstore.NewEngine() + + cmd := &contextCommandLine{context} + if err := command(cmd); err != nil { + logger.Errorf("\n%s: ", color.RedString("Error")) + logger.Errorf("%s\n\n", err) + + cmd.ShowHelp() + os.Exit(1) + } else { + logger.Info("\n\n") + } + } +} + +func runPluginCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { return func(context *cli.Context) { cmd := &contextCommandLine{context} @@ -28,34 +59,42 @@ var pluginCommands = []cli.Command{ { Name: "install", Usage: "install ", - Action: runCommand(installCommand), + Action: runPluginCommand(installCommand), }, { Name: "list-remote", Usage: "list remote available plugins", - Action: runCommand(listremoteCommand), + Action: runPluginCommand(listremoteCommand), }, { Name: "list-versions", Usage: "list-versions ", - Action: runCommand(listversionsCommand), + Action: runPluginCommand(listversionsCommand), }, { Name: "update", Usage: "update ", Aliases: []string{"upgrade"}, - Action: runCommand(upgradeCommand), + Action: runPluginCommand(upgradeCommand), }, { Name: "update-all", Aliases: []string{"upgrade-all"}, Usage: "update all your installed plugins", - Action: runCommand(upgradeAllCommand), + Action: runPluginCommand(upgradeAllCommand), }, { Name: "ls", Usage: "list all installed plugins", - Action: runCommand(lsCommand), + Action: runPluginCommand(lsCommand), }, { Name: "uninstall", Aliases: []string{"remove"}, Usage: "uninstall ", - Action: runCommand(removeCommand), + Action: runPluginCommand(removeCommand), + }, +} + +var adminCommands = []cli.Command{ + { + Name: "reset-admin-password", + Usage: "reset-admin-password ", + Action: runDbCommand(resetPasswordCommand), }, } @@ -65,4 +104,9 @@ var Commands = []cli.Command{ Usage: "Manage plugins for grafana", Subcommands: pluginCommands, }, + { + Name: "admin", + Usage: "Grafana admin commands", + Subcommands: adminCommands, + }, } diff --git a/pkg/cmd/grafana-cli/commands/reset_password_command.go b/pkg/cmd/grafana-cli/commands/reset_password_command.go new file mode 100644 index 00000000000..af2b8b3f89a --- /dev/null +++ b/pkg/cmd/grafana-cli/commands/reset_password_command.go @@ -0,0 +1,44 @@ +package commands + +import ( + "fmt" + + "github.com/fatih/color" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/util" +) + +const AdminUserId = 1 + +func resetPasswordCommand(c CommandLine) error { + newPassword := c.Args().First() + + password := models.Password(newPassword) + if password.IsWeak() { + return fmt.Errorf("New password is too short") + } + + userQuery := models.GetUserByIdQuery{Id: AdminUserId} + + if err := bus.Dispatch(&userQuery); err != nil { + return fmt.Errorf("Could not read user from database. Error: %v", err) + } + + passwordHashed := util.EncodePassword(newPassword, userQuery.Result.Salt) + + cmd := models.ChangeUserPasswordCommand{ + UserId: AdminUserId, + NewPassword: passwordHashed, + } + + if err := bus.Dispatch(&cmd); err != nil { + return fmt.Errorf("Failed to update user password") + } + + logger.Infof("\n") + logger.Infof("Admin password changed successfully %s", color.GreenString("✔")) + + return nil +} diff --git a/pkg/models/user.go b/pkg/models/user.go index 8bfad7c2fb4..e14f4486ba3 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -10,6 +10,12 @@ var ( ErrUserNotFound = errors.New("User not found") ) +type Password string + +func (p Password) IsWeak() bool { + return len(p) <= 4 +} + type User struct { Id int64 Version int