This commit is contained in:
Marcel van der Boom 2025-06-05 00:48:50 +00:00 committed by GitHub
commit 78ea108a11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 99 additions and 0 deletions

45
app.go
View file

@ -832,6 +832,51 @@ func DoDeleteAccount(apper Apper, username string) error {
return nil return nil
} }
func DoSilenceAccount(apper Apper, username string) error {
// Connect to the database
apper.LoadConfig()
connectToDatabase(apper.App())
defer shutdown(apper.App())
// check user exists
u, err := apper.App().db.GetUserForAuth(username)
if err != nil {
log.Error("%s", err)
os.Exit(1)
}
userID := u.ID
// do not silence the admin account
// TODO: check for other admins and skip?
if u.IsAdmin() {
log.Error("Can not silence admin account")
os.Exit(1)
}
// confirm deletion, w/ w/out posts
prompt := promptui.Prompt{
Templates: &promptui.PromptTemplates{
Success: "{{ . | bold | faint }}: ",
},
Label: fmt.Sprintf("Really silence user : %s", username),
IsConfirm: true,
}
_, err = prompt.Run()
if err != nil {
log.Info("Aborted...")
os.Exit(0)
}
log.Info("Silencing...")
err = apper.App().db.SilenceAccount(userID)
if err != nil {
log.Error("%s", err)
os.Exit(1)
}
log.Info("Success.")
return nil
}
func connectToDatabase(app *App) { func connectToDatabase(app *App) {
log.Info("Connecting to %s database...", app.cfg.Database.Type) log.Info("Connecting to %s database...", app.cfg.Database.Type)

View file

@ -84,6 +84,11 @@ func main() {
Usage: "Delete a user with the given username", Usage: "Delete a user with the given username",
Hidden: true, Hidden: true,
}, },
&cli.StringFlag{
Name: "silence-user",
Usage: "Silence a user with the given username",
Hidden: true,
},
&cli.StringFlag{ &cli.StringFlag{
Name: "reset-pass", Name: "reset-pass",
Usage: "Reset the given user's password", Usage: "Reset the given user's password",
@ -151,6 +156,8 @@ func legacyActions(c *cli.Context) error {
return writefreely.CreateUser(app, username, password, false) return writefreely.CreateUser(app, username, password, false)
case c.IsSet("delete-user"): case c.IsSet("delete-user"):
return writefreely.DoDeleteAccount(app, c.String("delete-user")) return writefreely.DoDeleteAccount(app, c.String("delete-user"))
case c.IsSet("silence-user"):
return writefreely.DoSilenceAccount(app, c.String("silence-user"))
case c.IsSet("reset-pass"): case c.IsSet("reset-pass"):
return writefreely.ResetPassword(app, c.String("reset-pass")) return writefreely.ResetPassword(app, c.String("reset-pass"))
} }

View file

@ -24,6 +24,7 @@ var (
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
&cmdAddUser, &cmdAddUser,
&cmdDelUser, &cmdDelUser,
&cmdSilenceUser,
&cmdResetPass, &cmdResetPass,
// TODO: possibly add a user list command // TODO: possibly add a user list command
}, },
@ -50,6 +51,13 @@ var (
Action: delUserAction, Action: delUserAction,
} }
cmdSilenceUser cli.Command = cli.Command{
Name: "silence",
Usage: "Silence user",
Aliases: []string{"sil", "s"},
Action: silenceUserAction,
}
cmdResetPass cli.Command = cli.Command{ cmdResetPass cli.Command = cli.Command{
Name: "reset-pass", Name: "reset-pass",
Usage: "Reset user's password", Usage: "Reset user's password",
@ -84,6 +92,17 @@ func delUserAction(c *cli.Context) error {
return writefreely.DoDeleteAccount(app, username) return writefreely.DoDeleteAccount(app, username)
} }
func silenceUserAction(c *cli.Context) error {
username := ""
if c.NArg() > 0 {
username = c.Args().Get(0)
} else {
return fmt.Errorf("No user passed. Example: writefreely user silence [USER]")
}
app := writefreely.NewApp(c.String("c"))
return writefreely.DoSilenceAccount(app, username)
}
func resetPassAction(c *cli.Context) error { func resetPassAction(c *cli.Context) error {
username := "" username := ""
if c.NArg() > 0 { if c.NArg() > 0 {

View file

@ -74,6 +74,7 @@ type writestore interface {
GetTemporaryAccessToken(userID int64, validSecs int) (string, error) GetTemporaryAccessToken(userID int64, validSecs int) (string, error)
GetTemporaryOneTimeAccessToken(userID int64, validSecs int, oneTime bool) (string, error) GetTemporaryOneTimeAccessToken(userID int64, validSecs int, oneTime bool) (string, error)
DeleteAccount(userID int64) error DeleteAccount(userID int64) error
SilenceAccount(userID int64) error
ChangeSettings(app *App, u *User, s *userSettings) error ChangeSettings(app *App, u *User, s *userSettings) error
ChangePassphrase(userID int64, sudo bool, curPass string, hashedPass []byte) error ChangePassphrase(userID int64, sudo bool, curPass string, hashedPass []byte) error
@ -2674,6 +2675,33 @@ func (db *datastore) DeleteAccount(userID int64) error {
return nil return nil
} }
func (db *datastore) SilenceAccount(userID int64) error {
// Start transaction
t, err := db.Begin()
if err != nil {
log.Error("Unable to begin: %v", err)
return err
}
// Update user state
_, err = t.Exec("UPDATE users SET status=1 WHERE id=?", userID)
if err != nil {
t.Rollback()
return fmt.Errorf("Unable to update user status: %s", err)
}
// Commit all changes to the database
err = t.Commit()
if err != nil {
t.Rollback()
log.Error("Unable to commit: %v", err)
return err
}
// TODO: federate delete actor here too?
return nil
}
func (db *datastore) GetAPActorKeys(collectionID int64) ([]byte, []byte) { func (db *datastore) GetAPActorKeys(collectionID int64) ([]byte, []byte) {
var pub, priv []byte var pub, priv []byte
err := db.QueryRow("SELECT public_key, private_key FROM collectionkeys WHERE collection_id = ?", collectionID).Scan(&pub, &priv) err := db.QueryRow("SELECT public_key, private_key FROM collectionkeys WHERE collection_id = ?", collectionID).Scan(&pub, &priv)