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 6 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

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
91 changes: 91 additions & 0 deletions auth/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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 SecureClient(authClient *api.Client, token string) (*api.Client, error) {
authClient.SetJWTSigner(&goaclient.JWTSigner{
TokenSource: &goaclient.StaticTokenSource{
StaticToken: &goaclient.StaticToken{
Value: token,
},
},
})
return authClient, nil
}

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 GetUser(ctx context.Context, client *api.Client, uID uuid.UUID) (*api.User, error) {
resp, err := client.ShowUsers(goasupport.ForwardContextRequestID(ctx), 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)
}

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 resp != nil {
defer resp.Body.Close()
}

if resp.StatusCode != http.StatusOK {
Copy link
Contributor

Choose a reason for hiding this comment

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

resp can be nil here. Check err first.

Copy link
Member Author

Choose a reason for hiding this comment

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

37b3c4a , done.
had misunderstood your comment here initially.

return nil, fmt.Errorf("non %v status code for %v, returned %v", http.StatusOK, "GET collaborators", resp.StatusCode)
}

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

func GetServiceAccountToken(ctx context.Context, client *api.Client, serviceAccountID string, serviceAccountSecret string) (*api.OauthToken, error) {
payload := api.TokenExchange{
ClientID: serviceAccountID,
ClientSecret: &serviceAccountSecret,
GrantType: "client_credentials",
}
resp, err := client.ExchangeToken(goasupport.ForwardContextRequestID(ctx), api.ExchangeTokenPath(), &payload, "application/x-www-form-urlencoded")

if err != nil {
return nil, err
}

return client.DecodeOauthToken(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)
}
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