feat: implemented initial login command

This commit is contained in:
Stevan Freeborn
2026-07-31 08:06:29 -05:00
commit 55a4a1285d
8 changed files with 252 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
package command
import (
"fmt"
"github.com/StevanFreeborn/gator/internal/state"
)
type Command struct {
Name string
Handler CommandHandler
}
type CommandHandler func(s *state.State) error
func newCommand(name string, handler CommandHandler) *Command {
return &Command{
Name: name,
Handler: handler,
}
}
type CommandRegistry struct {
commands map[string]*Command
}
func (c *CommandRegistry) register(cmd *Command) error {
c.commands[cmd.Name] = cmd
return nil
}
func NewRegistry() *CommandRegistry {
cr := CommandRegistry{
commands: map[string]*Command{},
}
commands := []*Command{
loginCommand(),
}
for _, cmd := range commands {
cr.register(cmd)
}
return &cr
}
func (c *CommandRegistry) RunCommand(cmdName string, s *state.State) error {
cmd, found := c.commands[cmdName]
if !found {
return fmt.Errorf("No '%s' registered", cmdName)
}
return cmd.Handler(s)
}
func loginCommand() *Command {
return newCommand("login", func(s *state.State) error {
if len(s.Arguments) == 0 {
return fmt.Errorf("Did not receive expected username argument")
}
username := s.Arguments[0]
err := s.Config.SetUser(username)
if err != nil {
return err
}
fmt.Printf("Current user set to '%s'\n", username)
return nil
})
}
+92
View File
@@ -0,0 +1,92 @@
package config
import (
"encoding/json"
"fmt"
"os"
"path"
)
const GATOR_CONFIG_FILE = ".gatorconfig.json"
type Config struct {
DbUrl string `json:"db_url"`
CurrentUserName string `json:"current_user_name"`
}
func Read() (*Config, error) {
config := Config{}
configFilePath, err := getConfigPath()
if err != nil {
return nil, err
}
data, err := os.ReadFile(configFilePath)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, &config)
if err != nil {
return nil, err
}
return &config, nil
}
// TODO: I don't think there should be
// hidden I/O in this method call
func (c *Config) SetUser(currentUserName string) error {
c.CurrentUserName = currentUserName
return writeFile(c)
}
func (c *Config) String() string {
return fmt.Sprintf("Config { DbUrl = %s, CurrentUserName = %s }", c.DbUrl, c.CurrentUserName)
}
func writeFile(config *Config) error {
data, err := json.Marshal(config)
if err != nil {
return err
}
configFilePath, err := getConfigPath()
if err != nil {
return err
}
file, err := os.Create(configFilePath)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return err
}
return nil
}
func getConfigPath() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
configFilePath := path.Join(homeDir, GATOR_CONFIG_FILE)
return configFilePath, nil
}
+12
View File
@@ -0,0 +1,12 @@
package state
import "github.com/StevanFreeborn/gator/internal/config"
type State struct {
Config *config.Config
Arguments []string
}
func NewState(c *config.Config, args []string) *State {
return &State{Config: c, Arguments: args}
}