mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-18 13:27:28 -06:00
Implement Cobra CLI tooling, Viper config tooling (#336)
* start pulling out + replacing urfave and config * replace many many instances of config * move more stuff => viper * properly remove urfave * move some flags to root command * add testrig commands to root * alias config file keys * start adding cli parsing tests * reorder viper init * remove config path alias * fmt * change config file keys to non-nested * we're more or less in business now * tidy up the common func * go fmt * get tests passing again * add note about the cliparsing tests * reorganize * update docs with changes * structure cmd dir better * rename + move some files around * fix dangling comma
This commit is contained in:
parent
182b4eea73
commit
0884f89431
487 changed files with 46667 additions and 8831 deletions
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func accountsFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: flagNames.AccountsOpenRegistration,
|
||||
Usage: "Allow anyone to submit an account signup request. If false, server will be invite-only.",
|
||||
Value: defaults.AccountsOpenRegistration,
|
||||
EnvVars: []string{envNames.AccountsOpenRegistration},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: flagNames.AccountsApprovalRequired,
|
||||
Usage: "Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved.",
|
||||
Value: defaults.AccountsRequireApproval,
|
||||
EnvVars: []string{envNames.AccountsApprovalRequired},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: flagNames.AccountsReasonRequired,
|
||||
Usage: "Do new account signups require a reason to be submitted on registration?",
|
||||
Value: defaults.AccountsReasonRequired,
|
||||
EnvVars: []string{envNames.AccountsReasonRequired},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -16,22 +16,13 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
package action
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli/v2"
|
||||
"context"
|
||||
)
|
||||
|
||||
func getCommands(allFlags []cli.Flag) []*cli.Command {
|
||||
commands := []*cli.Command{}
|
||||
commandSets := [][]*cli.Command{
|
||||
serverCommands(allFlags),
|
||||
adminCommands(allFlags),
|
||||
testrigCommands(allFlags),
|
||||
}
|
||||
for _, cs := range commandSets {
|
||||
commands = append(commands, cs...)
|
||||
}
|
||||
|
||||
return commands
|
||||
}
|
||||
// GTSAction defines one *action* that can be taken by the gotosocial cli command.
|
||||
// This can be either a long-running action (like server start) or something
|
||||
// shorter like db init or db inspect.
|
||||
type GTSAction func(context.Context) error
|
||||
258
cmd/gotosocial/action/admin/account/account.go
Normal file
258
cmd/gotosocial/action/admin/account/account.go
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
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/spf13/viper"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/validate"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// Create creates a new account in the database using the provided flags.
|
||||
var Create action.GTSAction = func(ctx context.Context) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
username := viper.GetString(config.Keys.AdminAccountUsername)
|
||||
if username == "" {
|
||||
return errors.New("no username set")
|
||||
}
|
||||
if err := validate.Username(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
email := viper.GetString(config.Keys.AdminAccountEmail)
|
||||
if email == "" {
|
||||
return errors.New("no email set")
|
||||
}
|
||||
if err := validate.Email(email); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password := viper.GetString(config.Keys.AdminAccountPassword)
|
||||
if password == "" {
|
||||
return errors.New("no password set")
|
||||
}
|
||||
if err := validate.NewPassword(password); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dbConn.NewSignup(ctx, username, "", false, email, password, nil, "", "", false, false)
|
||||
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) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
username := viper.GetString(config.Keys.AdminAccountUsername)
|
||||
if username == "" {
|
||||
return errors.New("no username set")
|
||||
}
|
||||
if err := validate.Username(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a, err := dbConn.GetLocalAccountByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u := >smodel.User{}
|
||||
if err := dbConn.GetWhere(ctx, []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.UpdateByPrimaryKey(ctx, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dbConn.Stop(ctx)
|
||||
}
|
||||
|
||||
// Promote sets a user to admin.
|
||||
var Promote action.GTSAction = func(ctx context.Context) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
username := viper.GetString(config.Keys.AdminAccountUsername)
|
||||
if username == "" {
|
||||
return errors.New("no username set")
|
||||
}
|
||||
if err := validate.Username(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a, err := dbConn.GetLocalAccountByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u := >smodel.User{}
|
||||
if err := dbConn.GetWhere(ctx, []db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil {
|
||||
return err
|
||||
}
|
||||
u.Admin = true
|
||||
if err := dbConn.UpdateByPrimaryKey(ctx, 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) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
username := viper.GetString(config.Keys.AdminAccountUsername)
|
||||
if username == "" {
|
||||
return errors.New("no username set")
|
||||
}
|
||||
if err := validate.Username(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a, err := dbConn.GetLocalAccountByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u := >smodel.User{}
|
||||
if err := dbConn.GetWhere(ctx, []db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil {
|
||||
return err
|
||||
}
|
||||
u.Admin = false
|
||||
if err := dbConn.UpdateByPrimaryKey(ctx, 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) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
username := viper.GetString(config.Keys.AdminAccountUsername)
|
||||
if username == "" {
|
||||
return errors.New("no username set")
|
||||
}
|
||||
if err := validate.Username(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a, err := dbConn.GetLocalAccountByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u := >smodel.User{}
|
||||
if err := dbConn.GetWhere(ctx, []db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil {
|
||||
return err
|
||||
}
|
||||
u.Disabled = true
|
||||
if err := dbConn.UpdateByPrimaryKey(ctx, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dbConn.Stop(ctx)
|
||||
}
|
||||
|
||||
// Suspend suspends the target account, cleanly removing all of its media, followers, following, likes, statuses, etc.
|
||||
var Suspend action.GTSAction = func(ctx context.Context) error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
// Password sets the password of target account.
|
||||
var Password action.GTSAction = func(ctx context.Context) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
username := viper.GetString(config.Keys.AdminAccountUsername)
|
||||
if username == "" {
|
||||
return errors.New("no username set")
|
||||
}
|
||||
if err := validate.Username(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password := viper.GetString(config.Keys.AdminAccountPassword)
|
||||
if password == "" {
|
||||
return errors.New("no password set")
|
||||
}
|
||||
if err := validate.NewPassword(password); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a, err := dbConn.GetLocalAccountByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u := >smodel.User{}
|
||||
if err := dbConn.GetWhere(ctx, []db.Where{{Key: "account_id", Value: a.ID}}, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pw, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error hashing password: %s", err)
|
||||
}
|
||||
|
||||
u.EncryptedPassword = string(pw)
|
||||
|
||||
if err := dbConn.UpdateByPrimaryKey(ctx, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
52
cmd/gotosocial/action/admin/trans/export.go
Normal file
52
cmd/gotosocial/action/admin/trans/export.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
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 trans
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/trans"
|
||||
)
|
||||
|
||||
// Export exports info from the database into a file
|
||||
var Export action.GTSAction = func(ctx context.Context) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
exporter := trans.NewExporter(dbConn)
|
||||
|
||||
path := viper.GetString(config.Keys.AdminTransPath)
|
||||
if path == "" {
|
||||
return errors.New("no path set")
|
||||
}
|
||||
|
||||
if err := exporter.ExportMinimal(ctx, path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dbConn.Stop(ctx)
|
||||
}
|
||||
52
cmd/gotosocial/action/admin/trans/import.go
Normal file
52
cmd/gotosocial/action/admin/trans/import.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
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 trans
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/trans"
|
||||
)
|
||||
|
||||
// Import imports info from a file into the database
|
||||
var Import action.GTSAction = func(ctx context.Context) error {
|
||||
dbConn, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
importer := trans.NewImporter(dbConn)
|
||||
|
||||
path := viper.GetString(config.Keys.AdminTransPath)
|
||||
if path == "" {
|
||||
return errors.New("no path set")
|
||||
}
|
||||
|
||||
if err := importer.Import(ctx, path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dbConn.Stop(ctx)
|
||||
}
|
||||
|
|
@ -16,27 +16,24 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/cliactions/testrig"
|
||||
"github.com/urfave/cli/v2"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
)
|
||||
|
||||
func testrigCommands(allFlags []cli.Flag) []*cli.Command {
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "testrig",
|
||||
Usage: "gotosocial testrig tasks",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "start",
|
||||
Usage: "start the gotosocial testrig",
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, testrig.Start)
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Config just prints the collated config out to stdout as json.
|
||||
var Config action.GTSAction = func(ctx context.Context) error {
|
||||
allSettings := viper.AllSettings()
|
||||
b, err := json.Marshal(&allSettings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
225
cmd/gotosocial/action/server/server.go
Normal file
225
cmd/gotosocial/action/server/server.go
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
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 server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"codeberg.org/gruf/go-store/kv"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/account"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/app"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/auth"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/blocks"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/emoji"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/favourites"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/fileserver"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/filter"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/followrequest"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/instance"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/list"
|
||||
mediaModule "github.com/superseriousbusiness/gotosocial/internal/api/client/media"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/notification"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/search"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/status"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/streaming"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/timeline"
|
||||
userClient "github.com/superseriousbusiness/gotosocial/internal/api/client/user"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/nodeinfo"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/user"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/webfinger"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/security"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/email"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/federation"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gotosocial"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/media"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/oidc"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/processing"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/router"
|
||||
timelineprocessing "github.com/superseriousbusiness/gotosocial/internal/timeline"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/web"
|
||||
)
|
||||
|
||||
// Start creates and starts a gotosocial server
|
||||
var Start action.GTSAction = func(ctx context.Context) error {
|
||||
dbService, err := bundb.NewBunDBService(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating dbservice: %s", err)
|
||||
}
|
||||
|
||||
if err := dbService.CreateInstanceAccount(ctx); err != nil {
|
||||
return fmt.Errorf("error creating instance account: %s", err)
|
||||
}
|
||||
|
||||
if err := dbService.CreateInstanceInstance(ctx); err != nil {
|
||||
return fmt.Errorf("error creating instance instance: %s", err)
|
||||
}
|
||||
|
||||
federatingDB := federatingdb.New(dbService)
|
||||
|
||||
router, err := router.New(ctx, dbService)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating router: %s", err)
|
||||
}
|
||||
|
||||
// build converters and util
|
||||
typeConverter := typeutils.NewConverter(dbService)
|
||||
timelineManager := timelineprocessing.NewManager(dbService, typeConverter)
|
||||
|
||||
// Open the storage backend
|
||||
storageBasePath := viper.GetString(config.Keys.StorageBasePath)
|
||||
storage, err := kv.OpenFile(storageBasePath, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating storage backend: %s", err)
|
||||
}
|
||||
|
||||
// build backend handlers
|
||||
mediaHandler := media.New(dbService, storage)
|
||||
oauthServer := oauth.New(ctx, dbService)
|
||||
transportController := transport.NewController(dbService, &federation.Clock{}, http.DefaultClient)
|
||||
federator := federation.NewFederator(dbService, federatingDB, transportController, typeConverter, mediaHandler)
|
||||
|
||||
// decide whether to create a noop email sender (won't send emails) or a real one
|
||||
var emailSender email.Sender
|
||||
smtpHost := viper.GetString(config.Keys.SMTPHost)
|
||||
if smtpHost != "" {
|
||||
// host is defined so create a proper sender
|
||||
emailSender, err = email.NewSender()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating email sender: %s", err)
|
||||
}
|
||||
} else {
|
||||
// no host is defined so create a noop sender
|
||||
emailSender, err = email.NewNoopSender(nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating noop email sender: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// create and start the message processor using the other services we've created so far
|
||||
processor := processing.NewProcessor(typeConverter, federator, oauthServer, mediaHandler, storage, timelineManager, dbService, emailSender)
|
||||
if err := processor.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting processor: %s", err)
|
||||
}
|
||||
|
||||
idp, err := oidc.NewIDP(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating oidc idp: %s", err)
|
||||
}
|
||||
|
||||
// build client api modules
|
||||
authModule := auth.New(dbService, oauthServer, idp)
|
||||
accountModule := account.New(processor)
|
||||
instanceModule := instance.New(processor)
|
||||
appsModule := app.New(processor)
|
||||
followRequestsModule := followrequest.New(processor)
|
||||
webfingerModule := webfinger.New(processor)
|
||||
nodeInfoModule := nodeinfo.New(processor)
|
||||
webBaseModule := web.New(processor)
|
||||
usersModule := user.New(processor)
|
||||
timelineModule := timeline.New(processor)
|
||||
notificationModule := notification.New(processor)
|
||||
searchModule := search.New(processor)
|
||||
filtersModule := filter.New(processor)
|
||||
emojiModule := emoji.New(processor)
|
||||
listsModule := list.New(processor)
|
||||
mm := mediaModule.New(processor)
|
||||
fileServerModule := fileserver.New(processor)
|
||||
adminModule := admin.New(processor)
|
||||
statusModule := status.New(processor)
|
||||
securityModule := security.New(dbService, oauthServer)
|
||||
streamingModule := streaming.New(processor)
|
||||
favouritesModule := favourites.New(processor)
|
||||
blocksModule := blocks.New(processor)
|
||||
userClientModule := userClient.New(processor)
|
||||
|
||||
apis := []api.ClientModule{
|
||||
// modules with middleware go first
|
||||
securityModule,
|
||||
authModule,
|
||||
|
||||
// now everything else
|
||||
webBaseModule,
|
||||
accountModule,
|
||||
instanceModule,
|
||||
appsModule,
|
||||
followRequestsModule,
|
||||
mm,
|
||||
fileServerModule,
|
||||
adminModule,
|
||||
statusModule,
|
||||
webfingerModule,
|
||||
nodeInfoModule,
|
||||
usersModule,
|
||||
timelineModule,
|
||||
notificationModule,
|
||||
searchModule,
|
||||
filtersModule,
|
||||
emojiModule,
|
||||
listsModule,
|
||||
streamingModule,
|
||||
favouritesModule,
|
||||
blocksModule,
|
||||
userClientModule,
|
||||
}
|
||||
|
||||
for _, m := range apis {
|
||||
if err := m.Route(router); err != nil {
|
||||
return fmt.Errorf("routing error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
gts, err := gotosocial.NewServer(dbService, router, federator)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating gotosocial service: %s", err)
|
||||
}
|
||||
|
||||
if err := gts.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting gotosocial service: %s", err)
|
||||
}
|
||||
|
||||
// catch shutdown signals from the operating system
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
|
||||
sig := <-sigs
|
||||
logrus.Infof("received signal %s, shutting down", sig)
|
||||
|
||||
// close down all running services in order
|
||||
if err := gts.Stop(ctx); err != nil {
|
||||
return fmt.Errorf("error closing gotosocial service: %s", err)
|
||||
}
|
||||
|
||||
logrus.Info("done! exiting...")
|
||||
return nil
|
||||
}
|
||||
184
cmd/gotosocial/action/testrig/testrig.go
Normal file
184
cmd/gotosocial/action/testrig/testrig.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
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 testrig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/account"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/app"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/auth"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/blocks"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/emoji"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/favourites"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/fileserver"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/filter"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/followrequest"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/instance"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/list"
|
||||
mediaModule "github.com/superseriousbusiness/gotosocial/internal/api/client/media"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/notification"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/search"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/status"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/streaming"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/client/timeline"
|
||||
userClient "github.com/superseriousbusiness/gotosocial/internal/api/client/user"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/nodeinfo"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/user"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/webfinger"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api/security"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gotosocial"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/oidc"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/web"
|
||||
"github.com/superseriousbusiness/gotosocial/testrig"
|
||||
)
|
||||
|
||||
// Start creates and starts a gotosocial testrig server
|
||||
var Start action.GTSAction = func(ctx context.Context) error {
|
||||
testrig.InitTestConfig()
|
||||
testrig.InitTestLog()
|
||||
|
||||
dbService := testrig.NewTestDB()
|
||||
testrig.StandardDBSetup(dbService, nil)
|
||||
router := testrig.NewTestRouter(dbService)
|
||||
storageBackend := testrig.NewTestStorage()
|
||||
testrig.StandardStorageSetup(storageBackend, "./testrig/media")
|
||||
|
||||
// build backend handlers
|
||||
oauthServer := testrig.NewTestOauthServer(dbService)
|
||||
transportController := testrig.NewTestTransportController(testrig.NewMockHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
r := ioutil.NopCloser(bytes.NewReader([]byte{}))
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: r,
|
||||
}, nil
|
||||
}), dbService)
|
||||
federator := testrig.NewTestFederator(dbService, transportController, storageBackend)
|
||||
|
||||
emailSender := testrig.NewEmailSender("./web/template/", nil)
|
||||
|
||||
processor := testrig.NewTestProcessor(dbService, storageBackend, federator, emailSender)
|
||||
if err := processor.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting processor: %s", err)
|
||||
}
|
||||
|
||||
idp, err := oidc.NewIDP(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating oidc idp: %s", err)
|
||||
}
|
||||
|
||||
// build client api modules
|
||||
authModule := auth.New(dbService, oauthServer, idp)
|
||||
accountModule := account.New(processor)
|
||||
instanceModule := instance.New(processor)
|
||||
appsModule := app.New(processor)
|
||||
followRequestsModule := followrequest.New(processor)
|
||||
webfingerModule := webfinger.New(processor)
|
||||
nodeInfoModule := nodeinfo.New(processor)
|
||||
webBaseModule := web.New(processor)
|
||||
usersModule := user.New(processor)
|
||||
timelineModule := timeline.New(processor)
|
||||
notificationModule := notification.New(processor)
|
||||
searchModule := search.New(processor)
|
||||
filtersModule := filter.New(processor)
|
||||
emojiModule := emoji.New(processor)
|
||||
listsModule := list.New(processor)
|
||||
mm := mediaModule.New(processor)
|
||||
fileServerModule := fileserver.New(processor)
|
||||
adminModule := admin.New(processor)
|
||||
statusModule := status.New(processor)
|
||||
securityModule := security.New(dbService, oauthServer)
|
||||
streamingModule := streaming.New(processor)
|
||||
favouritesModule := favourites.New(processor)
|
||||
blocksModule := blocks.New(processor)
|
||||
userClientModule := userClient.New(processor)
|
||||
|
||||
apis := []api.ClientModule{
|
||||
// modules with middleware go first
|
||||
securityModule,
|
||||
authModule,
|
||||
|
||||
// now everything else
|
||||
webBaseModule,
|
||||
accountModule,
|
||||
instanceModule,
|
||||
appsModule,
|
||||
followRequestsModule,
|
||||
mm,
|
||||
fileServerModule,
|
||||
adminModule,
|
||||
statusModule,
|
||||
webfingerModule,
|
||||
nodeInfoModule,
|
||||
usersModule,
|
||||
timelineModule,
|
||||
notificationModule,
|
||||
searchModule,
|
||||
filtersModule,
|
||||
emojiModule,
|
||||
listsModule,
|
||||
streamingModule,
|
||||
favouritesModule,
|
||||
blocksModule,
|
||||
userClientModule,
|
||||
}
|
||||
|
||||
for _, m := range apis {
|
||||
if err := m.Route(router); err != nil {
|
||||
return fmt.Errorf("routing error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
gts, err := gotosocial.NewServer(dbService, router, federator)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating gotosocial service: %s", err)
|
||||
}
|
||||
|
||||
if err := gts.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting gotosocial service: %s", err)
|
||||
}
|
||||
|
||||
// catch shutdown signals from the operating system
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
|
||||
sig := <-sigs
|
||||
logrus.Infof("received signal %s, shutting down", sig)
|
||||
|
||||
testrig.StandardDBTeardown(dbService)
|
||||
testrig.StandardStorageTeardown(storageBackend)
|
||||
|
||||
// close down all running services in order
|
||||
if err := gts.Stop(ctx); err != nil {
|
||||
return fmt.Errorf("error closing gotosocial service: %s", err)
|
||||
}
|
||||
|
||||
logrus.Info("done! exiting...")
|
||||
return nil
|
||||
}
|
||||
169
cmd/gotosocial/admin.go
Normal file
169
cmd/gotosocial/admin.go
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/admin/account"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/admin/trans"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/flag"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
)
|
||||
|
||||
func adminCommands() *cobra.Command {
|
||||
adminCmd := &cobra.Command{
|
||||
Use: "admin",
|
||||
Short: "gotosocial admin-related tasks",
|
||||
}
|
||||
|
||||
/*
|
||||
ADMIN ACCOUNT COMMANDS
|
||||
*/
|
||||
|
||||
adminAccountCmd := &cobra.Command{
|
||||
Use: "account",
|
||||
Short: "admin commands related to accounts",
|
||||
}
|
||||
flag.AdminAccount(adminAccountCmd, config.Defaults)
|
||||
|
||||
adminAccountCreateCmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "create a new account",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Create)
|
||||
},
|
||||
}
|
||||
flag.AdminAccountCreate(adminAccountCreateCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountCreateCmd)
|
||||
|
||||
adminAccountConfirmCmd := &cobra.Command{
|
||||
Use: "confirm",
|
||||
Short: "confirm an existing account manually, thereby skipping email confirmation",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Confirm)
|
||||
},
|
||||
}
|
||||
flag.AdminAccount(adminAccountConfirmCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountConfirmCmd)
|
||||
|
||||
adminAccountPromoteCmd := &cobra.Command{
|
||||
Use: "promote",
|
||||
Short: "promote an account to admin",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Promote)
|
||||
},
|
||||
}
|
||||
flag.AdminAccount(adminAccountPromoteCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountPromoteCmd)
|
||||
|
||||
adminAccountDemoteCmd := &cobra.Command{
|
||||
Use: "demote",
|
||||
Short: "demote an account from admin to normal user",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Demote)
|
||||
},
|
||||
}
|
||||
flag.AdminAccount(adminAccountDemoteCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountDemoteCmd)
|
||||
|
||||
adminAccountDisableCmd := &cobra.Command{
|
||||
Use: "disable",
|
||||
Short: "prevent an account from signing in or posting etc, but don't delete anything",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Disable)
|
||||
},
|
||||
}
|
||||
flag.AdminAccount(adminAccountDisableCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountDisableCmd)
|
||||
|
||||
adminAccountSuspendCmd := &cobra.Command{
|
||||
Use: "suspend",
|
||||
Short: "completely remove an account and all of its posts, media, etc",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Suspend)
|
||||
},
|
||||
}
|
||||
flag.AdminAccount(adminAccountSuspendCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountSuspendCmd)
|
||||
|
||||
adminAccountPasswordCmd := &cobra.Command{
|
||||
Use: "password",
|
||||
Short: "set a new password for the given account",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), account.Password)
|
||||
},
|
||||
}
|
||||
flag.AdminAccountPassword(adminAccountPasswordCmd, config.Defaults)
|
||||
adminAccountCmd.AddCommand(adminAccountPasswordCmd)
|
||||
|
||||
adminCmd.AddCommand(adminAccountCmd)
|
||||
|
||||
/*
|
||||
ADMIN IMPORT/EXPORT COMMANDS
|
||||
*/
|
||||
|
||||
adminExportCmd := &cobra.Command{
|
||||
Use: "export",
|
||||
Short: "export data from the database to file at the given path",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), trans.Export)
|
||||
},
|
||||
}
|
||||
flag.AdminTrans(adminExportCmd, config.Defaults)
|
||||
adminCmd.AddCommand(adminExportCmd)
|
||||
|
||||
adminImportCmd := &cobra.Command{
|
||||
Use: "import",
|
||||
Short: "import data from a file into the database",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), trans.Import)
|
||||
},
|
||||
}
|
||||
flag.AdminTrans(adminImportCmd, config.Defaults)
|
||||
adminCmd.AddCommand(adminImportCmd)
|
||||
|
||||
return adminCmd
|
||||
}
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/cliactions/admin/account"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/cliactions/admin/trans"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func adminCommands(allFlags []cli.Flag) []*cli.Command {
|
||||
return []*cli.Command{
|
||||
{
|
||||
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,
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: config.EmailFlag,
|
||||
Usage: config.EmailUsage,
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: config.PasswordFlag,
|
||||
Usage: config.PasswordUsage,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, 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,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, account.Confirm)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "promote",
|
||||
Usage: "promote an account to admin",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: config.UsernameFlag,
|
||||
Usage: config.UsernameUsage,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, account.Promote)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "demote",
|
||||
Usage: "demote an account from admin to normal user",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: config.UsernameFlag,
|
||||
Usage: config.UsernameUsage,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, 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,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, 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,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, account.Suspend)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "password",
|
||||
Usage: "set a new password for the given account",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: config.UsernameFlag,
|
||||
Usage: config.UsernameUsage,
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: config.PasswordFlag,
|
||||
Usage: config.PasswordUsage,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, account.Password)
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "export",
|
||||
Usage: "export data from the database to file at the given path",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: config.TransPathFlag,
|
||||
Usage: config.TransPathUsage,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, trans.Export)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "import",
|
||||
Usage: "import data from a file into the database",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: config.TransPathFlag,
|
||||
Usage: config.TransPathUsage,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, trans.Import)
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
64
cmd/gotosocial/common.go
Normal file
64
cmd/gotosocial/common.go
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
)
|
||||
|
||||
// preRun should be run in the pre-run stage of every cobra command.
|
||||
// The goal here is to initialize the viper config store, and also read in
|
||||
// the config file (if present).
|
||||
//
|
||||
// The order of these is important: the init-config function reads the location
|
||||
// of the config file from the viper store so that it can be picked up by either
|
||||
// env vars or cli flag.
|
||||
func preRun(cmd *cobra.Command) error {
|
||||
if err := config.InitViper(cmd.Flags()); err != nil {
|
||||
return fmt.Errorf("error initializing viper: %s", err)
|
||||
}
|
||||
|
||||
if err := config.ReadFromFile(); err != nil {
|
||||
return fmt.Errorf("error initializing config: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// run should be used during the run stage of every cobra command.
|
||||
// The idea here is to take a GTSAction and run it with the given
|
||||
// context, after initializing any last-minute things like loggers etc.
|
||||
func run(ctx context.Context, action action.GTSAction) error {
|
||||
// if log level has been set...
|
||||
if logLevel := viper.GetString(config.Keys.LogLevel); logLevel != "" {
|
||||
// then try to initialize the logger to that level
|
||||
if err := log.Initialize(logLevel); err != nil {
|
||||
return fmt.Errorf("error initializing log: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return action(ctx)
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func databaseFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbType,
|
||||
Usage: "Database type: eg., postgres",
|
||||
Value: defaults.DbType,
|
||||
EnvVars: []string{envNames.DbType},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbAddress,
|
||||
Usage: "Database ipv4 address or hostname",
|
||||
Value: defaults.DbAddress,
|
||||
EnvVars: []string{envNames.DbAddress},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.DbPort,
|
||||
Usage: "Database port",
|
||||
Value: defaults.DbPort,
|
||||
EnvVars: []string{envNames.DbPort},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbUser,
|
||||
Usage: "Database username",
|
||||
Value: defaults.DbUser,
|
||||
EnvVars: []string{envNames.DbUser},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbPassword,
|
||||
Usage: "Database password",
|
||||
Value: defaults.DbPassword,
|
||||
EnvVars: []string{envNames.DbPassword},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbDatabase,
|
||||
Usage: "Database name",
|
||||
Value: defaults.DbDatabase,
|
||||
EnvVars: []string{envNames.DbDatabase},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbTLSMode,
|
||||
Usage: "Database tls mode",
|
||||
Value: defaults.DBTlsMode,
|
||||
EnvVars: []string{envNames.DbTLSMode},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.DbTLSCACert,
|
||||
Usage: "Path to CA cert for db tls connection",
|
||||
Value: defaults.DBTlsCACert,
|
||||
EnvVars: []string{envNames.DbTLSCACert},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -19,31 +19,30 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
configaction "github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/debug/config"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/flag"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func getFlags() []cli.Flag {
|
||||
flagNames := config.GetFlagNames()
|
||||
envNames := config.GetEnvNames()
|
||||
defaults := config.GetDefaults()
|
||||
|
||||
flags := []cli.Flag{}
|
||||
flagSets := [][]cli.Flag{
|
||||
generalFlags(flagNames, envNames, defaults),
|
||||
databaseFlags(flagNames, envNames, defaults),
|
||||
templateFlags(flagNames, envNames, defaults),
|
||||
accountsFlags(flagNames, envNames, defaults),
|
||||
mediaFlags(flagNames, envNames, defaults),
|
||||
storageFlags(flagNames, envNames, defaults),
|
||||
statusesFlags(flagNames, envNames, defaults),
|
||||
letsEncryptFlags(flagNames, envNames, defaults),
|
||||
oidcFlags(flagNames, envNames, defaults),
|
||||
smtpFlags(flagNames, envNames, defaults),
|
||||
}
|
||||
for _, fs := range flagSets {
|
||||
flags = append(flags, fs...)
|
||||
func debugCommands() *cobra.Command {
|
||||
debugCmd := &cobra.Command{
|
||||
Use: "debug",
|
||||
Short: "gotosocial debug-related tasks",
|
||||
}
|
||||
|
||||
return flags
|
||||
debugConfigCmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "print the collated config (derived from env, flag, and config file) to stdout",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), configaction.Config)
|
||||
},
|
||||
}
|
||||
flag.Server(debugConfigCmd, config.Defaults)
|
||||
|
||||
debugCmd.AddCommand(debugConfigCmd)
|
||||
return debugCmd
|
||||
}
|
||||
62
cmd/gotosocial/flag/admin.go
Normal file
62
cmd/gotosocial/flag/admin.go
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
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 flag
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
)
|
||||
|
||||
// AdminAccount attaches flags pertaining to admin account actions.
|
||||
func AdminAccount(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().String(config.Keys.AdminAccountUsername, "", usage.AdminAccountUsername) // REQUIRED
|
||||
if err := cmd.MarkFlagRequired(config.Keys.AdminAccountUsername); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// AdminAccountPassword attaches flags pertaining to admin account password reset.
|
||||
func AdminAccountPassword(cmd *cobra.Command, values config.Values) {
|
||||
AdminAccount(cmd, values)
|
||||
cmd.Flags().String(config.Keys.AdminAccountPassword, "", usage.AdminAccountPassword) // REQUIRED
|
||||
if err := cmd.MarkFlagRequired(config.Keys.AdminAccountPassword); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// AdminAccountCreate attaches flags pertaining to admin account creation.
|
||||
func AdminAccountCreate(cmd *cobra.Command, values config.Values) {
|
||||
AdminAccount(cmd, values)
|
||||
cmd.Flags().String(config.Keys.AdminAccountPassword, "", usage.AdminAccountPassword) // REQUIRED
|
||||
if err := cmd.MarkFlagRequired(config.Keys.AdminAccountPassword); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cmd.Flags().String(config.Keys.AdminAccountEmail, "", usage.AdminAccountEmail) // REQUIRED
|
||||
if err := cmd.MarkFlagRequired(config.Keys.AdminAccountEmail); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// AdminTrans attaches flags pertaining to import/export commands.
|
||||
func AdminTrans(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().String(config.Keys.AdminTransPath, "", usage.AdminTransPath) // REQUIRED
|
||||
if err := cmd.MarkFlagRequired(config.Keys.AdminTransPath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
45
cmd/gotosocial/flag/global.go
Normal file
45
cmd/gotosocial/flag/global.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
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 flag
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
)
|
||||
|
||||
// Global attaches flags that are common to all commands, aka persistent commands.
|
||||
func Global(cmd *cobra.Command, values config.Values) {
|
||||
// general stuff
|
||||
cmd.PersistentFlags().String(config.Keys.ApplicationName, values.ApplicationName, usage.ApplicationName)
|
||||
cmd.PersistentFlags().String(config.Keys.Host, values.Host, usage.Host)
|
||||
cmd.PersistentFlags().String(config.Keys.AccountDomain, values.AccountDomain, usage.AccountDomain)
|
||||
cmd.PersistentFlags().String(config.Keys.Protocol, values.Protocol, usage.Protocol)
|
||||
cmd.PersistentFlags().String(config.Keys.LogLevel, values.LogLevel, usage.LogLevel)
|
||||
cmd.PersistentFlags().String(config.Keys.ConfigPath, values.ConfigPath, usage.ConfigPath)
|
||||
|
||||
// database stuff
|
||||
cmd.PersistentFlags().String(config.Keys.DbType, values.DbType, usage.DbType)
|
||||
cmd.PersistentFlags().String(config.Keys.DbAddress, values.DbAddress, usage.DbAddress)
|
||||
cmd.PersistentFlags().Int(config.Keys.DbPort, values.DbPort, usage.DbPort)
|
||||
cmd.PersistentFlags().String(config.Keys.DbUser, values.DbUser, usage.DbUser)
|
||||
cmd.PersistentFlags().String(config.Keys.DbPassword, values.DbPassword, usage.DbPassword)
|
||||
cmd.PersistentFlags().String(config.Keys.DbDatabase, values.DbDatabase, usage.DbDatabase)
|
||||
cmd.PersistentFlags().String(config.Keys.DbTLSMode, values.DbTLSMode, usage.DbTLSMode)
|
||||
cmd.PersistentFlags().String(config.Keys.DbTLSCACert, values.DbTLSCACert, usage.DbTLSCACert)
|
||||
}
|
||||
111
cmd/gotosocial/flag/server.go
Normal file
111
cmd/gotosocial/flag/server.go
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
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 flag
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
)
|
||||
|
||||
// Server attaches all flags pertaining to running the GtS server or testrig.
|
||||
func Server(cmd *cobra.Command, values config.Values) {
|
||||
Template(cmd, values)
|
||||
Accounts(cmd, values)
|
||||
Media(cmd, values)
|
||||
Storage(cmd, values)
|
||||
Statuses(cmd, values)
|
||||
LetsEncrypt(cmd, values)
|
||||
OIDC(cmd, values)
|
||||
SMTP(cmd, values)
|
||||
Router(cmd, values)
|
||||
}
|
||||
|
||||
// Router attaches flags pertaining to the gin router.
|
||||
func Router(cmd *cobra.Command, values config.Values) {
|
||||
cmd.PersistentFlags().String(config.Keys.BindAddress, values.BindAddress, usage.BindAddress)
|
||||
cmd.PersistentFlags().Int(config.Keys.Port, values.Port, usage.Port)
|
||||
cmd.PersistentFlags().StringSlice(config.Keys.TrustedProxies, values.TrustedProxies, usage.TrustedProxies)
|
||||
}
|
||||
|
||||
// Template attaches flags pertaining to templating config.
|
||||
func Template(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().String(config.Keys.WebTemplateBaseDir, values.WebTemplateBaseDir, usage.WebTemplateBaseDir)
|
||||
cmd.Flags().String(config.Keys.WebAssetBaseDir, values.WebAssetBaseDir, usage.WebAssetBaseDir)
|
||||
}
|
||||
|
||||
// Accounts attaches flags pertaining to account config.
|
||||
func Accounts(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().Bool(config.Keys.AccountsRegistrationOpen, values.AccountsRegistrationOpen, usage.AccountsRegistrationOpen)
|
||||
cmd.Flags().Bool(config.Keys.AccountsApprovalRequired, values.AccountsApprovalRequired, usage.AccountsApprovalRequired)
|
||||
cmd.Flags().Bool(config.Keys.AccountsReasonRequired, values.AccountsReasonRequired, usage.AccountsReasonRequired)
|
||||
}
|
||||
|
||||
// Media attaches flags pertaining to media config.
|
||||
func Media(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().Int(config.Keys.MediaImageMaxSize, values.MediaImageMaxSize, usage.MediaImageMaxSize)
|
||||
cmd.Flags().Int(config.Keys.MediaVideoMaxSize, values.MediaVideoMaxSize, usage.MediaVideoMaxSize)
|
||||
cmd.Flags().Int(config.Keys.MediaDescriptionMinChars, values.MediaDescriptionMinChars, usage.MediaDescriptionMinChars)
|
||||
cmd.Flags().Int(config.Keys.MediaDescriptionMaxChars, values.MediaDescriptionMaxChars, usage.MediaDescriptionMaxChars)
|
||||
}
|
||||
|
||||
// Storage attaches flags pertaining to storage config.
|
||||
func Storage(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().String(config.Keys.StorageBackend, values.StorageBackend, usage.StorageBackend)
|
||||
cmd.Flags().String(config.Keys.StorageBasePath, values.StorageBasePath, usage.StorageBasePath)
|
||||
cmd.Flags().String(config.Keys.StorageServeProtocol, values.StorageServeProtocol, usage.StorageServeProtocol)
|
||||
cmd.Flags().String(config.Keys.StorageServeHost, values.StorageServeHost, usage.StorageServeHost)
|
||||
cmd.Flags().String(config.Keys.StorageServeBasePath, values.StorageServeBasePath, usage.StorageServeBasePath)
|
||||
}
|
||||
|
||||
// Statuses attaches flags pertaining to statuses config.
|
||||
func Statuses(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().Int(config.Keys.StatusesMaxChars, values.StatusesMaxChars, usage.StatusesMaxChars)
|
||||
cmd.Flags().Int(config.Keys.StatusesCWMaxChars, values.StatusesCWMaxChars, usage.StatusesCWMaxChars)
|
||||
cmd.Flags().Int(config.Keys.StatusesPollMaxOptions, values.StatusesPollMaxOptions, usage.StatusesPollMaxOptions)
|
||||
cmd.Flags().Int(config.Keys.StatusesPollOptionMaxChars, values.StatusesPollOptionMaxChars, usage.StatusesPollOptionMaxChars)
|
||||
cmd.Flags().Int(config.Keys.StatusesMediaMaxFiles, values.StatusesMediaMaxFiles, usage.StatusesMediaMaxFiles)
|
||||
}
|
||||
|
||||
// LetsEncrypt attaches flags pertaining to letsencrypt config.
|
||||
func LetsEncrypt(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().Bool(config.Keys.LetsEncryptEnabled, values.LetsEncryptEnabled, usage.LetsEncryptEnabled)
|
||||
cmd.Flags().Int(config.Keys.LetsEncryptPort, values.LetsEncryptPort, usage.LetsEncryptPort)
|
||||
cmd.Flags().String(config.Keys.LetsEncryptCertDir, values.LetsEncryptCertDir, usage.LetsEncryptCertDir)
|
||||
cmd.Flags().String(config.Keys.LetsEncryptEmailAddress, values.LetsEncryptEmailAddress, usage.LetsEncryptEmailAddress)
|
||||
}
|
||||
|
||||
// OIDC attaches flags pertaining to oidc config.
|
||||
func OIDC(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().Bool(config.Keys.OIDCEnabled, values.OIDCEnabled, usage.OIDCEnabled)
|
||||
cmd.Flags().String(config.Keys.OIDCIdpName, values.OIDCIdpName, usage.OIDCIdpName)
|
||||
cmd.Flags().Bool(config.Keys.OIDCSkipVerification, values.OIDCSkipVerification, usage.OIDCSkipVerification)
|
||||
cmd.Flags().String(config.Keys.OIDCIssuer, values.OIDCIssuer, usage.OIDCIssuer)
|
||||
cmd.Flags().String(config.Keys.OIDCClientID, values.OIDCClientID, usage.OIDCClientID)
|
||||
cmd.Flags().String(config.Keys.OIDCClientSecret, values.OIDCClientSecret, usage.OIDCClientSecret)
|
||||
cmd.Flags().StringSlice(config.Keys.OIDCScopes, values.OIDCScopes, usage.OIDCScopes)
|
||||
}
|
||||
|
||||
// SMTP attaches flags pertaining to smtp/email config.
|
||||
func SMTP(cmd *cobra.Command, values config.Values) {
|
||||
cmd.Flags().String(config.Keys.SMTPHost, values.SMTPHost, usage.SMTPHost)
|
||||
cmd.Flags().Int(config.Keys.SMTPPort, values.SMTPPort, usage.SMTPPort)
|
||||
cmd.Flags().String(config.Keys.SMTPUsername, values.SMTPUsername, usage.SMTPUsername)
|
||||
cmd.Flags().String(config.Keys.SMTPPassword, values.SMTPPassword, usage.SMTPPassword)
|
||||
cmd.Flags().String(config.Keys.SMTPFrom, values.SMTPFrom, usage.SMTPFrom)
|
||||
}
|
||||
80
cmd/gotosocial/flag/usage.go
Normal file
80
cmd/gotosocial/flag/usage.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 flag
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
|
||||
var usage = config.KeyNames{
|
||||
LogLevel: "Log level to run at: [trace, debug, info, warn, fatal]",
|
||||
ApplicationName: "Name of the application, used in various places internally",
|
||||
ConfigPath: "Path to a file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments",
|
||||
Host: "Hostname to use for the server (eg., example.org, gotosocial.whatever.com). DO NOT change this on a server that's already run!",
|
||||
AccountDomain: "Domain to use in account names (eg., example.org, whatever.com). If not set, will default to the setting for host. DO NOT change this on a server that's already run!",
|
||||
Protocol: "Protocol to use for the REST api of the server (only use http for debugging and tests!)",
|
||||
BindAddress: "Bind address to use for the GoToSocial server (eg., 0.0.0.0, 172.138.0.9, [::], localhost). For ipv6, enclose the address in square brackets, eg [2001:db8::fed1]. Default binds to all interfaces.",
|
||||
Port: "Port to use for GoToSocial. Change this to 443 if you're running the binary directly on the host machine.",
|
||||
TrustedProxies: "Proxies to trust when parsing x-forwarded headers into real IPs.",
|
||||
DbType: "Database type: eg., postgres",
|
||||
DbAddress: "Database ipv4 address, hostname, or filename",
|
||||
DbPort: "Database port",
|
||||
DbUser: "Database username",
|
||||
DbPassword: "Database password",
|
||||
DbDatabase: "Database name",
|
||||
DbTLSMode: "Database tls mode",
|
||||
DbTLSCACert: "Path to CA cert for db tls connection",
|
||||
WebTemplateBaseDir: "Basedir for html templating files for rendering pages and composing emails.",
|
||||
WebAssetBaseDir: "Directory to serve static assets from, accessible at example.org/assets/",
|
||||
AccountsRegistrationOpen: "Allow anyone to submit an account signup request. If false, server will be invite-only.",
|
||||
AccountsApprovalRequired: "Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved.",
|
||||
AccountsReasonRequired: "Do new account signups require a reason to be submitted on registration?",
|
||||
MediaImageMaxSize: "Max size of accepted images in bytes",
|
||||
MediaVideoMaxSize: "Max size of accepted videos in bytes",
|
||||
MediaDescriptionMinChars: "Min required chars for an image description",
|
||||
MediaDescriptionMaxChars: "Max permitted chars for an image description",
|
||||
StorageBackend: "Storage backend to use for media attachments",
|
||||
StorageBasePath: "Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir.",
|
||||
StorageServeProtocol: "Protocol to use for serving media attachments (use https if storage is local)",
|
||||
StorageServeHost: "Hostname to serve media attachments from (use the same value as host if storage is local)",
|
||||
StorageServeBasePath: "Path to append to protocol and hostname to create the base path from which media files will be served (default will mostly be fine)",
|
||||
StatusesMaxChars: "Max permitted characters for posted statuses",
|
||||
StatusesCWMaxChars: "Max permitted characters for content/spoiler warnings on statuses",
|
||||
StatusesPollMaxOptions: "Max amount of options permitted on a poll",
|
||||
StatusesPollOptionMaxChars: "Max amount of characters for a poll option",
|
||||
StatusesMediaMaxFiles: "Maximum number of media files/attachments per status",
|
||||
LetsEncryptEnabled: "Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default).",
|
||||
LetsEncryptPort: "Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port.",
|
||||
LetsEncryptCertDir: "Directory to store acquired letsencrypt certificates.",
|
||||
LetsEncryptEmailAddress: "Email address to use when requesting letsencrypt certs. Will receive updates on cert expiry etc.",
|
||||
OIDCEnabled: "Enabled OIDC authorization for this instance. If set to true, then the other OIDC flags must also be set.",
|
||||
OIDCIdpName: "Name of the OIDC identity provider. Will be shown to the user when logging in.",
|
||||
OIDCSkipVerification: "Skip verification of tokens returned by the OIDC provider. Should only be set to 'true' for testing purposes, never in a production environment!",
|
||||
OIDCIssuer: "Address of the OIDC issuer. Should be the web address, including protocol, at which the issuer can be reached. Eg., 'https://example.org/auth'",
|
||||
OIDCClientID: "ClientID of GoToSocial, as registered with the OIDC provider.",
|
||||
OIDCClientSecret: "ClientSecret of GoToSocial, as registered with the OIDC provider.",
|
||||
OIDCScopes: "OIDC scopes.",
|
||||
SMTPHost: "Host of the smtp server. Eg., 'smtp.eu.mailgun.org'",
|
||||
SMTPPort: "Port of the smtp server. Eg., 587",
|
||||
SMTPUsername: "Username to authenticate with the smtp server as. Eg., 'postmaster@mail.example.org'",
|
||||
SMTPPassword: "Password to pass to the smtp server.",
|
||||
SMTPFrom: "Address to use as the 'from' field of the email. Eg., 'gotosocial@example.org'",
|
||||
AdminAccountUsername: "the username to create/delete/etc",
|
||||
AdminAccountEmail: "the email address of this account",
|
||||
AdminAccountPassword: "the password to set for this account",
|
||||
AdminTransPath: "the path of the file to import from/export to",
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func generalFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.LogLevel,
|
||||
Usage: "Log level to run at: debug, info, warn, fatal",
|
||||
Value: defaults.LogLevel,
|
||||
EnvVars: []string{envNames.LogLevel},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.ApplicationName,
|
||||
Usage: "Name of the application, used in various places internally",
|
||||
Value: defaults.ApplicationName,
|
||||
EnvVars: []string{envNames.ApplicationName},
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.ConfigPath,
|
||||
Usage: "Path to a yaml file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments",
|
||||
Value: defaults.ConfigPath,
|
||||
EnvVars: []string{envNames.ConfigPath},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.Host,
|
||||
Usage: "Hostname to use for the server (eg., example.org, gotosocial.whatever.com). DO NOT change this on a server that's already run!",
|
||||
Value: defaults.Host,
|
||||
EnvVars: []string{envNames.Host},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.AccountDomain,
|
||||
Usage: "Domain to use in account names (eg., example.org, whatever.com). If not set, will default to the setting for host. DO NOT change this on a server that's already run!",
|
||||
Value: defaults.AccountDomain,
|
||||
EnvVars: []string{envNames.AccountDomain},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.Protocol,
|
||||
Usage: "Protocol to use for the REST api of the server (only use http for debugging and tests!)",
|
||||
Value: defaults.Protocol,
|
||||
EnvVars: []string{envNames.Protocol},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.BindAddress,
|
||||
Usage: "Bind address to use for the GoToSocial server (eg., 0.0.0.0, 172.138.0.9, [::], localhost). For ipv6, enclose the address in square brackets, eg [2001:db8::fed1]. Default binds to all interfaces.",
|
||||
Value: defaults.BindAddress,
|
||||
EnvVars: []string{envNames.BindAddress},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.Port,
|
||||
Usage: "Port to use for GoToSocial. Change this to 443 if you're running the binary directly on the host machine.",
|
||||
Value: defaults.Port,
|
||||
EnvVars: []string{envNames.Port},
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: flagNames.TrustedProxies,
|
||||
Usage: "Proxies to trust when parsing x-forwarded headers into real IPs.",
|
||||
Value: cli.NewStringSlice(defaults.TrustedProxies...),
|
||||
EnvVars: []string{envNames.TrustedProxies},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func letsEncryptFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: flagNames.LetsEncryptEnabled,
|
||||
Usage: "Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default).",
|
||||
Value: defaults.LetsEncryptEnabled,
|
||||
EnvVars: []string{envNames.LetsEncryptEnabled},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.LetsEncryptPort,
|
||||
Usage: "Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port.",
|
||||
Value: defaults.LetsEncryptPort,
|
||||
EnvVars: []string{envNames.LetsEncryptPort},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.LetsEncryptCertDir,
|
||||
Usage: "Directory to store acquired letsencrypt certificates.",
|
||||
Value: defaults.LetsEncryptCertDir,
|
||||
EnvVars: []string{envNames.LetsEncryptCertDir},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.LetsEncryptEmailAddress,
|
||||
Usage: "Email address to use when requesting letsencrypt certs. Will receive updates on cert expiry etc.",
|
||||
Value: defaults.LetsEncryptEmailAddress,
|
||||
EnvVars: []string{envNames.LetsEncryptEmailAddress},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -19,38 +19,59 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/flag"
|
||||
_ "github.com/superseriousbusiness/gotosocial/docs"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
)
|
||||
|
||||
// Version is the software version of GtS being used
|
||||
// Version is the software version of GtS being used.
|
||||
var Version string
|
||||
|
||||
// Commit is the git commit of GtS being used
|
||||
// Commit is the git commit of GtS being used.
|
||||
var Commit string
|
||||
|
||||
//go:generate swagger generate spec
|
||||
func main() {
|
||||
var v string
|
||||
if Commit == "" {
|
||||
if len(Commit) < 7 {
|
||||
v = Version
|
||||
} else {
|
||||
v = Version + " " + Commit[:7]
|
||||
}
|
||||
|
||||
flagsSlice := getFlags()
|
||||
app := &cli.App{
|
||||
Version: v,
|
||||
Usage: "a fediverse social media server",
|
||||
Flags: flagsSlice,
|
||||
Commands: getCommands(flagsSlice),
|
||||
// override software version in viper store
|
||||
viper.Set(config.Keys.SoftwareVersion, v)
|
||||
|
||||
// instantiate the root command
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "gotosocial",
|
||||
Short: "GoToSocial - a fediverse social media server",
|
||||
Long: "GoToSocial - a fediverse social media server\n\nFor help, see: https://docs.gotosocial.org.\n\nCode: https://github.com/superseriousbusiness/gotosocial",
|
||||
Version: v,
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
logrus.Fatal(err)
|
||||
// attach global flags to the root command so that they can be accessed from any subcommand
|
||||
flag.Global(rootCmd, config.Defaults)
|
||||
|
||||
// bind the config-path flag to viper early so that we can call it in the pre-run of following commands
|
||||
if err := viper.BindPFlag(config.Keys.ConfigPath, rootCmd.PersistentFlags().Lookup(config.Keys.ConfigPath)); err != nil {
|
||||
logrus.Fatalf("error attaching config flag: %s", err)
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
rootCmd.AddCommand(serverCommands())
|
||||
rootCmd.AddCommand(testrigCommands())
|
||||
rootCmd.AddCommand(debugCommands())
|
||||
rootCmd.AddCommand(adminCommands())
|
||||
|
||||
// run
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
logrus.Fatalf("error executing command: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func mediaFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.MediaMaxImageSize,
|
||||
Usage: "Max size of accepted images in bytes",
|
||||
Value: defaults.MediaMaxImageSize,
|
||||
EnvVars: []string{envNames.MediaMaxImageSize},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.MediaMaxVideoSize,
|
||||
Usage: "Max size of accepted videos in bytes",
|
||||
Value: defaults.MediaMaxVideoSize,
|
||||
EnvVars: []string{envNames.MediaMaxVideoSize},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.MediaMinDescriptionChars,
|
||||
Usage: "Min required chars for an image description",
|
||||
Value: defaults.MediaMinDescriptionChars,
|
||||
EnvVars: []string{envNames.MediaMinDescriptionChars},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.MediaMaxDescriptionChars,
|
||||
Usage: "Max permitted chars for an image description",
|
||||
Value: defaults.MediaMaxDescriptionChars,
|
||||
EnvVars: []string{envNames.MediaMaxDescriptionChars},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func oidcFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: flagNames.OIDCEnabled,
|
||||
Usage: "Enabled OIDC authorization for this instance. If set to true, then the other OIDC flags must also be set.",
|
||||
Value: defaults.OIDCEnabled,
|
||||
EnvVars: []string{envNames.OIDCEnabled},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.OIDCIdpName,
|
||||
Usage: "Name of the OIDC identity provider. Will be shown to the user when logging in.",
|
||||
Value: defaults.OIDCIdpName,
|
||||
EnvVars: []string{envNames.OIDCIdpName},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: flagNames.OIDCSkipVerification,
|
||||
Usage: "Skip verification of tokens returned by the OIDC provider. Should only be set to 'true' for testing purposes, never in a production environment!",
|
||||
Value: defaults.OIDCSkipVerification,
|
||||
EnvVars: []string{envNames.OIDCSkipVerification},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.OIDCIssuer,
|
||||
Usage: "Address of the OIDC issuer. Should be the web address, including protocol, at which the issuer can be reached. Eg., 'https://example.org/auth'",
|
||||
Value: defaults.OIDCIssuer,
|
||||
EnvVars: []string{envNames.OIDCIssuer},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.OIDCClientID,
|
||||
Usage: "ClientID of GoToSocial, as registered with the OIDC provider.",
|
||||
Value: defaults.OIDCClientID,
|
||||
EnvVars: []string{envNames.OIDCClientID},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.OIDCClientSecret,
|
||||
Usage: "ClientSecret of GoToSocial, as registered with the OIDC provider.",
|
||||
Value: defaults.OIDCClientSecret,
|
||||
EnvVars: []string{envNames.OIDCClientSecret},
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: flagNames.OIDCScopes,
|
||||
Usage: "ClientSecret of GoToSocial, as registered with the OIDC provider.",
|
||||
Value: cli.NewStringSlice(defaults.OIDCScopes...),
|
||||
EnvVars: []string{envNames.OIDCScopes},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/cliactions"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type MonkeyPatchedCLIContext struct {
|
||||
CLIContext *cli.Context
|
||||
AllFlags []cli.Flag
|
||||
}
|
||||
|
||||
func (f MonkeyPatchedCLIContext) Bool(k string) bool { return f.CLIContext.Bool(k) }
|
||||
func (f MonkeyPatchedCLIContext) String(k string) string { return f.CLIContext.String(k) }
|
||||
func (f MonkeyPatchedCLIContext) StringSlice(k string) []string { return f.CLIContext.StringSlice(k) }
|
||||
func (f MonkeyPatchedCLIContext) Int(k string) int { return f.CLIContext.Int(k) }
|
||||
func (f MonkeyPatchedCLIContext) IsSet(k string) bool {
|
||||
for _, flag := range f.AllFlags {
|
||||
flagNames := flag.Names()
|
||||
for _, name := range flagNames {
|
||||
if name == k {
|
||||
return flag.IsSet()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// runAction builds up the config and logger necessary for any
|
||||
// gotosocial action, and then executes the action.
|
||||
func runAction(c *cli.Context, allFlags []cli.Flag, a cliactions.GTSAction) error {
|
||||
|
||||
// create a new *config.Config based on the config path provided...
|
||||
conf, err := config.FromFile(c.String(config.GetFlagNames().ConfigPath))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating config: %s", err)
|
||||
}
|
||||
|
||||
// ... and the flags set on the *cli.Context by urfave
|
||||
//
|
||||
// The IsSet function on the cli.Context object `c` here appears to have some issues right now, it always returns false in my tests.
|
||||
// However we can re-create the behaviour we want by simply referencing the flag objects we created previously
|
||||
// https://picopublish.sequentialread.com/files/chatlog_2021_11_18.txt
|
||||
monkeyPatchedCLIContext := MonkeyPatchedCLIContext{
|
||||
CLIContext: c,
|
||||
AllFlags: allFlags,
|
||||
}
|
||||
if err := conf.ParseCLIFlags(monkeyPatchedCLIContext, c.App.Version); err != nil {
|
||||
return fmt.Errorf("error parsing config: %s", err)
|
||||
}
|
||||
|
||||
// initialize the global logger to the log level, with formatting and output splitter already set
|
||||
err = log.Initialize(conf.LogLevel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating logger: %s", err)
|
||||
}
|
||||
|
||||
return a(c.Context, conf)
|
||||
}
|
||||
|
|
@ -19,23 +19,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/server"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/flag"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func templateFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.TemplateBaseDir,
|
||||
Usage: "Basedir for html templating files for rendering pages and composing emails.",
|
||||
Value: defaults.TemplateBaseDir,
|
||||
EnvVars: []string{envNames.TemplateBaseDir},
|
||||
// serverCommands returns the 'server' subcommand
|
||||
func serverCommands() *cobra.Command {
|
||||
serverCmd := &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "gotosocial server-related tasks",
|
||||
}
|
||||
|
||||
serverStartCmd := &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "start the gotosocial server",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return preRun(cmd)
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.AssetBaseDir,
|
||||
Usage: "Directory to serve static assets from, accessible at example.com/assets/",
|
||||
Value: defaults.AssetBaseDir,
|
||||
EnvVars: []string{envNames.AssetBaseDir},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), server.Start)
|
||||
},
|
||||
}
|
||||
flag.Server(serverStartCmd, config.Defaults)
|
||||
|
||||
serverCmd.AddCommand(serverStartCmd)
|
||||
return serverCmd
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func smtpFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.SMTPHost,
|
||||
Usage: "Host of the smtp server. Eg., 'smtp.eu.mailgun.org'",
|
||||
Value: defaults.SMTPHost,
|
||||
EnvVars: []string{envNames.SMTPHost},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.SMTPPort,
|
||||
Usage: "Port of the smtp server. Eg., 587",
|
||||
Value: defaults.SMTPPort,
|
||||
EnvVars: []string{envNames.SMTPPort},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.SMTPUsername,
|
||||
Usage: "Username to authenticate with the smtp server as. Eg., 'postmaster@mail.example.org'",
|
||||
Value: defaults.SMTPUsername,
|
||||
EnvVars: []string{envNames.SMTPUsername},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.SMTPPassword,
|
||||
Usage: "Password to pass to the smtp server.",
|
||||
Value: defaults.SMTPPassword,
|
||||
EnvVars: []string{envNames.SMTPPassword},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.SMTPFrom,
|
||||
Usage: "Address to use as the 'from' field of the email. Eg., 'gotosocial@example.org'",
|
||||
Value: defaults.SMTPFrom,
|
||||
EnvVars: []string{envNames.SMTPFrom},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func statusesFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.StatusesMaxChars,
|
||||
Usage: "Max permitted characters for posted statuses",
|
||||
Value: defaults.StatusesMaxChars,
|
||||
EnvVars: []string{envNames.StatusesMaxChars},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.StatusesCWMaxChars,
|
||||
Usage: "Max permitted characters for content/spoiler warnings on statuses",
|
||||
Value: defaults.StatusesCWMaxChars,
|
||||
EnvVars: []string{envNames.StatusesCWMaxChars},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.StatusesPollMaxOptions,
|
||||
Usage: "Max amount of options permitted on a poll",
|
||||
Value: defaults.StatusesPollMaxOptions,
|
||||
EnvVars: []string{envNames.StatusesPollMaxOptions},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.StatusesPollOptionMaxChars,
|
||||
Usage: "Max amount of characters for a poll option",
|
||||
Value: defaults.StatusesPollOptionMaxChars,
|
||||
EnvVars: []string{envNames.StatusesPollOptionMaxChars},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: flagNames.StatusesMaxMediaFiles,
|
||||
Usage: "Maximum number of media files/attachments per status",
|
||||
Value: defaults.StatusesMaxMediaFiles,
|
||||
EnvVars: []string{envNames.StatusesMaxMediaFiles},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func storageFlags(flagNames, envNames config.Flags, defaults config.Defaults) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.StorageBackend,
|
||||
Usage: "Storage backend to use for media attachments",
|
||||
Value: defaults.StorageBackend,
|
||||
EnvVars: []string{envNames.StorageBackend},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.StorageBasePath,
|
||||
Usage: "Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir.",
|
||||
Value: defaults.StorageBasePath,
|
||||
EnvVars: []string{envNames.StorageBasePath},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.StorageServeProtocol,
|
||||
Usage: "Protocol to use for serving media attachments (use https if storage is local)",
|
||||
Value: defaults.StorageServeProtocol,
|
||||
EnvVars: []string{envNames.StorageServeProtocol},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.StorageServeHost,
|
||||
Usage: "Hostname to serve media attachments from (use the same value as host if storage is local)",
|
||||
Value: defaults.StorageServeHost,
|
||||
EnvVars: []string{envNames.StorageServeHost},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: flagNames.StorageServeBasePath,
|
||||
Usage: "Path to append to protocol and hostname to create the base path from which media files will be served (default will mostly be fine)",
|
||||
Value: defaults.StorageServeBasePath,
|
||||
EnvVars: []string{envNames.StorageServeBasePath},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -19,24 +19,24 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/cliactions/server"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/testrig"
|
||||
)
|
||||
|
||||
func serverCommands(allFlags []cli.Flag) []*cli.Command {
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "server",
|
||||
Usage: "gotosocial server-related tasks",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "start",
|
||||
Usage: "start the gotosocial server",
|
||||
Action: func(c *cli.Context) error {
|
||||
return runAction(c, allFlags, server.Start)
|
||||
},
|
||||
},
|
||||
},
|
||||
func testrigCommands() *cobra.Command {
|
||||
testrigCmd := &cobra.Command{
|
||||
Use: "testrig",
|
||||
Short: "gotosocial testrig-related tasks",
|
||||
}
|
||||
|
||||
testrigStartCmd := &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "start the gotosocial testrig server",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return run(cmd.Context(), testrig.Start)
|
||||
},
|
||||
}
|
||||
|
||||
testrigCmd.AddCommand(testrigStartCmd)
|
||||
return testrigCmd
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue