forked from keybase/client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cmd_login.go
137 lines (122 loc) · 3.52 KB
/
cmd_login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package client
import (
"errors"
"time"
"golang.org/x/net/context"
"github.com/keybase/cli"
"github.com/keybase/client/go/libcmdline"
"github.com/keybase/client/go/libkb"
keybase1 "github.com/keybase/client/go/protocol"
rpc "github.com/keybase/go-framed-msgpack-rpc"
)
func NewCmdLogin(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
cmd := cli.Command{
Name: "login",
ArgumentHelp: "[username]",
Usage: "Establish a session with the keybase server",
Action: func(c *cli.Context) {
cl.ChooseCommand(NewCmdLoginRunner(g), "login", c)
},
}
// Note we'll only be able to set this via mode via Environment variable
// since it's too early to check command-line setting of it.
if g.Env.GetRunMode() == libkb.DevelRunMode {
cmd.Flags = append(cmd.Flags, cli.BoolFlag{
Name: "emulate-gui",
Usage: "emulate GUI signing and fork GPG from the service",
})
}
return cmd
}
type CmdLogin struct {
libkb.Contextified
username string
clientType keybase1.ClientType
cancel func()
done chan struct{}
}
func NewCmdLoginRunner(g *libkb.GlobalContext) *CmdLogin {
return &CmdLogin{
Contextified: libkb.NewContextified(g),
clientType: keybase1.ClientType_CLI,
done: make(chan struct{}, 1),
}
}
func (c *CmdLogin) Run() error {
protocols := []rpc.Protocol{
NewProvisionUIProtocol(c.G(), libkb.KexRoleProvisionee),
NewLoginUIProtocol(c.G()),
NewSecretUIProtocol(c.G()),
NewGPGUIProtocol(c.G()),
}
if err := RegisterProtocolsWithContext(protocols, c.G()); err != nil {
return err
}
client, err := GetLoginClient(c.G())
if err != nil {
return err
}
// TODO: it would be nice to move this up a level and have keybase/main.go create
// a context and pass it to Command.Run(), then it can handle cancel itself
// instead of using Command.Cancel().
ctx, cancel := context.WithCancel(context.Background())
c.cancel = cancel
defer func() {
c.cancel()
c.cancel = nil
}()
err = client.Login(ctx,
keybase1.LoginArg{
Username: c.username,
DeviceType: libkb.DeviceTypeDesktop,
ClientType: c.clientType,
})
c.done <- struct{}{}
return err
}
func (c *CmdLogin) ParseArgv(ctx *cli.Context) error {
nargs := len(ctx.Args())
if nargs > 1 {
return errors.New("Invalid arguments.")
}
if nargs == 1 {
c.username = ctx.Args()[0]
if libkb.CheckEmail.F(c.username) {
return errors.New("Please login again via `keybase login [username]`")
}
if !libkb.CheckUsername.F(c.username) {
return errors.New("Invalid username format. Please login again via `keybase login [username]`")
}
}
if ctx.Bool("emulate-gui") {
c.clientType = keybase1.ClientType_GUI
}
return nil
}
func (c *CmdLogin) GetUsage() libkb.Usage {
return libkb.Usage{
Config: true,
KbKeyring: true,
API: true,
}
}
func (c *CmdLogin) Cancel() error {
c.G().Log.Debug("received request to cancel running login command")
if c.cancel != nil {
c.G().Log.Debug("command cancel function exists, calling it")
c.cancel()
// In go-framed-msgpack-rpc, dispatch.handleCall() starts a goroutine to check the context being
// canceled.
// So, need to wait here for call to actually finish in order for the cancel message to make it
// to the daemon.
select {
case <-c.done:
c.G().Log.Debug("command finished, cancel complete")
case <-time.After(5 * time.Second):
c.G().Log.Debug("timed out waiting for command to finish")
}
}
return nil
}