func TestKeycloakAuthorizationRedirect(t *testing.T) { resource.Require(t, resource.UnitTest) rw := httptest.NewRecorder() u := &url.URL{ Path: fmt.Sprintf("/api/login/authorize"), } req, err := http.NewRequest("GET", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } // The user clicks login while on ALM UI. // Therefore the referer would be an ALM URL. refererUrl := "https://alm-url.example.org/path" req.Header.Add("referer", refererUrl) prms := url.Values{} ctx := context.Background() goaCtx := goa.NewContext(goa.WithAction(ctx, "LoginTest"), rw, req, prms) authorizeCtx, err := app.NewAuthorizeLoginContext(goaCtx, goa.New("LoginService")) if err != nil { panic("invalid test data " + err.Error()) // bug } err = loginService.Perform(authorizeCtx) assert.Equal(t, 307, rw.Code) assert.Contains(t, rw.Header().Get("Location"), configuration.GetKeycloakEndpointAuth()) }
func TestInvalidState(t *testing.T) { resource.Require(t, resource.UnitTest) // Setup request context rw := httptest.NewRecorder() u := &url.URL{ Path: fmt.Sprintf("/api/login/authorize"), } req, err := http.NewRequest("GET", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } // The OAuth 'state' is sent as a query parameter by calling /api/login/authorize?code=_SOME_CODE_&state=_SOME_STATE_ // The request originates from Keycloak after a valid authorization by the end user. // This is not where the redirection should happen on failure. refererKeyclaokUrl := "https://keycloak-url.example.org/path-of-login" req.Header.Add("referer", refererKeyclaokUrl) prms := url.Values{ "state": {}, "code": {"doesnt_matter_what_is_here"}, } ctx := context.Background() goaCtx := goa.NewContext(goa.WithAction(ctx, "LoginTest"), rw, req, prms) authorizeCtx, err := app.NewAuthorizeLoginContext(goaCtx, goa.New("LoginService")) if err != nil { panic("invalid test data " + err.Error()) // bug } err = loginService.Perform(authorizeCtx) assert.Equal(t, 401, rw.Code) }
// HandlePreflight calls the given cors middleware and returns a simple 200 response. func HandlePreflight(ctx context.Context, middleware goa.Middleware) goa.MuxHandler { return func(rw http.ResponseWriter, req *http.Request, params url.Values) { h := func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { rw.WriteHeader(200) return nil } ctx = goa.NewContext(ctx, rw, req, params) middleware(h)(ctx, rw, req) } }
// StartAeOK runs the method Start of the given controller with the given parameters. // It returns the response writer so it's possible to inspect the response headers. // If ctx is nil then context.Background() is used. // If service is nil then a default service is created. func StartAeOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.AeController) http.ResponseWriter { // Setup service var ( logBuf bytes.Buffer resp interface{} respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } ) if service == nil { service = goatest.Service(&logBuf, respSetter) } else { logger := log.New(&logBuf, "", log.Ltime) service.WithLogger(goa.NewLogger(logger)) newEncoder := func(io.Writer) goa.Encoder { return respSetter } service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder service.Encoder.Register(newEncoder, "*/*") } // Setup request context rw := httptest.NewRecorder() u := &url.URL{ Path: fmt.Sprintf("/_ah/start"), } req, err := http.NewRequest("GET", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } prms := url.Values{} if ctx == nil { ctx = context.Background() } goaCtx := goa.NewContext(goa.WithAction(ctx, "AeTest"), rw, req, prms) startCtx, err := app.NewStartAeContext(goaCtx, service) if err != nil { panic("invalid test data " + err.Error()) // bug } // Perform action err = ctrl.Start(startCtx) // Validate response if err != nil { t.Fatalf("controller returned %s, logs:\n%s", err, logBuf.String()) } if rw.Code != 200 { t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) } // Return results return rw }
// searchByURL copies much of the codebase from search_testing.go->ShowSearchOK // and customises the values to add custom Host in the call. func searchByURL(t *testing.T, customHost, queryString string) *app.SearchWorkItemList { service := getServiceAsUser() var resp interface{} var respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } newEncoder := func(io.Writer) goa.Encoder { return respSetter } service.Encoder = goa.NewHTTPEncoder() service.Encoder.Register(newEncoder, "*/*") rw := httptest.NewRecorder() query := url.Values{} u := &url.URL{ Path: fmt.Sprintf("/api/search"), RawQuery: query.Encode(), Host: customHost, } req, err := http.NewRequest("GET", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } prms := url.Values{} prms["q"] = []string{queryString} // any value will do ctx := service.Context goaCtx := goa.NewContext(goa.WithAction(ctx, "SearchTest"), rw, req, prms) showCtx, err := app.NewShowSearchContext(goaCtx, service) if err != nil { panic("invalid test data " + err.Error()) // bug } ctrl := NewSearchController(service, gormapplication.NewGormDB(DB)) // Perform action err = ctrl.Show(showCtx) // Validate response if err != nil { t.Fatalf("controller returned %s", err) } if rw.Code != 200 { t.Fatalf("invalid response status code: got %+v, expected 200", rw.Code) } mt, ok := resp.(*app.SearchWorkItemList) if !ok { t.Fatalf("invalid response media: got %+v, expected instance of app.SearchWorkItemList", resp) } return mt }
var ctx *goa.Context var req *http.Request var rw *TestResponseWriter params := url.Values{"param": []string{"value"}} payload := map[string]interface{}{"payload": 42} BeforeEach(func() { var err error req, err = http.NewRequest("POST", "/foo/bar", strings.NewReader(`{"payload":42}`)) req.Header.Set("Accept-Encoding", "gzip") Ω(err).ShouldNot(HaveOccurred()) rw = &TestResponseWriter{ ParentHeader: http.Header{}, } ctx = goa.NewContext(nil, goa.New("test"), req, rw, params) ctx.SetPayload(payload) handler = new(testHandler) logger := log15.New("test", "test") logger.SetHandler(handler) ctx.Logger = logger }) It("encodes response using gzip", func() { h := func(ctx *goa.Context) error { ctx.Write([]byte("gzip me!")) ctx.WriteHeader(http.StatusOK) return nil } t := gzm.Middleware(gzip.BestCompression)(h) err := t(ctx)
. "github.com/onsi/gomega" ) var _ = Describe("ResponseData", func() { var data *goa.ResponseData var rw http.ResponseWriter var req *http.Request var params url.Values BeforeEach(func() { var err error req, err = http.NewRequest("GET", "google.com", nil) Ω(err).ShouldNot(HaveOccurred()) rw = &TestResponseWriter{Status: 42} params = url.Values{"query": []string{"value"}} ctx := goa.NewContext(context.Background(), rw, req, params) data = goa.ContextResponse(ctx) }) Context("SwitchWriter", func() { var rwo http.ResponseWriter It("sets the response writer and returns the previous one", func() { Ω(rwo).Should(BeNil()) rwo = data.SwitchWriter(&TestResponseWriter{Status: 43}) Ω(rwo).ShouldNot(BeNil()) Ω(rwo).Should(BeAssignableToTypeOf(&TestResponseWriter{})) trw := rwo.(*TestResponseWriter) Ω(trw.Status).Should(Equal(42)) }) })
"strings" "github.com/goadesign/goa" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "golang.org/x/net/context" "gopkg.in/inconshreveable/log15.v2" ) var _ = Describe("Context", func() { var logger log15.Logger var ctx *goa.Context BeforeEach(func() { gctx := context.Background() ctx = goa.NewContext(gctx, goa.New("test"), nil, nil, nil) ctx.Logger = logger }) Describe("SetValue", func() { key := "answer" val := 42 BeforeEach(func() { ctx.SetValue(key, val) }) It("sets the value in the context.Context", func() { v := ctx.Value(key) Ω(v).Should(Equal(val)) })
Ω(fmt.Sprintf("%#v", middleware)).Should(Equal(fmt.Sprintf("%#v", goa.Middleware(goaMiddlewareFunc)))) Ω(mErr).ShouldNot(HaveOccurred()) }) }) Context("with a context", func() { var service goa.Service var ctx *goa.Context BeforeEach(func() { service = goa.New("test") req, err := http.NewRequest("GET", "/goo", nil) Ω(err).ShouldNot(HaveOccurred()) rw := new(testResponseWriter) params := url.Values{"foo": []string{"bar"}} ctx = goa.NewContext(nil, service, req, rw, params) Ω(ctx.ResponseStatus()).Should(Equal(0)) }) Context("using a goa handler", func() { BeforeEach(func() { var goaHandler goa.Handler = func(ctx *goa.Context) error { ctx.Respond(200, "ok") return nil } input = goaHandler }) It("wraps it in a middleware", func() { Ω(mErr).ShouldNot(HaveOccurred()) h := func(ctx *goa.Context) error { return nil }
} var _ = Describe("Gzip", func() { var ctx context.Context var req *http.Request var rw *TestResponseWriter payload := map[string]interface{}{"payload": 42} BeforeEach(func() { var err error req, err = http.NewRequest("POST", "/foo/bar", strings.NewReader(`{"payload":42}`)) req.Header.Set("Accept-Encoding", "gzip") Ω(err).ShouldNot(HaveOccurred()) rw = &TestResponseWriter{ParentHeader: make(http.Header)} ctx = goa.NewContext(nil, rw, req, nil) goa.ContextRequest(ctx).Payload = payload }) It("encodes response using gzip", func() { h := func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { resp := goa.ContextResponse(ctx) resp.Write([]byte("gzip me!")) resp.WriteHeader(http.StatusOK) return nil } t := gzm.Middleware(gzip.BestCompression)(h) err := t(ctx, rw, req) Ω(err).ShouldNot(HaveOccurred()) resp := goa.ContextResponse(ctx) Ω(resp.Status).Should(Equal(http.StatusOK))
// CreateBottleCreated Create runs the method Create of the given controller with the given parameters and payload. // It returns the response writer so it's possible to inspect the response headers. // If ctx is nil then context.Background() is used. // If service is nil then a default service is created. func CreateBottleCreated(t *testing.T, ctx context.Context, service *goa.Service, ctrl app.BottleController, payload *app.CreateBottlePayload) http.ResponseWriter { // Setup service var ( logBuf bytes.Buffer resp interface{} respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } ) if service == nil { service = goatest.Service(&logBuf, respSetter) } else { logger := log.New(&logBuf, "", log.Ltime) service.WithLogger(goa.NewLogger(logger)) newEncoder := func(io.Writer) goa.Encoder { return respSetter } service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder service.Encoder.Register(newEncoder, "*/*") } // Validate payload err := payload.Validate() if err != nil { e, ok := err.(*goa.Error) if !ok { panic(err) // bug } if e.Status != 201 { t.Errorf("unexpected payload validation error: %+v", e) } return nil } // Setup request context rw := httptest.NewRecorder() u := &url.URL{ Path: fmt.Sprintf("/bottles"), } req, err := http.NewRequest("POST", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } prms := url.Values{} if ctx == nil { ctx = context.Background() } goaCtx := goa.NewContext(goa.WithAction(ctx, "BottleTest"), rw, req, prms) createCtx, err := app.NewCreateBottleContext(goaCtx, service) if err != nil { panic("invalid test data " + err.Error()) // bug } createCtx.Payload = payload // Perform action err = ctrl.Create(createCtx) // Validate response if err != nil { t.Fatalf("controller returned %s, logs:\n%s", err, logBuf.String()) } if rw.Code != 201 { t.Errorf("invalid response status code: got %+v, expected 201", rw.Code) } // Return results return rw }
// ShowBottleOK Show runs the method Show of the given controller with the given parameters. // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. // If ctx is nil then context.Background() is used. // If service is nil then a default service is created. func ShowBottleOK(t *testing.T, ctx context.Context, service *goa.Service, ctrl app.BottleController, id int) (http.ResponseWriter, *app.Bottle) { // Setup service var ( logBuf bytes.Buffer resp interface{} respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } ) if service == nil { service = goatest.Service(&logBuf, respSetter) } else { logger := log.New(&logBuf, "", log.Ltime) service.WithLogger(goa.NewLogger(logger)) newEncoder := func(io.Writer) goa.Encoder { return respSetter } service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder service.Encoder.Register(newEncoder, "*/*") } // Setup request context rw := httptest.NewRecorder() u := &url.URL{ Path: fmt.Sprintf("/bottles/%v", id), } req, err := http.NewRequest("GET", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } prms := url.Values{} prms["id"] = []string{fmt.Sprintf("%v", id)} if ctx == nil { ctx = context.Background() } goaCtx := goa.NewContext(goa.WithAction(ctx, "BottleTest"), rw, req, prms) showCtx, err := app.NewShowBottleContext(goaCtx, service) if err != nil { panic("invalid test data " + err.Error()) // bug } // Perform action err = ctrl.Show(showCtx) // Validate response if err != nil { t.Fatalf("controller returned %s, logs:\n%s", err, logBuf.String()) } if rw.Code != 200 { t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) } var mt *app.Bottle if resp != nil { var ok bool mt, ok = resp.(*app.Bottle) if !ok { t.Errorf("invalid response media: got %+v, expected instance of app.Bottle", resp) } err = mt.Validate() if err != nil { t.Errorf("invalid response media type: %s", err) } } // Return results return rw, mt }
handler := func(ctx *goa.Context) error { ctx.Respond(200, "ok") return nil } BeforeEach(func() { req, err = http.NewRequest("GET", "/goo", nil) Ω(err).ShouldNot(HaveOccurred()) rw = new(TestResponseWriter) rw.ParentHeader = make(http.Header) s := goa.New("test") s.SetEncoder(goa.JSONEncoderFactory(), true, "*/*") ctx = goa.NewContext(nil, s, req, rw, nil) spec = &httpauth.Specification{ ValidationProvider: validFunc, } }) It("handles valid credentials", func() { req.Header.Add("Authorization", authString) auth := httpauth.BasicMiddleware(spec)(handler) Ω(auth(ctx)).ShouldNot(HaveOccurred()) Ω(ctx.ResponseStatus()).Should(Equal(http.StatusOK)) Ω(rw.Body).Should(Equal([]byte("\"ok\"\n"))) })
func TestInvalidOAuthAuthorizationCode(t *testing.T) { // When a valid referrer talks to our system and provides // an invalid OAuth2.0 code, the access token exchange // fails. In such a scenario, there is response redirection // to the valid referer, ie, the URL where the request originated from. // Currently, this should be something like https://demo.almighty.org/somepage/ resource.Require(t, resource.UnitTest) // Setup request context rw := httptest.NewRecorder() u := &url.URL{ Path: fmt.Sprintf("/api/login/authorize"), } req, err := http.NewRequest("GET", u.String(), nil) if err != nil { panic("invalid test " + err.Error()) // bug } // The user clicks login while on ALM UI. // Therefore the referer would be an ALM URL. refererUrl := "https://alm-url.example.org/path" req.Header.Add("referer", refererUrl) prms := url.Values{} ctx := context.Background() goaCtx := goa.NewContext(goa.WithAction(ctx, "LoginTest"), rw, req, prms) authorizeCtx, err := app.NewAuthorizeLoginContext(goaCtx, goa.New("LoginService")) if err != nil { panic("invalid test data " + err.Error()) // bug } err = loginService.Perform(authorizeCtx) assert.Equal(t, 307, rw.Code) // redirect to keycloak login page. locationString := rw.HeaderMap["Location"][0] locationUrl, err := url.Parse(locationString) if err != nil { t.Fatal("Redirect URL is in a wrong format ", err) } t.Log(locationString) allQueryParameters := locationUrl.Query() // Avoiding panics. assert.NotNil(t, allQueryParameters) assert.NotNil(t, allQueryParameters["state"][0]) returnedState := allQueryParameters["state"][0] prms = url.Values{ "state": {returnedState}, "code": {"INVALID_OAUTH2.0_CODE"}, } ctx = context.Background() rw = httptest.NewRecorder() req, err = http.NewRequest("GET", u.String(), nil) // The OAuth code is sent as a query parameter by calling /api/login/authorize?code=_SOME_CODE_&state=_SOME_STATE_ // The request originates from Keycloak after a valid authorization by the end user. // This is not where the redirection should happen on failure. refererKeycloakUrl := "https://keycloak-url.example.org/path-of-login" req.Header.Add("referer", refererKeycloakUrl) if err != nil { panic("invalid test " + err.Error()) // bug } goaCtx = goa.NewContext(goa.WithAction(ctx, "LoginTest"), rw, req, prms) authorizeCtx, err = app.NewAuthorizeLoginContext(goaCtx, goa.New("LoginService")) err = loginService.Perform(authorizeCtx) locationString = rw.HeaderMap["Location"][0] locationUrl, err = url.Parse(locationString) if err != nil { t.Fatal("Redirect URL is in a wrong format ", err) } t.Log(locationString) allQueryParameters = locationUrl.Query() assert.Equal(t, 307, rw.Code) // redirect to ALM page where login was clicked. // Avoiding panics. assert.NotNil(t, allQueryParameters) assert.NotNil(t, allQueryParameters["error"]) assert.Equal(t, allQueryParameters["error"][0], InvalidCodeError) returnedErrorReason := allQueryParameters["error"][0] assert.NotEmpty(t, returnedErrorReason) assert.NotContains(t, locationString, refererKeycloakUrl) assert.Contains(t, locationString, refererUrl) }
}) }) Context("with a context", func() { var service *goa.Service var req *http.Request var rw http.ResponseWriter var ctx context.Context BeforeEach(func() { service = goa.New("test") var err error req, err = http.NewRequest("GET", "/goo", nil) Ω(err).ShouldNot(HaveOccurred()) rw = new(TestResponseWriter) ctx = goa.NewContext(nil, service, rw, req, nil) Ω(goa.Response(ctx).Status).Should(Equal(0)) }) Context("using a goa handler", func() { BeforeEach(func() { var goaHandler goa.Handler = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { goa.Response(ctx).Send(ctx, 200, "ok") return nil } input = goaHandler }) It("wraps it in a middleware", func() { Ω(mErr).ShouldNot(HaveOccurred()) h := func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { return nil }
var logger *testLogger var service *goa.Service payload := map[string]interface{}{"payload": 42} BeforeEach(func() { logger = new(testLogger) service = newService(logger) var err error req, err = http.NewRequest("POST", "/goo?param=value", strings.NewReader(`{"payload":42}`)) Ω(err).ShouldNot(HaveOccurred()) rw = new(testResponseWriter) params = url.Values{"query": []string{"value"}} ctrl := service.NewController("test") ctx = goa.NewContext(ctrl.Context, rw, req, params) goa.ContextRequest(ctx).Payload = payload }) It("logs requests", func() { // Add Action name to the context to make sure we log it properly. ctx = goa.WithAction(ctx, "goo") h := func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { return service.Send(ctx, 200, "ok") } lg := middleware.LogRequest(true)(h) Ω(lg(ctx, rw, req)).ShouldNot(HaveOccurred()) Ω(logger.InfoEntries).Should(HaveLen(4)) Ω(logger.InfoEntries[0].Data).Should(HaveLen(10))
// Creates a test context func newContext(service *goa.Service, rw http.ResponseWriter, req *http.Request, params url.Values) context.Context { ctrl := service.NewController("test") return goa.NewContext(ctrl.Context, rw, req, params) }
}) Context("with a context", func() { var service *goa.Service var req *http.Request var rw http.ResponseWriter var ctx context.Context BeforeEach(func() { service = goa.New("test") ctrl := service.NewController("foo") var err error req, err = http.NewRequest("GET", "/goo", nil) Ω(err).ShouldNot(HaveOccurred()) rw = new(TestResponseWriter) ctx = goa.NewContext(ctrl.Context, rw, req, nil) Ω(goa.ContextResponse(ctx).Status).Should(Equal(0)) }) Context("using a goa handler", func() { BeforeEach(func() { var goaHandler goa.Handler = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { service.Send(ctx, 200, "ok") return nil } input = goaHandler }) It("wraps it in a middleware", func() { Ω(mErr).ShouldNot(HaveOccurred()) h := func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { return nil }
Ω(fmt.Sprintf("%#v", middleware)).Should(Equal(fmt.Sprintf("%#v", goa.Middleware(goaMiddlewareFunc)))) Ω(mErr).ShouldNot(HaveOccurred()) }) }) Context("with a context", func() { var service goa.Service var ctx *goa.Context BeforeEach(func() { service = goa.New("test") req, err := http.NewRequest("GET", "/goo", nil) Ω(err).ShouldNot(HaveOccurred()) rw := new(TestResponseWriter) params := url.Values{"foo": []string{"bar"}} ctx = goa.NewContext(nil, service, req, rw, params) Ω(ctx.ResponseStatus()).Should(Equal(0)) }) Context("using a goa handler", func() { BeforeEach(func() { var goaHandler goa.Handler = func(ctx *goa.Context) error { ctx.Respond(200, "ok") return nil } input = goaHandler }) It("wraps it in a middleware", func() { Ω(mErr).ShouldNot(HaveOccurred()) h := func(ctx *goa.Context) error { return nil }