mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 06:02:26 -05:00 
			
		
		
		
	Admin cli (#29)
Now you can use the CLI tool to: * Create a new account with the given username, email address and password (which will be hashed of course). * Confirm the account's so that it can log in and post. * Promote the account to admin. * Demote the account from admin. * Disable the account. * Suspend the account.
This commit is contained in:
		
					parent
					
						
							
								0df2e18cc0
							
						
					
				
			
			
				commit
				
					
						43c3a47773
					
				
			
		
					 4 changed files with 364 additions and 2 deletions
				
			
		|  | @ -24,6 +24,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/action" | 	"github.com/superseriousbusiness/gotosocial/internal/action" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/clitools/admin/account" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gotosocial" | 	"github.com/superseriousbusiness/gotosocial/internal/gotosocial" | ||||||
|  | @ -263,6 +264,104 @@ func main() { | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
|  | 			{ | ||||||
|  | 				Name:  "admin", | ||||||
|  | 				Usage: "gotosocial admin-related tasks", | ||||||
|  | 				Subcommands: []*cli.Command{ | ||||||
|  | 					{ | ||||||
|  | 						Name:  "account", | ||||||
|  | 						Usage: "admin commands related to accounts", | ||||||
|  | 						Subcommands: []*cli.Command{ | ||||||
|  | 							{ | ||||||
|  | 								Name:  "create", | ||||||
|  | 								Usage: "create a new account", | ||||||
|  | 								Flags: []cli.Flag{ | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.UsernameFlag, | ||||||
|  | 										Usage:   config.UsernameUsage, | ||||||
|  | 									}, | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.EmailFlag, | ||||||
|  | 										Usage:   config.EmailUsage, | ||||||
|  | 									}, | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.PasswordFlag, | ||||||
|  | 										Usage:   config.PasswordUsage, | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
|  | 								Action: func(c *cli.Context) error { | ||||||
|  | 									return runAction(c, account.Create) | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							{ | ||||||
|  | 								Name:  "confirm", | ||||||
|  | 								Usage: "confirm an existing account manually, thereby skipping email confirmation", | ||||||
|  | 								Flags: []cli.Flag{ | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.UsernameFlag, | ||||||
|  | 										Usage:   config.UsernameUsage, | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
|  | 								Action: func(c *cli.Context) error { | ||||||
|  | 									return runAction(c, account.Confirm) | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							{ | ||||||
|  | 								Name:  "promote", | ||||||
|  | 								Usage: "promote an account to admin", | ||||||
|  | 								Flags: []cli.Flag{ | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.UsernameFlag, | ||||||
|  | 										Usage:   config.UsernameUsage, | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
|  | 								Action: func(c *cli.Context) error { | ||||||
|  | 									return runAction(c, account.Promote) | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							{ | ||||||
|  | 								Name:  "demote", | ||||||
|  | 								Usage: "demote an account from admin to normal user", | ||||||
|  | 								Flags: []cli.Flag{ | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.UsernameFlag, | ||||||
|  | 										Usage:   config.UsernameUsage, | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
|  | 								Action: func(c *cli.Context) error { | ||||||
|  | 									return runAction(c, account.Demote) | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							{ | ||||||
|  | 								Name:  "disable", | ||||||
|  | 								Usage: "prevent an account from signing in or posting etc, but don't delete anything", | ||||||
|  | 								Flags: []cli.Flag{ | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.UsernameFlag, | ||||||
|  | 										Usage:   config.UsernameUsage, | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
|  | 								Action: func(c *cli.Context) error { | ||||||
|  | 									return runAction(c, account.Disable) | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							{ | ||||||
|  | 								Name:  "suspend", | ||||||
|  | 								Usage: "completely remove an account and all of its posts, media, etc", | ||||||
|  | 								Flags: []cli.Flag{ | ||||||
|  | 									&cli.StringFlag{ | ||||||
|  | 										Name:    config.UsernameFlag, | ||||||
|  | 										Usage:   config.UsernameUsage, | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
|  | 								Action: func(c *cli.Context) error { | ||||||
|  | 									return runAction(c, account.Suspend) | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
| 			{ | 			{ | ||||||
| 				Name:  "db", | 				Name:  "db", | ||||||
| 				Usage: "database-related tasks and utils", | 				Usage: "database-related tasks and utils", | ||||||
|  | @ -308,7 +407,9 @@ func runAction(c *cli.Context, a action.GTSAction) error { | ||||||
| 		return fmt.Errorf("error creating config: %s", err) | 		return fmt.Errorf("error creating config: %s", err) | ||||||
| 	} | 	} | ||||||
| 	// ... and the flags set on the *cli.Context by urfave | 	// ... and the flags set on the *cli.Context by urfave | ||||||
| 	conf.ParseCLIFlags(c) | 	if err := conf.ParseCLIFlags(c); err != nil { | ||||||
|  | 		return fmt.Errorf("error parsing config: %s", err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// create a logger with the log level, formatting, and output splitter already set | 	// create a logger with the log level, formatting, and output splitter already set | ||||||
| 	log, err := log.New(conf.LogLevel) | 	log, err := log.New(conf.LogLevel) | ||||||
|  |  | ||||||
							
								
								
									
										209
									
								
								internal/clitools/admin/account/account.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								internal/clitools/admin/account/account.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,209 @@ | ||||||
|  | /* | ||||||
|  |    GoToSocial | ||||||
|  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | ||||||
|  | 
 | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU Affero General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  |    You should have received a copy of the GNU Affero General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package account | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/action" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/db/pg" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Create creates a new account in the database using the provided flags. | ||||||
|  | var Create action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { | ||||||
|  | 	dbConn, err := pg.NewPostgresService(ctx, c, log) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error creating dbservice: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	username, ok := c.AccountCLIFlags[config.UsernameFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no username set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateUsername(username); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	email, ok := c.AccountCLIFlags[config.EmailFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no email set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateEmail(email); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	password, ok := c.AccountCLIFlags[config.PasswordFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no password set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateNewPassword(password); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_, err = dbConn.NewSignup(username, "", false, email, password, nil, "", "") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return dbConn.Stop(ctx) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Confirm sets a user to Approved, sets Email to the current UnconfirmedEmail value, and sets ConfirmedAt to now. | ||||||
|  | var Confirm action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { | ||||||
|  | 	dbConn, err := pg.NewPostgresService(ctx, c, log) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error creating dbservice: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	username, ok := c.AccountCLIFlags[config.UsernameFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no username set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateUsername(username); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	a := >smodel.Account{} | ||||||
|  | 	if err := dbConn.GetLocalAccountByUsername(username, a); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u := >smodel.User{} | ||||||
|  | 	if err := dbConn.GetWhere([]db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u.Approved = true | ||||||
|  | 	u.Email = u.UnconfirmedEmail | ||||||
|  | 	u.ConfirmedAt = time.Now() | ||||||
|  | 	if err := dbConn.UpdateByID(u.ID, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return dbConn.Stop(ctx) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Promote sets a user to admin. | ||||||
|  | var Promote action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { | ||||||
|  | 	dbConn, err := pg.NewPostgresService(ctx, c, log) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error creating dbservice: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	username, ok := c.AccountCLIFlags[config.UsernameFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no username set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateUsername(username); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	a := >smodel.Account{} | ||||||
|  | 	if err := dbConn.GetLocalAccountByUsername(username, a); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u := >smodel.User{} | ||||||
|  | 	if err := dbConn.GetWhere([]db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	u.Admin = true | ||||||
|  | 	if err := dbConn.UpdateByID(u.ID, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return dbConn.Stop(ctx) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Demote sets admin on a user to false. | ||||||
|  | var Demote action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { | ||||||
|  | 	dbConn, err := pg.NewPostgresService(ctx, c, log) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error creating dbservice: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	username, ok := c.AccountCLIFlags[config.UsernameFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no username set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateUsername(username); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	a := >smodel.Account{} | ||||||
|  | 	if err := dbConn.GetLocalAccountByUsername(username, a); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u := >smodel.User{} | ||||||
|  | 	if err := dbConn.GetWhere([]db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	u.Admin = false | ||||||
|  | 	if err := dbConn.UpdateByID(u.ID, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return dbConn.Stop(ctx) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Disable sets Disabled to true on a user. | ||||||
|  | var Disable action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { | ||||||
|  | 	dbConn, err := pg.NewPostgresService(ctx, c, log) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error creating dbservice: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	username, ok := c.AccountCLIFlags[config.UsernameFlag] | ||||||
|  | 	if !ok { | ||||||
|  | 		return errors.New("no username set") | ||||||
|  | 	} | ||||||
|  | 	if err := util.ValidateUsername(username); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	a := >smodel.Account{} | ||||||
|  | 	if err := dbConn.GetLocalAccountByUsername(username, a); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u := >smodel.User{} | ||||||
|  | 	if err := dbConn.GetWhere([]db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	u.Disabled = true | ||||||
|  | 	if err := dbConn.UpdateByID(u.ID, u); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return dbConn.Stop(ctx) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var Suspend action.GTSAction = func(ctx context.Context, c *config.Config, log *logrus.Logger) error { | ||||||
|  | 	// TODO | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | @ -19,14 +19,31 @@ | ||||||
| package config | package config | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 
 | 
 | ||||||
| 	"gopkg.in/yaml.v2" | 	"gopkg.in/yaml.v2" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | const ( | ||||||
|  | 	UsernameFlag  = "username" | ||||||
|  | 	UsernameUsage = "the username to create/delete/etc" | ||||||
|  | 
 | ||||||
|  | 	EmailFlag  = "email" | ||||||
|  | 	EmailUsage = "the email address of this account" | ||||||
|  | 
 | ||||||
|  | 	PasswordFlag  = "password" | ||||||
|  | 	PasswordUsage = "the password to set for this account" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| // Config pulls together all the configuration needed to run gotosocial | // Config pulls together all the configuration needed to run gotosocial | ||||||
| type Config struct { | type Config struct { | ||||||
|  | 	/* | ||||||
|  | 		Parseable from .yaml configuration file. | ||||||
|  | 		For long-running commands (server start etc). | ||||||
|  | 	*/ | ||||||
|  | 
 | ||||||
| 	LogLevel          string             `yaml:"logLevel"` | 	LogLevel          string             `yaml:"logLevel"` | ||||||
| 	ApplicationName   string             `yaml:"applicationName"` | 	ApplicationName   string             `yaml:"applicationName"` | ||||||
| 	Host              string             `yaml:"host"` | 	Host              string             `yaml:"host"` | ||||||
|  | @ -38,6 +55,12 @@ type Config struct { | ||||||
| 	StorageConfig     *StorageConfig     `yaml:"storage"` | 	StorageConfig     *StorageConfig     `yaml:"storage"` | ||||||
| 	StatusesConfig    *StatusesConfig    `yaml:"statuses"` | 	StatusesConfig    *StatusesConfig    `yaml:"statuses"` | ||||||
| 	LetsEncryptConfig *LetsEncryptConfig `yaml:"letsEncrypt"` | 	LetsEncryptConfig *LetsEncryptConfig `yaml:"letsEncrypt"` | ||||||
|  | 
 | ||||||
|  | 	/* | ||||||
|  | 		Not parsed from .yaml configuration file. | ||||||
|  | 		For short running commands (admin CLI tools etc). | ||||||
|  | 	*/ | ||||||
|  | 	AccountCLIFlags map[string]string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FromFile returns a new config from a file, or an error if something goes amiss. | // FromFile returns a new config from a file, or an error if something goes amiss. | ||||||
|  | @ -62,6 +85,7 @@ func Empty() *Config { | ||||||
| 		StorageConfig:     &StorageConfig{}, | 		StorageConfig:     &StorageConfig{}, | ||||||
| 		StatusesConfig:    &StatusesConfig{}, | 		StatusesConfig:    &StatusesConfig{}, | ||||||
| 		LetsEncryptConfig: &LetsEncryptConfig{}, | 		LetsEncryptConfig: &LetsEncryptConfig{}, | ||||||
|  | 		AccountCLIFlags:   make(map[string]string), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -81,7 +105,7 @@ func loadFromFile(path string) (*Config, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ParseCLIFlags sets flags on the config using the provided Flags object | // ParseCLIFlags sets flags on the config using the provided Flags object | ||||||
| func (c *Config) ParseCLIFlags(f KeyedFlags) { | func (c *Config) ParseCLIFlags(f KeyedFlags) error { | ||||||
| 	fn := GetFlagNames() | 	fn := GetFlagNames() | ||||||
| 
 | 
 | ||||||
| 	// For all of these flags, we only want to set them on the config if: | 	// For all of these flags, we only want to set them on the config if: | ||||||
|  | @ -104,10 +128,16 @@ func (c *Config) ParseCLIFlags(f KeyedFlags) { | ||||||
| 	if c.Host == "" || f.IsSet(fn.Host) { | 	if c.Host == "" || f.IsSet(fn.Host) { | ||||||
| 		c.Host = f.String(fn.Host) | 		c.Host = f.String(fn.Host) | ||||||
| 	} | 	} | ||||||
|  | 	if c.Host == "" { | ||||||
|  | 		return errors.New("host was not set") | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if c.Protocol == "" || f.IsSet(fn.Protocol) { | 	if c.Protocol == "" || f.IsSet(fn.Protocol) { | ||||||
| 		c.Protocol = f.String(fn.Protocol) | 		c.Protocol = f.String(fn.Protocol) | ||||||
| 	} | 	} | ||||||
|  | 	if c.Protocol == "" { | ||||||
|  | 		return errors.New("protocol was not set") | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// db flags | 	// db flags | ||||||
| 	if c.DBConfig.Type == "" || f.IsSet(fn.DbType) { | 	if c.DBConfig.Type == "" || f.IsSet(fn.DbType) { | ||||||
|  | @ -215,6 +245,15 @@ func (c *Config) ParseCLIFlags(f KeyedFlags) { | ||||||
| 	if c.LetsEncryptConfig.EmailAddress == "" || f.IsSet(fn.LetsEncryptEmailAddress) { | 	if c.LetsEncryptConfig.EmailAddress == "" || f.IsSet(fn.LetsEncryptEmailAddress) { | ||||||
| 		c.LetsEncryptConfig.EmailAddress = f.String(fn.LetsEncryptEmailAddress) | 		c.LetsEncryptConfig.EmailAddress = f.String(fn.LetsEncryptEmailAddress) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	// command-specific flags | ||||||
|  | 
 | ||||||
|  | 	// admin account CLI flags | ||||||
|  | 	c.AccountCLIFlags[UsernameFlag] = f.String(UsernameFlag) | ||||||
|  | 	c.AccountCLIFlags[EmailFlag] = f.String(EmailFlag) | ||||||
|  | 	c.AccountCLIFlags[PasswordFlag] = f.String(PasswordFlag) | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // KeyedFlags is a wrapper for any type that can store keyed flags and give them back. | // KeyedFlags is a wrapper for any type that can store keyed flags and give them back. | ||||||
|  |  | ||||||
|  | @ -54,9 +54,22 @@ func (p *processor) FollowRequestAccept(auth *oauth.Auth, accountID string) (*ap | ||||||
| 		return nil, NewErrorNotFound(err) | 		return nil, NewErrorNotFound(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	originAccount := >smodel.Account{} | ||||||
|  | 	if err := p.db.GetByID(follow.AccountID, originAccount); err != nil { | ||||||
|  | 		return nil, NewErrorInternalError(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	targetAccount := >smodel.Account{} | ||||||
|  | 	if err := p.db.GetByID(follow.TargetAccountID, targetAccount); err != nil { | ||||||
|  | 		return nil, NewErrorInternalError(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | ||||||
|  | 		APObjectType:   gtsmodel.ActivityStreamsFollow, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsAccept, | 		APActivityType: gtsmodel.ActivityStreamsAccept, | ||||||
| 		GTSModel:       follow, | 		GTSModel:       follow, | ||||||
|  | 		OriginAccount: originAccount, | ||||||
|  | 		TargetAccount: targetAccount, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	gtsR, err := p.db.GetRelationship(auth.Account.ID, accountID) | 	gtsR, err := p.db.GetRelationship(auth.Account.ID, accountID) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue