From 6a1fcbcf320d282659f475b5f5ca75eb929bc22a Mon Sep 17 00:00:00 2001 From: vilmibm Date: Sat, 4 Mar 2023 00:51:40 +0000 Subject: [PATCH] add welcome message --- cmd/welcome/main.go | 189 ++++++++------------------------------------ 1 file changed, 31 insertions(+), 158 deletions(-) diff --git a/cmd/welcome/main.go b/cmd/welcome/main.go index a4f44b4..5b793fe 100644 --- a/cmd/welcome/main.go +++ b/cmd/welcome/main.go @@ -4,26 +4,22 @@ import ( "bytes" "errors" "fmt" - "net/mail" "os" "os/exec" - "regexp" - "strings" "git.tilde.town/tildetown/town/invites" - "git.tilde.town/tildetown/town/sshkey" "git.tilde.town/tildetown/town/stats" - "github.com/AlecAivazis/survey/v2" "github.com/charmbracelet/lipgloss" _ "embed" ) +// TODO move magic key machine to static page +// TODO link to code of conduct as part of the form and ask if they agree + //go:embed welcome.txt var welcomeArt string -// TODO move magic key machine to static page - type newUserData struct { Username string DisplayName string @@ -31,148 +27,12 @@ type newUserData struct { PubKey string } -func surveyIconSet(icons *survey.IconSet) { - icons.Question.Text = "~" - icons.Question.Format = "magenta:b" -} - -func promptCode() (code string, err error) { - err = survey.AskOne(&survey.Input{ - Message: "invite code?", - }, &code, - survey.WithValidator(survey.Required), - survey.WithIcons(surveyIconSet)) - code = strings.TrimSpace(code) - return -} - -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?", - Default: a.UserData.Username, - }, &a.UserData.Username, - survey.WithValidator(survey.Required), - survey.WithIcons(surveyIconSet), - survey.WithValidator(func(val interface{}) error { - un := val.(string) - if len(un) > 32 { - return fmt.Errorf("username '%s' is too long", un) - } - return nil - }), - survey.WithValidator(func(val interface{}) error { - un := val.(string) - 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 a.TownData.Users { - if v.Username == un { - return fmt.Errorf("username '%s' is already in use", un) - } - } - return nil - })) - - return -} - -func (a *asker) promptEmail() (err error) { - err = survey.AskOne( - &survey.Input{ - Message: "e-mail (for account recovery only)?", - Default: a.UserData.Email, - }, &a.UserData.Email, - survey.WithValidator(survey.Required), - survey.WithIcons(surveyIconSet), - survey.WithValidator(func(val interface{}) error { - email := val.(string) - _, err := mail.ParseAddress(email) - if err != nil { - return fmt.Errorf("'%s' doesn't look like an email: %w", email, err) - } - - if !strings.Contains(email, ".") { - return fmt.Errorf("'%s' doesn't look like an email: domain not fully qualified", email) - } - - return nil - })) - - return -} - -func (a *asker) promptKey() (err error) { - err = survey.AskOne( - &survey.Input{ - Message: "SSH public key?", - Default: a.UserData.PubKey, - }, &a.UserData.PubKey, - survey.WithValidator(survey.Required), - survey.WithIcons(surveyIconSet), - survey.WithValidator(func(v interface{}) error { - key := v.(string) - valid, err := sshkey.ValidKey(key) - 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 - })) - - return +func defaultStyle() lipgloss.Style { + return lipgloss.NewStyle(). + Foreground(lipgloss.AdaptiveColor{ + Light: "#7D19BD", + Dark: "#E0B0FF", + }) } func _main() error { @@ -181,13 +41,7 @@ func _main() error { return err } - s := lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{ - Light: "#7D19BD", - Dark: "#E0B0FF", - }) - - s = s.SetString(welcomeArt) + s := defaultStyle().SetString(welcomeArt) fmt.Println(s) code, err := promptCode() @@ -220,7 +74,7 @@ func _main() error { UserData: data, Invite: *invite, TownData: townData, - Style: s, + Style: defaultStyle(), } if err = a.Ask(); err != nil { @@ -252,11 +106,30 @@ Please email root@tilde.town and paste the following error: %s -Your invite code has not been marked as used and you're welcome to try again, though if there is a system issue you might need to wait for word from an admin.`, err.Error())) +Your invite code has not been marked as used and you're welcome to try again, +though if there is a system issue you might need to wait for word from an admin.`, err.Error())) fmt.Println(s) return nil } + s = s.SetString(fmt.Sprintf(`OK! your user account has been created. + +welcome, ~%[1]s <3 + +This program is going to exit and you are now free to ssh to town as yourself: + + ssh %[1]s@tilde.town + +if your public key isn't found by ssh, you'll need to explain to ssh how to find it with: + + ssh -i "replace with path to public key file" %[1]s@tilde.town + +for help with ssh, see: https://tilde.town/wiki/getting-started/ssh.html + +if you end up very stuck, you can email root@tilde.town .`, data.Username)) + + fmt.Println(s) + // TODO mark invite as used // TODO add user to town.db