diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index 3a54b13ac..8a2d7f006 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -58,6 +58,28 @@ var _disable2faCmd = &cobra.Command{ }, } +var _deleteUser = &cobra.Command{ + Use: "delete-user", + Short: "Delete a user", + RunE: func(cmd *cobra.Command, args []string) error { + recoverWithLog() + var flags = &model.AdminActionForUser{} + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Name == "admin-user" { + flags.AdminEmail = f.Value.String() + } + if f.Name == "user" { + flags.UserEmail = f.Value.String() + } + }) + if flags.UserEmail == "" { + return fmt.Errorf("user email is required") + } + return ctrl.DeleteUser(context.Background(), *flags) + + }, +} + var _listUsers = &cobra.Command{ Use: "list-users", Short: "List all users", @@ -108,9 +130,11 @@ func init() { _listUsers.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") _disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") _disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)") + _deleteUser.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") + _deleteUser.Flags().StringP("user", "u", "", "The email of the user to delete. (required)") _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user.") _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") // add a flag with no value --no-limit _updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years") - _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage, _listUsers) + _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage, _listUsers, _deleteUser) } diff --git a/cli/internal/api/admin.go b/cli/internal/api/admin.go index c2b948111..9e0bcb90a 100644 --- a/cli/internal/api/admin.go +++ b/cli/internal/api/admin.go @@ -47,6 +47,24 @@ func (c *Client) ListUsers(ctx context.Context) ([]models.User, error) { return res.Users, nil } +func (c *Client) DeleteUser(ctx context.Context, email string) error { + + r, err := c.restClient.R(). + SetContext(ctx). + SetQueryParam("email", email). + Delete("/admin/user/delete") + if err != nil { + return err + } + if r.IsError() { + return &ApiError{ + StatusCode: r.StatusCode(), + Message: r.String(), + } + } + return nil +} + func (c *Client) Disable2Fa(ctx context.Context, userID int64) error { var res interface{} diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go index a7a060f66..0105cdc19 100644 --- a/cli/pkg/admin_actions.go +++ b/cli/pkg/admin_actions.go @@ -44,6 +44,23 @@ func (c *ClICtrl) ListUsers(ctx context.Context, params model.AdminActionForUser return nil } +func (c *ClICtrl) DeleteUser(ctx context.Context, params model.AdminActionForUser) error { + accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) + if err != nil { + return err + } + err = c.Client.DeleteUser(accountCtx, params.UserEmail) + if err != nil { + if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") { + fmt.Printf("Error: old admin token, please re-authenticate using `ente account add` \n") + return nil + } + return err + } + fmt.Println("Successfully deleted user") + return nil +} + func (c *ClICtrl) Disable2FA(ctx context.Context, params model.AdminActionForUser) error { accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) if err != nil {