@@ -17,10 +17,20 @@ import (
1717 "gitlab.com/gitlab-org/gitlab-shell/v14/internal/gitlabnet/twofactorverify"
1818)
1919
20+ type blockingReader struct {}
21+
22+ func (* blockingReader ) Read ([]byte ) (int , error ) {
23+ waitInfinitely := make (chan struct {})
24+ <- waitInfinitely
25+
26+ return 0 , nil
27+ }
28+
2029func setup (t * testing.T ) []testserver.TestRequestHandler {
30+ waitInfinitely := make (chan struct {})
2131 requests := []testserver.TestRequestHandler {
2232 {
23- Path : "/api/v4/internal/two_factor_otp_check " ,
33+ Path : "/api/v4/internal/two_factor_manual_otp_check " ,
2434 Handler : func (w http.ResponseWriter , r * http.Request ) {
2535 b , err := io .ReadAll (r .Body )
2636 defer r .Body .Close ()
@@ -31,11 +41,13 @@ func setup(t *testing.T) []testserver.TestRequestHandler {
3141 require .NoError (t , json .Unmarshal (b , & requestBody ))
3242
3343 switch requestBody .KeyId {
34- case "1 " :
44+ case "verify_via_otp" , "verify_via_otp_with_push_error " :
3545 body := map [string ]interface {}{
3646 "success" : true ,
3747 }
3848 json .NewEncoder (w ).Encode (body )
49+ case "wait_infinitely" :
50+ <- waitInfinitely
3951 case "error" :
4052 body := map [string ]interface {}{
4153 "success" : false ,
@@ -47,15 +59,36 @@ func setup(t *testing.T) []testserver.TestRequestHandler {
4759 }
4860 },
4961 },
62+ {
63+ Path : "/api/v4/internal/two_factor_push_otp_check" ,
64+ Handler : func (w http.ResponseWriter , r * http.Request ) {
65+ b , err := io .ReadAll (r .Body )
66+ defer r .Body .Close ()
67+
68+ require .NoError (t , err )
69+
70+ var requestBody * twofactorverify.RequestBody
71+ require .NoError (t , json .Unmarshal (b , & requestBody ))
72+
73+ switch requestBody .KeyId {
74+ case "verify_via_push" :
75+ body := map [string ]interface {}{
76+ "success" : true ,
77+ }
78+ json .NewEncoder (w ).Encode (body )
79+ case "verify_via_otp_with_push_error" :
80+ w .WriteHeader (http .StatusInternalServerError )
81+ default :
82+ <- waitInfinitely
83+ }
84+ },
85+ },
5086 }
5187
5288 return requests
5389}
5490
55- const (
56- question = "OTP: \n "
57- errorHeader = "OTP validation failed.\n "
58- )
91+ const errorHeader = "OTP validation failed: "
5992
6093func TestExecute (t * testing.T ) {
6194 requests := setup (t )
@@ -65,46 +98,61 @@ func TestExecute(t *testing.T) {
6598 testCases := []struct {
6699 desc string
67100 arguments * commandargs.Shell
68- answer string
101+ input io. Reader
69102 expectedOutput string
70103 }{
71104 {
72- desc : "With a known key id" ,
73- arguments : & commandargs.Shell {GitlabKeyId : "1" },
74- answer : "123456\n " ,
75- expectedOutput : question +
76- "OTP validation successful. Git operations are now allowed.\n " ,
105+ desc : "Verify via OTP" ,
106+ arguments : & commandargs.Shell {GitlabKeyId : "verify_via_otp" },
107+ expectedOutput : "OTP validation successful. Git operations are now allowed.\n " ,
108+ },
109+ {
110+ desc : "Verify via OTP" ,
111+ arguments : & commandargs.Shell {GitlabKeyId : "verify_via_otp_with_push_error" },
112+ expectedOutput : "OTP validation successful. Git operations are now allowed.\n " ,
113+ },
114+ {
115+ desc : "Verify via push authentication" ,
116+ arguments : & commandargs.Shell {GitlabKeyId : "verify_via_push" },
117+ input : & blockingReader {},
118+ expectedOutput : "OTP has been validated by Push Authentication. Git operations are now allowed.\n " ,
119+ },
120+ {
121+ desc : "With an empty OTP" ,
122+ arguments : & commandargs.Shell {GitlabKeyId : "verify_via_otp" },
123+ input : bytes .NewBufferString ("\n " ),
124+ expectedOutput : errorHeader + "OTP cannot be blank.\n " ,
77125 },
78126 {
79127 desc : "With bad response" ,
80128 arguments : & commandargs.Shell {GitlabKeyId : "-1" },
81- answer : "123456\n " ,
82- expectedOutput : question + errorHeader + "Parsing failed\n " ,
129+ expectedOutput : errorHeader + "Parsing failed\n " ,
83130 },
84131 {
85132 desc : "With API returns an error" ,
86133 arguments : & commandargs.Shell {GitlabKeyId : "error" },
87- answer : "yes\n " ,
88- expectedOutput : question + errorHeader + "error message\n " ,
134+ expectedOutput : errorHeader + "error message\n " ,
89135 },
90136 {
91137 desc : "With API fails" ,
92138 arguments : & commandargs.Shell {GitlabKeyId : "broken" },
93- answer : "yes\n " ,
94- expectedOutput : question + errorHeader + "Internal API error (500)\n " ,
139+ expectedOutput : errorHeader + "Internal API error (500)\n " ,
95140 },
96141 {
97142 desc : "With missing arguments" ,
98143 arguments : & commandargs.Shell {},
99- answer : "yes\n " ,
100- expectedOutput : question + errorHeader + "who='' is invalid\n " ,
144+ expectedOutput : errorHeader + "who='' is invalid\n " ,
101145 },
102146 }
103147
104148 for _ , tc := range testCases {
105149 t .Run (tc .desc , func (t * testing.T ) {
106150 output := & bytes.Buffer {}
107- input := bytes .NewBufferString (tc .answer )
151+
152+ input := tc .input
153+ if input == nil {
154+ input = bytes .NewBufferString ("123456\n " )
155+ }
108156
109157 cmd := & Command {
110158 Config : & config.Config {GitlabUrl : url },
@@ -115,7 +163,29 @@ func TestExecute(t *testing.T) {
115163 err := cmd .Execute (context .Background ())
116164
117165 require .NoError (t , err )
118- require .Equal (t , tc .expectedOutput , output .String ())
166+ require .Equal (t , prompt + " \n " + tc .expectedOutput , output .String ())
119167 })
120168 }
121169}
170+
171+ func TestCanceledContext (t * testing.T ) {
172+ requests := setup (t )
173+
174+ output := & bytes.Buffer {}
175+
176+ url := testserver .StartSocketHttpServer (t , requests )
177+ cmd := & Command {
178+ Config : & config.Config {GitlabUrl : url },
179+ Args : & commandargs.Shell {GitlabKeyId : "wait_infinitely" },
180+ ReadWriter : & readwriter.ReadWriter {Out : output , In : & bytes.Buffer {}},
181+ }
182+
183+ ctx , cancel := context .WithCancel (context .Background ())
184+
185+ errCh := make (chan error )
186+ go func () { errCh <- cmd .Execute (ctx ) }()
187+ cancel ()
188+
189+ require .NoError (t , <- errCh )
190+ require .Equal (t , prompt + "\n " + errorHeader + "context canceled\n " , output .String ())
191+ }
0 commit comments