diff --git a/cmd/welcome/main.go b/cmd/welcome/main.go index 6b39555..24e0baf 100644 --- a/cmd/welcome/main.go +++ b/cmd/welcome/main.go @@ -44,13 +44,58 @@ func promptCode() (code string, err error) { return } -func promptUsername(townData stats.TildeData) (un string, err error) { +func confirmContinue() (conf bool, err error) { + err = survey.AskOne( + &survey.Confirm{ + Message: "Does the above look ok?", + }, &conf, + survey.WithValidator(survey.Required), + survey.WithIcons(surveyIconSet)) + return +} + +type asker struct { + UserData *newUserData + Style lipgloss.Style + Invite invites.Invite + TownData stats.TildeData +} + +func (a *asker) Ask() (err error) { + // TODO somehow un and email getting set to "" but pubkey works fine? + + if err = a.promptUsername(); err != nil { + return err + } + + if err = a.promptEmail(); err != nil { + return err + } + + if err = a.promptKey(); err != nil { + return err + } + + s := a.Style.SetString( + fmt.Sprintf(`ok! your account is about to be created with the following details: + +username: %s +email: %s +pubkey: %s`, a.UserData.Username, a.UserData.Email, a.UserData.PubKey)).Bold(true).MaxWidth(80) + + fmt.Println(s) + + return nil +} + +func (a *asker) promptUsername() (err error) { // copied from /etc/adduser.conf usernameRE := regexp.MustCompile(`^[a-z][-a-z0-9_]*$`) err = survey.AskOne( &survey.Input{ Message: "desired username?", - }, &un, + Default: a.UserData.Username, + }, &a.UserData.Username, survey.WithValidator(survey.Required), survey.WithIcons(surveyIconSet), survey.WithValidator(func(val interface{}) error { @@ -58,7 +103,6 @@ func promptUsername(townData stats.TildeData) (un string, err error) { if len(un) > 32 { return fmt.Errorf("username '%s' is too long", un) } - return nil }), survey.WithValidator(func(val interface{}) error { @@ -66,12 +110,11 @@ func promptUsername(townData stats.TildeData) (un string, err error) { if !usernameRE.MatchString(un) { return errors.New("usernames must start with a letter and only contain letters, nubers, - or _") } - return nil }), survey.WithValidator(func(val interface{}) error { un := val.(string) - for _, v := range townData.Users { + for _, v := range a.TownData.Users { if v.Username == un { return fmt.Errorf("username '%s' is already in use", un) } @@ -79,15 +122,15 @@ func promptUsername(townData stats.TildeData) (un string, err error) { return nil })) - return "", nil + return } -func promptEmail(defaultEmail string) (email string, err error) { +func (a *asker) promptEmail() (err error) { err = survey.AskOne( &survey.Input{ Message: "e-mail (for account recovery only)?", - Default: defaultEmail, - }, &email, + Default: a.UserData.Email, + }, &a.UserData.Email, survey.WithValidator(survey.Required), survey.WithIcons(surveyIconSet), survey.WithValidator(func(val interface{}) error { @@ -104,14 +147,15 @@ func promptEmail(defaultEmail string) (email string, err error) { return nil })) - return "", nil + return } -func promptKey() (key string, err error) { +func (a *asker) promptKey() (err error) { err = survey.AskOne( &survey.Input{ Message: "SSH public key?", - }, &key, + Default: a.UserData.PubKey, + }, &a.UserData.PubKey, survey.WithValidator(survey.Required), survey.WithIcons(surveyIconSet), survey.WithValidator(func(v interface{}) error { @@ -120,11 +164,9 @@ func promptKey() (key string, err error) { if err != nil { return fmt.Errorf("failed to validate key: %w", err) } - if !valid { return errors.New("that doesn't seem like a valid SSH key. try another public key?") } - return nil })) @@ -132,18 +174,11 @@ func promptKey() (key string, err error) { } func _main() error { - townData, err := stats.Stats() - if err != nil { - return err - } - inviteDB, err := invites.ConnectDB() if err != nil { return err } - data := &newUserData{} - s := lipgloss.NewStyle(). Foreground(lipgloss.AdaptiveColor{ Light: "#7D19BD", @@ -171,22 +206,43 @@ func _main() error { fmt.Println(s) - data.Username, err = promptUsername(townData) + townData, err := stats.Stats() + if err != nil { + return err + } + data := &newUserData{ + Email: invite.Email, + } + + a := &asker{ + UserData: data, + Invite: *invite, + TownData: townData, + Style: s, + } + + if err = a.Ask(); err != nil { + return err + } + + conf, err := confirmContinue() if err != nil { return err } - data.Email, err = promptEmail(invite.Email) - if err != nil { - return err + if !conf { + for !conf { + if err = a.Ask(); err != nil { + return err + } + if conf, err = confirmContinue(); err != nil { + return err + } + } } - data.PubKey, err = promptKey() - if err != nil { - return err - } - - // TODO should I allow a review+edit step? + s = s.SetString("cool, awesome, going to make your account now...") + fmt.Println(s) // TODO have enough to make account; can now do that // TODO assuming account creation succeeded, mark invite as used diff --git a/stats/stats.go b/stats/stats.go index 24290d5..41f01d0 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -16,6 +16,8 @@ import ( "time" ) +// TODO FIX LOGGING TO STDOUT (move this to the cmd) + const defaultIndexPath = "/etc/skel/public_html/index.html" const description = `an intentional digital community for creating and sharing works of art, peer education, and technological anachronism. we are