Skip to content
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ build:
.PHONY: build

test:
go test -v -cover
go test -v -cover -timeout=15m
.PHONY: test

clean:
Expand Down
8 changes: 5 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ type Client struct {
BOM BOMService
Component ComponentService
Config ConfigService
Finding FindingService
Event EventService
Finding FindingService
Health HealthService
LDAP LDAPService
License LicenseService
Metrics MetricsService
Expand Down Expand Up @@ -93,8 +94,9 @@ func NewClient(baseURL string, options ...ClientOption) (*Client, error) {
client.BOM = BOMService{client: &client}
client.Component = ComponentService{client: &client}
client.Config = ConfigService{client: &client}
client.Finding = FindingService{client: &client}
client.Event = EventService{client: &client}
client.Finding = FindingService{client: &client}
client.Health = HealthService{client: &client}
client.LDAP = LDAPService{client: &client}
client.License = LicenseService{client: &client}
client.Metrics = MetricsService{client: &client}
Expand Down Expand Up @@ -193,7 +195,7 @@ func withPathParams(params map[string]string) requestOption {
}

for k, v := range params {
req.URL.Path = strings.Replace(req.URL.Path, fmt.Sprintf("{%s}", k), v, -1)
req.URL.Path = strings.ReplaceAll(req.URL.Path, fmt.Sprintf("{%s}", k), v)
}
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ func TestComponentLifecycle(t *testing.T) {
// Delete
{
err := client.Component.Delete(context.Background(), component.UUID)
// Occassionally receives 500 response from API - https://github.com/DependencyTrack/client-go/actions/runs/20657420675/job/59312871798?pr=55
// Due to the intermittent nature, the cause is not yet identified.
require.NoError(t, err)
}

Expand Down
31 changes: 31 additions & 0 deletions health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package dtrack

import (
"context"
"net/http"
)

type HealthCheck struct {
Name string `json:"name"`
Status string `json:"status"`
Data interface{} `json:"data,omitempty"`
}

type Health struct {
Status string `json:"status"`
Checks []HealthCheck `json:"checks"`
}

type HealthService struct {
client *Client
}

func (hs HealthService) Get(ctx context.Context) (h Health, err error) {
req, err := hs.client.newRequest(ctx, http.MethodGet, "health", withoutAuth())
if err != nil {
return
}

_, err = hs.client.doRequest(req, &h)
return
}
24 changes: 24 additions & 0 deletions health_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dtrack

import (
"context"
"testing"

"github.com/stretchr/testify/require"
)

func TestHealth(t *testing.T) {
client := setUpContainer(t, testContainerOptions{})

health, err := client.Health.Get(context.TODO())
require.NoError(t, err)
require.NotNil(t, health)

require.Equal(t, "UP", health.Status)
require.Equal(t, 1, len(health.Checks))
require.Equal(t, "database", health.Checks[0].Name)
require.Equal(t, "UP", health.Checks[0].Status)
require.NotNil(t, health.Checks[0].Data)
require.Equal(t, "UP", health.Checks[0].Data.(map[string]any)["nontx_connection_pool"])
require.Equal(t, "UP", health.Checks[0].Data.(map[string]any)["tx_connection_pool"])
}
145 changes: 137 additions & 8 deletions oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"strconv"

"github.com/google/uuid"
Expand All @@ -28,7 +29,25 @@ type OIDCMapping struct {
UUID uuid.UUID `json:"uuid"`
}

type OIDCUser struct {
Username string `json:"username"`
SubjectIdentifier string `json:"subjectIdentifier"`
Email string `json:"email"`
Teams []Team `json:"teams"`
Permissions []Permission `json:"permissions"`
}

type OIDCTokens struct {
ID string `json:"idToken"`
Access string `json:"accessToken,omitempty"`
}

func (s OIDCService) Available(ctx context.Context) (available bool, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodGet, "api/v1/oidc/available", withAcceptContentType("text/plain"))
if err != nil {
return
Expand All @@ -44,22 +63,28 @@ func (s OIDCService) Available(ctx context.Context) (available bool, err error)
return
}

func (s OIDCService) GetAllGroups(ctx context.Context, po PageOptions) (p Page[OIDCGroup], err error) {
req, err := s.client.newRequest(ctx, http.MethodGet, "api/v1/oidc/group", withPageOptions(po))
func (s OIDCService) GetAllGroups(ctx context.Context) (groups []OIDCGroup, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

res, err := s.client.doRequest(req, &p.Items)
req, err := s.client.newRequest(ctx, http.MethodGet, "api/v1/oidc/group")
if err != nil {
return
}

p.TotalCount = res.TotalCount
_, err = s.client.doRequest(req, &groups)
return

}

func (s OIDCService) CreateGroup(ctx context.Context, name string) (g OIDCGroup, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodPut, "api/v1/oidc/group", withBody(OIDCGroup{Name: name}))
if err != nil {
return
Expand All @@ -69,6 +94,11 @@ func (s OIDCService) CreateGroup(ctx context.Context, name string) (g OIDCGroup,
return
}
func (s OIDCService) UpdateGroup(ctx context.Context, group OIDCGroup) (g OIDCGroup, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodPost, "api/v1/oidc/group", withBody(group))
if err != nil {
return
Expand All @@ -79,6 +109,11 @@ func (s OIDCService) UpdateGroup(ctx context.Context, group OIDCGroup) (g OIDCGr
}

func (s OIDCService) DeleteGroup(ctx context.Context, groupUUID uuid.UUID) (err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodDelete, fmt.Sprintf("api/v1/oidc/group/%s", groupUUID.String()))
if err != nil {
return
Expand All @@ -88,22 +123,27 @@ func (s OIDCService) DeleteGroup(ctx context.Context, groupUUID uuid.UUID) (err
return
}

func (s OIDCService) GetAllTeamsOf(ctx context.Context, group OIDCGroup, po PageOptions) (p Page[Team], err error) {
req, err := s.client.newRequest(ctx, http.MethodGet, fmt.Sprintf("api/v1/oidc/group/%s/team", group.UUID.String()), withPageOptions(po))
func (s OIDCService) GetAllTeamsOf(ctx context.Context, group OIDCGroup) (teams []Team, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

res, err := s.client.doRequest(req, &p.Items)
req, err := s.client.newRequest(ctx, http.MethodGet, fmt.Sprintf("api/v1/oidc/group/%s/team", group.UUID.String()))
if err != nil {
return
}

p.TotalCount = res.TotalCount
_, err = s.client.doRequest(req, &teams)
return
}

func (s OIDCService) AddTeamMapping(ctx context.Context, mapping OIDCMappingRequest) (m OIDCMapping, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodPut, "api/v1/oidc/mapping", withBody(mapping))
if err != nil {
return
Expand All @@ -114,6 +154,11 @@ func (s OIDCService) AddTeamMapping(ctx context.Context, mapping OIDCMappingRequ
}

func (s OIDCService) RemoveTeamMapping(ctx context.Context, mappingID uuid.UUID) (err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodDelete, fmt.Sprintf("api/v1/oidc/mapping/%s", mappingID.String()))
if err != nil {
return
Expand All @@ -122,3 +167,87 @@ func (s OIDCService) RemoveTeamMapping(ctx context.Context, mappingID uuid.UUID)
_, err = s.client.doRequest(req, nil)
return
}

func (s OIDCService) RemoveTeamMapping2(ctx context.Context, groupID, teamID uuid.UUID) (err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodDelete, fmt.Sprintf("api/v1/oidc/group/%s/team/%s/mapping", groupID.String(), teamID.String()))
if err != nil {
return
}

_, err = s.client.doRequest(req, nil)
return
}

func (s OIDCService) GetAllUsers(ctx context.Context) (p Page[OIDCUser], err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodGet, "api/v1/user/oidc")
if err != nil {
return
}

res, err := s.client.doRequest(req, &p.Items)
if err != nil {
return
}

p.TotalCount = res.TotalCount
return
}

func (s OIDCService) CreateUser(ctx context.Context, userReq OIDCUser) (userRes OIDCUser, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodPut, "api/v1/user/oidc", withBody(userReq))
if err != nil {
return
}

_, err = s.client.doRequest(req, &userRes)
return
}

func (s OIDCService) DeleteUser(ctx context.Context, user OIDCUser) (err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

req, err := s.client.newRequest(ctx, http.MethodDelete, "api/v1/user/oidc", withBody(user))
if err != nil {
return
}

_, err = s.client.doRequest(req, nil)
return
}

func (s OIDCService) Login(ctx context.Context, tokens OIDCTokens) (token string, err error) {
err = s.client.assertServerVersionAtLeast("4.0.0")
if err != nil {
return
}

body := url.Values{}
body.Set("idToken", tokens.ID)
body.Set("accessToken", tokens.Access)

req, err := s.client.newRequest(ctx, http.MethodPost, "api/v1/user/oidc/login", withBody(body))
if err != nil {
return
}

_, err = s.client.doRequest(req, &token)
return
}
Loading
Loading