finish form part, next make user account
parent
f28da14d98
commit
28ac63f256
|
@ -44,13 +44,58 @@ func promptCode() (code string, err error) {
|
||||||
return
|
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
|
// copied from /etc/adduser.conf
|
||||||
usernameRE := regexp.MustCompile(`^[a-z][-a-z0-9_]*$`)
|
usernameRE := regexp.MustCompile(`^[a-z][-a-z0-9_]*$`)
|
||||||
err = survey.AskOne(
|
err = survey.AskOne(
|
||||||
&survey.Input{
|
&survey.Input{
|
||||||
Message: "desired username?",
|
Message: "desired username?",
|
||||||
}, &un,
|
Default: a.UserData.Username,
|
||||||
|
}, &a.UserData.Username,
|
||||||
survey.WithValidator(survey.Required),
|
survey.WithValidator(survey.Required),
|
||||||
survey.WithIcons(surveyIconSet),
|
survey.WithIcons(surveyIconSet),
|
||||||
survey.WithValidator(func(val interface{}) error {
|
survey.WithValidator(func(val interface{}) error {
|
||||||
|
@ -58,7 +103,6 @@ func promptUsername(townData stats.TildeData) (un string, err error) {
|
||||||
if len(un) > 32 {
|
if len(un) > 32 {
|
||||||
return fmt.Errorf("username '%s' is too long", un)
|
return fmt.Errorf("username '%s' is too long", un)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}),
|
}),
|
||||||
survey.WithValidator(func(val interface{}) error {
|
survey.WithValidator(func(val interface{}) error {
|
||||||
|
@ -66,12 +110,11 @@ func promptUsername(townData stats.TildeData) (un string, err error) {
|
||||||
if !usernameRE.MatchString(un) {
|
if !usernameRE.MatchString(un) {
|
||||||
return errors.New("usernames must start with a letter and only contain letters, nubers, - or _")
|
return errors.New("usernames must start with a letter and only contain letters, nubers, - or _")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}),
|
}),
|
||||||
survey.WithValidator(func(val interface{}) error {
|
survey.WithValidator(func(val interface{}) error {
|
||||||
un := val.(string)
|
un := val.(string)
|
||||||
for _, v := range townData.Users {
|
for _, v := range a.TownData.Users {
|
||||||
if v.Username == un {
|
if v.Username == un {
|
||||||
return fmt.Errorf("username '%s' is already in use", 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 "", nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func promptEmail(defaultEmail string) (email string, err error) {
|
func (a *asker) promptEmail() (err error) {
|
||||||
err = survey.AskOne(
|
err = survey.AskOne(
|
||||||
&survey.Input{
|
&survey.Input{
|
||||||
Message: "e-mail (for account recovery only)?",
|
Message: "e-mail (for account recovery only)?",
|
||||||
Default: defaultEmail,
|
Default: a.UserData.Email,
|
||||||
}, &email,
|
}, &a.UserData.Email,
|
||||||
survey.WithValidator(survey.Required),
|
survey.WithValidator(survey.Required),
|
||||||
survey.WithIcons(surveyIconSet),
|
survey.WithIcons(surveyIconSet),
|
||||||
survey.WithValidator(func(val interface{}) error {
|
survey.WithValidator(func(val interface{}) error {
|
||||||
|
@ -104,14 +147,15 @@ func promptEmail(defaultEmail string) (email string, err error) {
|
||||||
return nil
|
return nil
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return "", nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func promptKey() (key string, err error) {
|
func (a *asker) promptKey() (err error) {
|
||||||
err = survey.AskOne(
|
err = survey.AskOne(
|
||||||
&survey.Input{
|
&survey.Input{
|
||||||
Message: "SSH public key?",
|
Message: "SSH public key?",
|
||||||
}, &key,
|
Default: a.UserData.PubKey,
|
||||||
|
}, &a.UserData.PubKey,
|
||||||
survey.WithValidator(survey.Required),
|
survey.WithValidator(survey.Required),
|
||||||
survey.WithIcons(surveyIconSet),
|
survey.WithIcons(surveyIconSet),
|
||||||
survey.WithValidator(func(v interface{}) error {
|
survey.WithValidator(func(v interface{}) error {
|
||||||
|
@ -120,11 +164,9 @@ func promptKey() (key string, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to validate key: %w", err)
|
return fmt.Errorf("failed to validate key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !valid {
|
if !valid {
|
||||||
return errors.New("that doesn't seem like a valid SSH key. try another public key?")
|
return errors.New("that doesn't seem like a valid SSH key. try another public key?")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -132,18 +174,11 @@ func promptKey() (key string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _main() error {
|
func _main() error {
|
||||||
townData, err := stats.Stats()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
inviteDB, err := invites.ConnectDB()
|
inviteDB, err := invites.ConnectDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := &newUserData{}
|
|
||||||
|
|
||||||
s := lipgloss.NewStyle().
|
s := lipgloss.NewStyle().
|
||||||
Foreground(lipgloss.AdaptiveColor{
|
Foreground(lipgloss.AdaptiveColor{
|
||||||
Light: "#7D19BD",
|
Light: "#7D19BD",
|
||||||
|
@ -171,22 +206,43 @@ func _main() error {
|
||||||
|
|
||||||
fmt.Println(s)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Email, err = promptEmail(invite.Email)
|
if !conf {
|
||||||
if err != nil {
|
for !conf {
|
||||||
|
if err = a.Ask(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if conf, err = confirmContinue(); err != nil {
|
||||||
data.PubKey, err = promptKey()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
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 have enough to make account; can now do that
|
||||||
// TODO assuming account creation succeeded, mark invite as used
|
// TODO assuming account creation succeeded, mark invite as used
|
||||||
|
|
|
@ -16,6 +16,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO FIX LOGGING TO STDOUT (move this to the cmd)
|
||||||
|
|
||||||
const defaultIndexPath = "/etc/skel/public_html/index.html"
|
const defaultIndexPath = "/etc/skel/public_html/index.html"
|
||||||
const description = `an intentional digital community for creating and sharing
|
const description = `an intentional digital community for creating and sharing
|
||||||
works of art, peer education, and technological anachronism. we are
|
works of art, peer education, and technological anachronism. we are
|
||||||
|
|
Loading…
Reference in New Issue