1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4// loginLoadUser is an engine that will get a username or email
5// address from the user and load that user, for the purposes of
6// preparing for provisioning a new device.
7//
8// It is only meant to be used by the Login engine.
9
10package engine
11
12import (
13	"strings"
14
15	"github.com/keybase/client/go/libkb"
16)
17
18// loginLoadUser is an engine.
19type loginLoadUser struct {
20	libkb.Contextified
21	user     *libkb.User
22	username string
23}
24
25// newLoginLoadUser creates a loginLoadUser engine. `username` argument is
26// optional.
27func newLoginLoadUser(g *libkb.GlobalContext, username string) *loginLoadUser {
28	return &loginLoadUser{
29		Contextified: libkb.NewContextified(g),
30		username:     strings.TrimSpace(username),
31	}
32}
33
34// Name is the unique engine name.
35func (e *loginLoadUser) Name() string {
36	return "loginLoadUser"
37}
38
39// GetPrereqs returns the engine prereqs.
40func (e *loginLoadUser) Prereqs() Prereqs {
41	return Prereqs{}
42}
43
44// RequiredUIs returns the required UIs.
45func (e *loginLoadUser) RequiredUIs() []libkb.UIKind {
46	return []libkb.UIKind{
47		libkb.LoginUIKind,
48		libkb.SecretUIKind,
49	}
50}
51
52// SubConsumers returns the other UI consumers for this engine.
53func (e *loginLoadUser) SubConsumers() []libkb.UIConsumer {
54	return nil
55}
56
57// Run starts the engine.
58func (e *loginLoadUser) Run(m libkb.MetaContext) (err error) {
59	defer m.Trace("loginLoadUser#Run", &err)()
60
61	var username string
62	username, err = e.findUsername(m)
63	if err != nil {
64		return err
65	}
66
67	m.Debug("loginLoadUser: found username %q", username)
68
69	// NOTE(max) 2018-05-09: ForceReload since older versions of cached users don't
70	// have salt stored, ad we need it in DeviceWrap to write out the config file.
71	arg := libkb.NewLoadUserArgWithMetaContext(m).WithName(username).WithPublicKeyOptional().WithForceReload()
72	user, err := libkb.LoadUser(arg)
73	if err != nil {
74		return err
75	}
76	e.user = user
77
78	m.Debug("loginLoadUser: found user %s for username %q", e.user.GetUID(), username)
79
80	return nil
81}
82
83func (e *loginLoadUser) User() *libkb.User {
84	return e.user
85}
86
87func (e *loginLoadUser) findUsername(m libkb.MetaContext) (string, error) {
88	if len(e.username) == 0 {
89		if err := e.prompt(m); err != nil {
90			return "", err
91		}
92	}
93
94	if len(e.username) == 0 {
95		return "", libkb.NoUsernameError{}
96	}
97
98	if !libkb.CheckUsername.F(e.username) {
99		// Username is not valid:
100		if libkb.CheckEmail.F(e.username) {
101			// It's an e-mail, that we don't support anymore (CORE-10470).
102			return "", libkb.NewBadUsernameErrorWithFullMessage("Logging in with e-mail address is not supported")
103		}
104		return "", libkb.NewBadUsernameError(e.username)
105	}
106
107	return e.username, nil
108}
109
110func (e *loginLoadUser) prompt(m libkb.MetaContext) error {
111	res, err := m.UIs().LoginUI.GetEmailOrUsername(m.Ctx(), 0)
112	if err != nil {
113		return err
114	}
115	e.username = res
116	return nil
117}
118