Skip to content

Commit

Permalink
Update API test workflow and schemas
Browse files Browse the repository at this point in the history
Signed-off-by: Rodney Osodo <[email protected]>
Signed-off-by: rodneyosodo <[email protected]>
Signed-off-by: Rodney Osodo <[email protected]>
  • Loading branch information
rodneyosodo committed Mar 22, 2024
1 parent 30afc0a commit 3f56a84
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 48 deletions.
97 changes: 95 additions & 2 deletions .github/workflows/api-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,47 @@ on:
push:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "twins/api/**"
- "users/api/**"

pull_request:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "twins/api/**"
- "users/api/**"

env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
DOMAINS_URL: http://localhost:8189/domains
USER_IDENTITY: [email protected]
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost:9002
THINGS_URL: http://localhost:9000

jobs:
api-test:
Expand Down Expand Up @@ -44,20 +75,82 @@ jobs:
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\",\"domain_id\": \"$DOMAIN_ID\"}" | jq -r .access_token)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV
- name: Check for changes in specific paths
uses: dorny/paths-filter@v2
id: changes
with:
filters: |
auth:
- ".github/workflows/api-tests.yml"
- "api/openapi/auth.yml"
- "auth/api/http/**"
bootstrap:
- ".github/workflows/api-tests.yml"
- "api/openapi/bootstrap.yml"
- "bootstrap/api/**"
certs:
- ".github/workflows/api-tests.yml"
- "api/openapi/certs.yml"
- "certs/api/**"
notifiers:
- ".github/workflows/api-tests.yml"
- "api/openapi/notifiers.yml"
- "consumers/notifiers/api/**"
http:
- ".github/workflows/api-tests.yml"
- "api/openapi/http.yml"
- "http/api/**"
invitations:
- ".github/workflows/api-tests.yml"
- "api/openapi/invitations.yml"
- "invitations/api/**"
provision:
- ".github/workflows/api-tests.yml"
- "api/openapi/provision.yml"
- "provision/api/**"
readers:
- ".github/workflows/api-tests.yml"
- "api/openapi/readers.yml"
- "readers/api/**"
things:
- ".github/workflows/api-tests.yml"
- "api/openapi/things.yml"
- "things/api/**"
twins:
- ".github/workflows/api-tests.yml"
- "api/openapi/twins.yml"
- "twins/api/**"
users:
- ".github/workflows/api-tests.yml"
- "api/openapi/users.yml"
- "users/api/**"
- name: Run Users API tests
if: steps.changes.outputs.users == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/users.yml
base-url: http://localhost:9002
base-url: ${{ env.USERS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Things API tests
if: steps.changes.outputs.things == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/things.yml
base-url: http://localhost:9000
base-url: ${{ env.THINGS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
Expand Down
27 changes: 20 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ BUILD_DIR = build
SERVICES = auth users things http coap ws lora influxdb-writer influxdb-reader mongodb-writer \
mongodb-reader cassandra-writer cassandra-reader postgres-writer postgres-reader timescale-writer timescale-reader cli \
bootstrap opcua twins mqtt provision certs smtp-notifier smpp-notifier invitations
TEST_API_SERVICES = auth bootstrap certs http invitations notifiers provision readers things twins users
TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES))
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
CGO_ENABLED ?= 0
Expand Down Expand Up @@ -129,19 +131,30 @@ test: mocks
done
go test -v --race -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|postgres\|internal\|opcua\|cmd')

test_api:
ifeq ($(USER_TOKEN),)
@echo "env variable USER_TOKEN is empty"
exit 1
endif
define test_api_service
$(eval svc=$(subst test_api_,,$(1)))
@which st > /dev/null || (echo "schemathesis not found, please install it from https://github.com/schemathesis/schemathesis#getting-started" && exit 1)
st run api/openapi/users.yml \

@if [ -z "$(USER_TOKEN)" ]; then \
echo "USER_TOKEN is not set"; \
echo "Please set it to a valid token"; \
exit 1; \
fi

st run api/openapi/$(svc).yml \
--checks all \
--base-url http://localhost:9002 \
--base-url $(2) \
--header "Authorization: Bearer $(USER_TOKEN)" \
--contrib-openapi-formats-uuid \
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links
endef

test_api_users: TEST_API_URL := http://localhost:9002
test_api_things: TEST_API_URL := http://localhost:9000

$(TEST_API):
$(call test_api_service,$(@),$(TEST_API_URL))

proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
Expand Down
26 changes: 20 additions & 6 deletions api/openapi/things.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ paths:
"401":
description: |
Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
Expand All @@ -112,7 +114,7 @@ paths:
requestBody:
$ref: "#/components/requestBodies/ThingsCreateReq"
responses:
"201":
"200":
$ref: "#/components/responses/ThingPageRes"
"400":
description: Failed due to malformed JSON.
Expand Down Expand Up @@ -179,6 +181,8 @@ paths:
description: Failed to perform authorization over the entity.
"404":
description: Failed due to non existing thing.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
Expand Down Expand Up @@ -294,6 +298,8 @@ paths:
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already disabled thing.
"422":
description: Database can't process request.
"500":
Expand Down Expand Up @@ -322,6 +328,8 @@ paths:
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already enabled thing.
"422":
description: Database can't process request.
"500":
Expand Down Expand Up @@ -534,6 +542,8 @@ paths:
description: Failed to perform authorization over the entity.
"404":
description: Channel does not exist.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
Expand Down Expand Up @@ -584,6 +594,8 @@ paths:
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already enabled channel.
"422":
description: Database can't process request.
"500":
Expand Down Expand Up @@ -612,6 +624,8 @@ paths:
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already disabled channel.
"422":
description: Database can't process request.
"500":
Expand Down Expand Up @@ -662,7 +676,7 @@ paths:
security:
- bearerAuth: []
responses:
"200":
"204":
description: Thing unshared.
"400":
description: Failed due to malformed thing's ID.
Expand Down Expand Up @@ -722,7 +736,7 @@ paths:
security:
- bearerAuth: []
responses:
"200":
"204":
description: Thing unshared.
"400":
description: Failed due to malformed thing's ID.
Expand Down Expand Up @@ -1346,7 +1360,7 @@ components:
ChannelsPage:
type: object
properties:
channels:
groups:
type: array
minItems: 0
uniqueItems: true
Expand All @@ -1364,9 +1378,9 @@ components:
example: 10
description: Maximum number of items to return in one page.
required:
- channels
- groups
- total
- level
- offset

PoliciesPage:
type: object
Expand Down
8 changes: 4 additions & 4 deletions auth/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (svc service) RetrieveKey(ctx context.Context, token, id string) (Key, erro

key, err := svc.keys.Retrieve(ctx, issuerID, id)
if err != nil {
return Key{}, errors.Wrap(errRetrieve, err)
return Key{}, errors.Wrap(svcerr.ErrViewEntity, err)
}
return key, nil
}
Expand Down Expand Up @@ -207,7 +207,7 @@ func (svc service) checkPolicy(ctx context.Context, pr PolicyReq) error {
func (svc service) checkDomain(ctx context.Context, subjectType, subject, domainID string) error {
d, err := svc.domains.RetrieveByID(ctx, domainID)
if err != nil {
return errors.Wrap(errors.ErrUnidentified, err)
return errors.Wrap(svcerr.ErrViewEntity, err)
}

switch d.Status {
Expand Down Expand Up @@ -573,7 +573,7 @@ func (svc service) RetrieveDomain(ctx context.Context, token, id string) (Domain
}
dom, err := svc.domains.RetrieveByID(ctx, id)
if err != nil {
return Domain{}, errors.Wrap(svcerr.ErrNotFound, err)
return Domain{}, errors.Wrap(svcerr.ErrViewEntity, err)
}
return dom, nil
}
Expand Down Expand Up @@ -602,7 +602,7 @@ func (svc service) RetrieveDomainPermissions(ctx context.Context, token, id stri
ObjectType: DomainType,
}, []string{AdminPermission, EditPermission, ViewPermission, MembershipPermission})
if err != nil {
return []string{}, err
return []string{}, errors.Wrap(svcerr.ErrViewEntity, err)
}
return lp, nil
}
Expand Down
24 changes: 14 additions & 10 deletions internal/groups/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import (
)

var (
errParentUnAuthz = errors.New("failed to authorize parent group")
errMemberKind = errors.New("invalid member kind")
errRetrieveGroups = errors.New("failed to retrieve groups")
errGroupIDs = errors.New("invalid group ids")
errParentUnAuthz = errors.New("failed to authorize parent group")
errMemberKind = errors.New("invalid member kind")
errGroupIDs = errors.New("invalid group ids")
)

type service struct {
Expand Down Expand Up @@ -70,7 +69,7 @@ func (svc service) CreateGroup(ctx context.Context, token, kind string, g groups

g, err = svc.groups.Save(ctx, g)
if err != nil {
return groups.Group{}, err
return groups.Group{}, errors.Wrap(repoerr.ErrCreateEntity, err)
}
// IMPROVEMENT NOTE: Add defer function , if return err is not nil, then delete group

Expand Down Expand Up @@ -116,7 +115,12 @@ func (svc service) ViewGroup(ctx context.Context, token, id string) (groups.Grou
return groups.Group{}, err
}

return svc.groups.RetrieveByID(ctx, id)
group, err := svc.groups.RetrieveByID(ctx, id)
if err != nil {
return groups.Group{}, errors.Wrap(repoerr.ErrViewEntity, err)
}

return group, nil
}

func (svc service) ViewGroupPerms(ctx context.Context, token, id string) ([]string, error) {
Expand Down Expand Up @@ -228,7 +232,7 @@ func (svc service) ListGroups(ctx context.Context, token, memberKind, memberID s

gp, err := svc.groups.RetrieveByIDs(ctx, gm, ids...)
if err != nil {
return groups.Page{}, err
return groups.Page{}, errors.Wrap(svcerr.ErrViewEntity, err)
}

if gm.ListPerms && len(gp.Groups) > 0 {
Expand Down Expand Up @@ -454,7 +458,7 @@ func (svc service) Assign(ctx context.Context, token, groupID, relation, memberK
func (svc service) assignParentGroup(ctx context.Context, domain, parentGroupID string, groupIDs []string) (err error) {
groupsPage, err := svc.groups.RetrieveByIDs(ctx, groups.Page{PageMeta: groups.PageMeta{Limit: 1<<63 - 1}}, groupIDs...)
if err != nil {
return errors.Wrap(errRetrieveGroups, err)
return errors.Wrap(svcerr.ErrViewEntity, err)
}
if len(groupsPage.Groups) == 0 {
return errGroupIDs
Expand Down Expand Up @@ -500,7 +504,7 @@ func (svc service) assignParentGroup(ctx context.Context, domain, parentGroupID
func (svc service) unassignParentGroup(ctx context.Context, domain, parentGroupID string, groupIDs []string) (err error) {
groupsPage, err := svc.groups.RetrieveByIDs(ctx, groups.Page{PageMeta: groups.PageMeta{Limit: 1<<63 - 1}}, groupIDs...)
if err != nil {
return errors.Wrap(errRetrieveGroups, err)
return errors.Wrap(svcerr.ErrViewEntity, err)
}
if len(groupsPage.Groups) == 0 {
return errGroupIDs
Expand Down Expand Up @@ -691,7 +695,7 @@ func (svc service) changeGroupStatus(ctx context.Context, token string, group gr
}
dbGroup, err := svc.groups.RetrieveByID(ctx, group.ID)
if err != nil {
return groups.Group{}, err
return groups.Group{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
if dbGroup.Status == group.Status {
return groups.Group{}, errors.ErrStatusAlreadyAssigned
Expand Down
Loading

0 comments on commit 3f56a84

Please sign in to comment.