200 lines
4.3 KiB
Go
200 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"go.jolheiser.com/cabinet/internal/gc"
|
|
"go.jolheiser.com/cabinet/internal/router"
|
|
"go.jolheiser.com/cabinet/internal/workspace"
|
|
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type serveOpts struct {
|
|
jsonMode bool
|
|
debugMode bool
|
|
maxFileSize int
|
|
maxDiskSize int
|
|
workspacePath string
|
|
gcInterval time.Duration
|
|
requestPerMinute int
|
|
sizePerMinute int
|
|
burstSize int
|
|
memPerRequest int
|
|
port int
|
|
domain string
|
|
}
|
|
|
|
var serveCmd = func(opts *serveOpts) func(context.Context, []string) error {
|
|
return func(_ context.Context, _ []string) error {
|
|
if opts.jsonMode {
|
|
log.Logger = zerolog.New(os.Stderr).With().Timestamp().Logger()
|
|
}
|
|
if opts.debugMode {
|
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
}
|
|
|
|
if opts.domain == "" {
|
|
opts.domain = fmt.Sprintf("http://localhost:%d", opts.port)
|
|
}
|
|
|
|
ws, err := workspace.New(opts.workspacePath)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("could not open workspace")
|
|
}
|
|
|
|
go gc.Start(ws, opts.maxDiskSize, opts.gcInterval)
|
|
|
|
r := router.New(opts.domain, ws, router.NewLimit(opts.requestPerMinute, opts.sizePerMinute, opts.burstSize, opts.memPerRequest))
|
|
|
|
portStr := fmt.Sprintf(":%d", opts.port)
|
|
log.Info().Msgf("Listening at %s", opts.domain)
|
|
if err := http.ListenAndServe(portStr, r); err != nil {
|
|
log.Err(err).Msg("could not start HTTP server")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
type tokenOpts struct {
|
|
token string
|
|
perm workspace.TokenPermission
|
|
desc string
|
|
workspacePath string
|
|
delete bool
|
|
}
|
|
|
|
var tokenCmd = func(opts *tokenOpts) func(context.Context, []string) error {
|
|
return func(_ context.Context, _ []string) error {
|
|
ws, err := workspace.New(opts.workspacePath)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("could not open workspace")
|
|
}
|
|
|
|
if opts.delete {
|
|
return deleteTokens(ws, opts)
|
|
}
|
|
return addToken(ws, opts)
|
|
}
|
|
}
|
|
|
|
func addToken(ws *workspace.Workspace, opts *tokenOpts) error {
|
|
token := opts.token
|
|
if token == "" {
|
|
r, err := randToken()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
q := &survey.Input{
|
|
Message: "Token",
|
|
Default: r,
|
|
Help: "Input token or use randomly generated",
|
|
}
|
|
if err := survey.AskOne(q, &token, survey.WithValidator(survey.Required)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
perm := opts.perm
|
|
if perm == 0 {
|
|
q := &survey.Select{
|
|
Message: "Permission",
|
|
Default: "all",
|
|
Help: "Token permission",
|
|
Options: []string{
|
|
"all",
|
|
"redirect",
|
|
"file",
|
|
},
|
|
}
|
|
var p string
|
|
err := survey.AskOne(q, &p, survey.WithValidator(survey.Required))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
perm, err = workspace.ParseTokenPermission(p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
desc := opts.desc
|
|
if desc == "" {
|
|
q := &survey.Input{
|
|
Message: "Description",
|
|
Default: "",
|
|
Help: "Description of the token usage/user",
|
|
}
|
|
if err := survey.AskOne(q, &desc, survey.WithValidator(survey.Required)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := ws.AddToken(workspace.Token{
|
|
Key: token,
|
|
Permission: perm,
|
|
Description: desc,
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info().Msg(token)
|
|
return nil
|
|
}
|
|
|
|
func deleteTokens(ws *workspace.Workspace, opts *tokenOpts) error {
|
|
if opts.token != "" {
|
|
if err := ws.DeleteTokens(opts.token); err != nil {
|
|
return err
|
|
}
|
|
log.Info().Msgf("Successfully deleted %q", opts.token)
|
|
return nil
|
|
}
|
|
|
|
tokens, err := ws.Tokens()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(tokens) == 0 {
|
|
log.Info().Msg("This instance has no tokens")
|
|
return nil
|
|
}
|
|
|
|
var tokenSlice []string
|
|
tokenMap := make(map[string]string)
|
|
for _, token := range tokens {
|
|
k := fmt.Sprintf("%s (%s) -- %s", token.Key, token.Permission, token.Description)
|
|
tokenSlice = append(tokenSlice, k)
|
|
tokenMap[k] = token.Key
|
|
}
|
|
|
|
q := &survey.MultiSelect{
|
|
Message: "Token(s) to delete",
|
|
Options: tokenSlice,
|
|
Help: "Select any tokens you wish to remove",
|
|
}
|
|
var selections []string
|
|
if err := survey.AskOne(q, &selections); err != nil {
|
|
return err
|
|
}
|
|
|
|
var keys []string
|
|
for _, selection := range selections {
|
|
keys = append(keys, tokenMap[selection])
|
|
}
|
|
|
|
if err := ws.DeleteTokens(keys...); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info().Msgf("Successfully deleted %d token(s)", len(keys))
|
|
return nil
|
|
}
|