From dc3f68584abef950078a10ce8022ce7f791a3d19 Mon Sep 17 00:00:00 2001 From: Patrick Pfeiffer Date: Mon, 11 Mar 2024 17:13:39 +0100 Subject: [PATCH] (NOBIDS) misc: add command: disable-user-per-email --- cmd/misc/main.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/cmd/misc/main.go b/cmd/misc/main.go index a98962860a..2da6a27260 100644 --- a/cmd/misc/main.go +++ b/cmd/misc/main.go @@ -60,7 +60,9 @@ var opts = struct { Family string Key string ValidatorNameRanges string + Email string DryRun bool + Yes bool }{} func main() { @@ -86,6 +88,8 @@ func main() { flag.StringVar(&opts.ValidatorNameRanges, "validator-name-ranges", "https://config.dencun-devnet-8.ethpandaops.io/api/v1/nodes/validator-ranges", "url to or json of validator-ranges (format must be: {'ranges':{'X-Y':'name'}})") flag.StringVar(&opts.Addresses, "addresses", "", "Comma separated list of addresses that should be processed by the command") flag.StringVar(&opts.Columns, "columns", "", "Comma separated list of columns that should be affected by the command") + flag.StringVar(&opts.Email, "email", "", "Email of the user") + flag.BoolVar(&opts.Yes, "yes", false, "Answer yes to all questions") dryRun := flag.String("dry-run", "true", "if 'false' it deletes all rows starting with the key, per default it only logs the rows that would be deleted, but does not really delete them") versionFlag := flag.Bool("version", false, "Show version and exit") @@ -394,6 +398,8 @@ func main() { err = fixEnsAddresses(erigonClient) case "update-ratelimits": ratelimit.DBUpdater() + case "disable-user-per-email": + err = disableUserPerEmail() default: utils.LogFatal(nil, fmt.Sprintf("unknown command %s", opts.Command), 0) } @@ -405,6 +411,58 @@ func main() { } } +func disableUserPerEmail() error { + if opts.Email == "" { + return errors.New("no email specified") + } + user := struct { + ID uint64 `db:"id"` + Email string `db:"email"` + }{} + err := db.FrontendWriterDB.Select(&user, `select id, email from users where email = $1`, opts.Email) + if err != nil { + return err + } + + if !askForConfirmation(fmt.Sprintf(`Do you want to disable the user with email: %v (id: %v)? + +- the user will get logged out +- the password will change +- the apikey will change +- password-reset will be disabled +`, user.Email, user.ID)) { + logrus.Warnf("aborted") + return nil + } + + _, err = db.FrontendWriterDB.Exec(`update users set password = $3, apikey = $4, password_reset_not_allowed = true where id = $1 and email = $2`, user.ID, user.Email, utils.RandomString(128), utils.RandomString(32)) + if err != nil { + return err + } + + ctx := context.Background() + + // invalidate all sessions for this user + err = utils.SessionStore.SCS.Iterate(ctx, func(ctx context.Context) error { + sessionUserID, ok := utils.SessionStore.SCS.Get(ctx, "user_id").(uint64) + if !ok { + return nil + } + + if user.ID == sessionUserID { + return utils.SessionStore.SCS.Destroy(ctx) + } + + return nil + }) + + if err != nil { + return err + } + + return nil +} + func fixEns(erigonClient *rpc.ErigonClient) error { logrus.Infof("command: fix-ens") addrs := []struct { @@ -1936,3 +1994,24 @@ func reExportSyncCommittee(rpcClient rpc.Client, p uint64, dryRun bool) error { return tx.Commit() } } + +func askForConfirmation(q string) bool { + if opts.Yes { + return true + } + var s string + + fmt.Printf("%s (y/N): ", q) + _, err := fmt.Scan(&s) + if err != nil { + panic(err) + } + + s = strings.TrimSpace(s) + s = strings.ToLower(s) + + if s == "y" || s == "yes" { + return true + } + return false +}