Skip to content
This repository has been archived by the owner on Mar 11, 2021. It is now read-only.

Support notifications to users with private email ( using fabric8 service account ) #54

Merged
merged 19 commits into from
Jan 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ tool/cli/
migration/sqlbindata.go
template/bindata.go
wit/api
auth/api

# Ignore artifacts directory
bin/
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ clean-generated:
-rm -rf ./swagger/
-rm -f ./migration/sqlbindata.go
-rm -f ./template/bindata.go
-rm -rf auth/api

CLEAN_TARGETS += clean-vendor
.PHONY: clean-vendor
Expand All @@ -211,6 +212,7 @@ app/controllers.go: $(DESIGNS) $(GOAGEN_BIN) $(VENDOR_DIR)
$(GOAGEN_BIN) app -d ${PACKAGE_NAME}/${DESIGN_DIR}
$(GOAGEN_BIN) controller -d ${PACKAGE_NAME}/${DESIGN_DIR} -o controller/ --pkg controller --app-pkg app
$(GOAGEN_BIN) client -d github.com/fabric8-services/fabric8-wit/design --notool --pkg api -o wit
$(GOAGEN_BIN) client -d github.com/fabric8-services/fabric8-auth/design --notool --pkg api -o auth

.PHONY: migrate-database
## Compiles the server and runs the database migration with it
Expand Down
50 changes: 50 additions & 0 deletions auth/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package auth

import (
"context"
"net/http"
"net/url"

"fmt"

"github.com/fabric8-services/fabric8-notification/auth/api"
"github.com/fabric8-services/fabric8-wit/goasupport"
goaclient "github.com/goadesign/goa/client"
"github.com/goadesign/goa/uuid"
"github.com/gregjones/httpcache"
)

func NewCachedClient(hostURL string) (*api.Client, error) {

u, err := url.Parse(hostURL)
if err != nil {
return nil, err
}

tp := httpcache.NewMemoryCacheTransport()
client := http.Client{Transport: tp}

c := api.New(goaclient.HTTPClientDoer(&client))
c.Host = u.Host
c.Scheme = u.Scheme
return c, nil
}

func GetSpaceCollaborators(ctx context.Context, client *api.Client, spaceID uuid.UUID) (*api.UserList, error) {
pageLimit := 100
pageOffset := "0"
resp, err := client.ListCollaborators(goasupport.ForwardContextRequestID(ctx), api.ListCollaboratorsPath(spaceID), &pageLimit, &pageOffset, nil, nil)
if err != nil {
return nil, err
}
if resp != nil {
defer resp.Body.Close()
} else {
return nil, fmt.Errorf("failed to make request to get list of collaborators")
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("non %v status code for %v, returned %v", http.StatusOK, "GET collaborators", resp.StatusCode)
}
return client.DecodeUserList(resp)
}
36 changes: 36 additions & 0 deletions auth/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package auth_test

import (
"context"
"testing"

"github.com/fabric8-services/fabric8-notification/auth"
"github.com/fabric8-services/fabric8-notification/auth/api"
"github.com/goadesign/goa/uuid"
"github.com/stretchr/testify/assert"
)

const (
openshiftIOAPI = "http://auth.openshift.io"
)

func createClient(t *testing.T) *api.Client {
c, err := auth.NewCachedClient(openshiftIOAPI)
if err != nil {
t.Fatal(err)
}
return c
}

func TestSpaceCollaborators(t *testing.T) {

c := createClient(t)
id, _ := uuid.FromString("020f756e-b51a-4b43-b113-45cec16b9ce9")

u, err := auth.GetSpaceCollaborators(context.Background(), c, id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, you are testing the real "openshiftio" space from prod here. Not sure we need such a test here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this test was there before, just moved it around a bit to a new file.
using the prod space "openshiftio" because that's the only one's that's constant and hence test-able. Ideal situation would be to create a space and validate it :)

if err != nil {
t.Fatal(err)
}

assert.True(t, len(u.Data) > 10)
}
77 changes: 77 additions & 0 deletions auth/user_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package auth

import (
"context"
"net/http"
"net/url"

"fmt"

"github.com/fabric8-services/fabric8-notification/auth/api"
"github.com/fabric8-services/fabric8-wit/goasupport"
"github.com/goadesign/goa/uuid"
)

/*
Took out the auth api client code relevant to User API in order to add a custom
client.JWTSigner.Sign(req) before the http request is made.

This wasn't present in the auto-generated client for GET /api/users/ID
because we don't set "a.Security("jwt")" in auth's design/account.go
for the `Show Users` action.
*/

func GetUser(ctx context.Context, client *api.Client, uID uuid.UUID) (*api.User, error) {
resp, err := showUsers(goasupport.ForwardContextRequestID(ctx), client, api.ShowUsersPath(uID.String()), nil, nil)
if resp != nil {
defer resp.Body.Close()
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("non %v status code for %v, returned %v", http.StatusOK, "GET user", resp.StatusCode)
}

if err != nil {
return nil, err
}
return client.DecodeUser(resp)
}

// retrieve user for the given ID.
func showUsers(ctx context.Context, client *api.Client, path string, ifModifiedSince *string, ifNoneMatch *string) (*http.Response, error) {
req, err := newShowUsersRequest(ctx, client, path, ifModifiedSince, ifNoneMatch)
if err != nil {
return nil, err
}
return client.Do(ctx, req)
}

// newShowUsersRequest create the request corresponding to the show action endpoint of the users resource.
func newShowUsersRequest(ctx context.Context, client *api.Client, path string, ifModifiedSince *string, ifNoneMatch *string) (*http.Request, error) {
scheme := client.Scheme
if scheme == "" {
scheme = "http"
}
u := url.URL{Host: client.Host, Scheme: scheme, Path: path}
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, err
}
header := req.Header
if ifModifiedSince != nil {

header.Set("If-Modified-Since", *ifModifiedSince)
}
if ifNoneMatch != nil {

header.Set("If-None-Match", *ifNoneMatch)
}

// This wasn't present in the auto-generated client for GET /api/users/ID
// because we don't set "a.Security("jwt")" in auth's design/account.go
// for the `Show Users` action.
if client.JWTSigner != nil {
client.JWTSigner.Sign(req)
}
return req, nil
}
2 changes: 1 addition & 1 deletion collector/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"fmt"

"github.com/fabric8-services/fabric8-notification/wit/api"
"github.com/fabric8-services/fabric8-notification/auth/api"
"github.com/goadesign/goa/uuid"
)

Expand Down
4 changes: 2 additions & 2 deletions collector/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
)

func TestUser(t *testing.T) {
c := createClient(t)
_, authClient := createClient(t)
uID, _ := uuid.FromString("3383826c-51e4-401b-9ccd-b898f7e2397d")
users, vars, err := collector.User(context.Background(), c, uID)
users, vars, err := collector.User(context.Background(), authClient, uID)

assert.Nil(t, err)
assert.Len(t, users, 1)
Expand Down
42 changes: 22 additions & 20 deletions collector/workitem.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"

jwt "github.com/dgrijalva/jwt-go"
"github.com/fabric8-services/fabric8-notification/auth"
authapi "github.com/fabric8-services/fabric8-notification/auth/api"
"github.com/fabric8-services/fabric8-notification/configuration"
"github.com/fabric8-services/fabric8-notification/wit"
"github.com/fabric8-services/fabric8-notification/wit/api"
Expand All @@ -13,23 +15,23 @@ import (
"github.com/goadesign/goa/uuid"
)

func NewCommentResolver(c *api.Client) ReceiverResolver {
func NewCommentResolver(authclient *authapi.Client, c *api.Client) ReceiverResolver {
return func(ctx context.Context, id string) ([]Receiver, map[string]interface{}, error) {
cID, err := uuid.FromString(id)
if err != nil {
return []Receiver{}, nil, fmt.Errorf("unable to lookup comment based on id %v", id)
}
return Comment(ctx, c, cID)
return Comment(ctx, authclient, c, cID)
}
}

func NewWorkItemResolver(c *api.Client) ReceiverResolver {
func NewWorkItemResolver(authclient *authapi.Client, c *api.Client) ReceiverResolver {
return func(ctx context.Context, id string) ([]Receiver, map[string]interface{}, error) {
wID, err := uuid.FromString(id)
if err != nil {
return []Receiver{}, nil, fmt.Errorf("unable to lookup Workitem based on id %v", id)
}
return WorkItem(ctx, c, wID)
return WorkItem(ctx, authclient, c, wID)
}
}

Expand All @@ -45,7 +47,7 @@ func ConfiguredVars(config *configuration.Data, resolver ReceiverResolver) Recei
}
}

func Comment(ctx context.Context, c *api.Client, cID uuid.UUID) ([]Receiver, map[string]interface{}, error) {
func Comment(ctx context.Context, authClient *authapi.Client, c *api.Client, cID uuid.UUID) ([]Receiver, map[string]interface{}, error) {
var values = map[string]interface{}{}
var errors []error
var users []uuid.UUID
Expand All @@ -57,7 +59,7 @@ func Comment(ctx context.Context, c *api.Client, cID uuid.UUID) ([]Receiver, map
values["comment"] = comment
users = append(users, collectCommentUsers(comment)...)

commentOwner, err := wit.GetUser(ctx, c, *comment.Data.Relationships.CreatedBy.Data.ID)
commentOwner, err := auth.GetUser(ctx, authClient, *comment.Data.Relationships.CreatedBy.Data.ID)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -73,7 +75,7 @@ func Comment(ctx context.Context, c *api.Client, cID uuid.UUID) ([]Receiver, map
values["workitem"] = wi

ownerID, _ := uuid.FromString(*wi.Data.Relationships.Creator.Data.ID)
workitemOwner, err := wit.GetUser(ctx, c, ownerID)
workitemOwner, err := auth.GetUser(ctx, authClient, ownerID)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -100,7 +102,7 @@ func Comment(ctx context.Context, c *api.Client, cID uuid.UUID) ([]Receiver, map
users = append(users, collectSpaceUsers(s)...)
values["space"] = s

spaceOwner, err := wit.GetUser(ctx, c, *s.Data.Relationships.OwnedBy.Data.ID)
spaceOwner, err := auth.GetUser(ctx, authClient, *s.Data.Relationships.OwnedBy.Data.ID)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -114,20 +116,20 @@ func Comment(ctx context.Context, c *api.Client, cID uuid.UUID) ([]Receiver, map

actorID, err := getActorID(ctx)
if err == nil {
actor, err := wit.GetUser(ctx, c, actorID)
actor, err := auth.GetUser(ctx, authClient, actorID)
if err != nil {
errors = append(errors, err)
}
values["actor"] = actor
}

sc, err := wit.GetSpaceCollaborators(ctx, c, spaceID)
sc, err := auth.GetSpaceCollaborators(ctx, authClient, spaceID)
if err != nil {
errors = append(errors, err)
}
users = append(users, collectSpaceCollaboratorUsers(sc)...)

resolved, err := resolveAllUsers(ctx, c, SliceUniq(users), sc.Data)
resolved, err := resolveAllUsers(ctx, authClient, SliceUniq(users), sc.Data)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -140,7 +142,7 @@ func Comment(ctx context.Context, c *api.Client, cID uuid.UUID) ([]Receiver, map
return resolved, values, nil
}

func WorkItem(ctx context.Context, c *api.Client, wiID uuid.UUID) ([]Receiver, map[string]interface{}, error) {
func WorkItem(ctx context.Context, authclient *authapi.Client, c *api.Client, wiID uuid.UUID) ([]Receiver, map[string]interface{}, error) {
var values = map[string]interface{}{}
var errors []error
var users []uuid.UUID
Expand All @@ -153,7 +155,7 @@ func WorkItem(ctx context.Context, c *api.Client, wiID uuid.UUID) ([]Receiver, m
users = append(users, collectWorkItemUsers(wi)...)

ownerID, _ := uuid.FromString(*wi.Data.Relationships.Creator.Data.ID)
workitemOwner, err := wit.GetUser(ctx, c, ownerID)
workitemOwner, err := auth.GetUser(ctx, authclient, ownerID)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -180,7 +182,7 @@ func WorkItem(ctx context.Context, c *api.Client, wiID uuid.UUID) ([]Receiver, m
values["space"] = s
users = append(users, collectSpaceUsers(s)...)

spaceOwner, err := wit.GetUser(ctx, c, *s.Data.Relationships.OwnedBy.Data.ID)
spaceOwner, err := auth.GetUser(ctx, authclient, *s.Data.Relationships.OwnedBy.Data.ID)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -194,20 +196,20 @@ func WorkItem(ctx context.Context, c *api.Client, wiID uuid.UUID) ([]Receiver, m

actorID, err := getActorID(ctx)
if err == nil {
actor, err := wit.GetUser(ctx, c, actorID)
actor, err := auth.GetUser(ctx, authclient, actorID)
if err != nil {
errors = append(errors, err)
}
values["actor"] = actor
}

sc, err := wit.GetSpaceCollaborators(ctx, c, spaceID)
sc, err := auth.GetSpaceCollaborators(ctx, authclient, spaceID)
if err != nil {
errors = append(errors, err)
}
users = append(users, collectSpaceCollaboratorUsers(sc)...)

resolved, err := resolveAllUsers(ctx, c, SliceUniq(users), sc.Data)
resolved, err := resolveAllUsers(ctx, authclient, SliceUniq(users), sc.Data)
if err != nil {
errors = append(errors, err)
}
Expand All @@ -220,7 +222,7 @@ func WorkItem(ctx context.Context, c *api.Client, wiID uuid.UUID) ([]Receiver, m
return resolved, values, nil
}

func resolveAllUsers(ctx context.Context, c *api.Client, users []uuid.UUID, collaborators []*api.UserData) ([]Receiver, error) {
func resolveAllUsers(ctx context.Context, c *authapi.Client, users []uuid.UUID, collaborators []*authapi.UserData) ([]Receiver, error) {
var resolved []Receiver

for _, u := range users {
Expand All @@ -238,7 +240,7 @@ func resolveAllUsers(ctx context.Context, c *api.Client, users []uuid.UUID, coll
}
}
if !found {
usr, err := wit.GetUser(ctx, c, u)
usr, err := auth.GetUser(ctx, c, u)
if err == nil {
if usr.Data.Attributes.Email != nil {
user := Receiver{EMail: *usr.Data.Attributes.Email}
Expand All @@ -260,7 +262,7 @@ func resolveAllUsers(ctx context.Context, c *api.Client, users []uuid.UUID, coll
return resolved, nil
}

func collectSpaceCollaboratorUsers(cl *api.UserList) []uuid.UUID {
func collectSpaceCollaboratorUsers(cl *authapi.UserList) []uuid.UUID {
var users []uuid.UUID
for _, c := range cl.Data {
cID, err := uuid.FromString(*c.ID)
Expand Down
Loading