NOISSUE - Add property based testing to users service (#2087)

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
This commit is contained in:
b1ackd0t
2024-03-22 18:16:07 +03:00
committed by GitHub
parent f733147517
commit 70c3d65863
38 changed files with 523 additions and 265 deletions
+58
View File
@@ -0,0 +1,58 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Property Based Tests
on:
push:
branches:
- main
pull_request:
branches:
- main
env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
DOMAINS_URL: http://localhost:8189/domains
USER_IDENTITY: admin@example.com
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
cache-dependency-path: "go.sum"
- name: Build images
run: make all -j $(nproc) && make dockers_dev -j $(nproc)
- name: Start containers
run: make run up args="-d" && sleep 10
- name: Set access token
run: |
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\"}" | jq -r .access_token)
export DOMAIN_ID=$(curl -sSX POST $DOMAINS_URL -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" -d "{\"name\":\"$DOMAIN_NAME\",\"alias\":\"$DOMAIN_NAME\"}" | jq -r .id)
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: Run Users API tests
uses: schemathesis/action@v1
with:
schema: api/openapi/users.yml
base-url: http://localhost:9002
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: Stop containers
if: always()
run: make run down args="-v"
+3
View File
@@ -12,3 +12,6 @@ tools/provision/mgconn.toml
# coverage files
coverage
# Schemathesis
.hypothesis
+15 -1
View File
@@ -97,7 +97,7 @@ FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES))
all: $(SERVICES)
.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs
.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs test_api
clean:
rm -rf ${BUILD_DIR}
@@ -129,6 +129,20 @@ 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
@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 \
--checks all \
--base-url http://localhost:9002 \
--header "Authorization: Bearer $(USER_TOKEN)" \
--contrib-openapi-formats-uuid \
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links
proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./*.proto
+283 -4
View File
@@ -34,6 +34,7 @@ tags:
paths:
/users:
post:
operationId: createUser
tags:
- Users
summary: Registers user account
@@ -49,14 +50,19 @@ paths:
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listUsers
tags:
- Users
summary: List users
@@ -93,6 +99,7 @@ paths:
/users/profile:
get:
operationId: getProfile
summary: Gets info on currently logged in user.
description: |
Gets info on currently logged in user. Info is obtained using
@@ -113,6 +120,7 @@ paths:
/users/{userID}:
get:
operationId: getUser
summary: Retrieves a user
description: |
Retrieves a specific user that is identifier by the user ID.
@@ -129,6 +137,8 @@ paths:
description: Failed due to malformed query parameters.
"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":
@@ -137,6 +147,7 @@ paths:
$ref: "#/components/responses/ServiceError"
patch:
operationId: updateUser
summary: Updates name and metadata of the user.
description: |
Updates name and metadata of the user with provided ID. Name and metadata
@@ -154,15 +165,24 @@ paths:
$ref: "#/components/responses/UserRes"
"400":
description: Failed due to malformed JSON.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Failed due to non existing user.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/users/{userID}/tags:
patch:
operationId: updateUserTags
summary: Updates tags the user.
description: |
Updates tags of the user with provided ID. Tags is updated using
@@ -180,15 +200,22 @@ paths:
$ref: "#/components/responses/UserRes"
"400":
description: Failed due to malformed JSON.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Failed due to non existing user.
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/users/{userID}/identity:
patch:
operationId: updateUserIdentity
summary: Updates Identity of the user.
description: |
Updates identity of the user with provided ID. Identity is
@@ -206,15 +233,24 @@ paths:
$ref: "#/components/responses/UserRes"
"400":
description: Failed due to malformed JSON.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Failed due to non existing user.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/users/{userID}/role:
patch:
operationId: updateUserRole
summary: Updates the user role.
description: |
Updates role for the user with provided ID.
@@ -231,15 +267,22 @@ paths:
$ref: "#/components/responses/UserRes"
"400":
description: Failed due to malformed JSON.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Failed due to non existing user.
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/users/{userID}/disable:
post:
operationId: disableUser
summary: Disables a user
description: |
Disables a specific user that is identifier by the user ID.
@@ -256,8 +299,14 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already disabled user.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -265,6 +314,7 @@ paths:
/users/{userID}/enable:
post:
operationId: enableUser
summary: Enables a user
description: |
Enables a specific user that is identifier by the user ID.
@@ -281,8 +331,14 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already enabled user.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -290,6 +346,7 @@ paths:
/users/secret:
patch:
operationId: updateUserSecret
summary: Updates Secret of currently logged in user.
description: |
Updates secret of currently logged in user. Secret is updated using
@@ -305,15 +362,20 @@ paths:
$ref: "#/components/responses/UserRes"
"400":
description: Failed due to malformed JSON.
"404":
description: Failed due to non existing user.
"401":
description: Missing or invalid access token provided.
"404":
description: Failed due to non existing user.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/password/reset-request:
post:
operationId: requestPasswordReset
summary: User password reset request
description: |
Generates a reset token and sends and
@@ -331,11 +393,14 @@ paths:
description: Failed due to malformed JSON.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/password/reset:
put:
operationId: resetPassword
summary: User password reset endpoint
description: |
When user gets reset token, after he submitted
@@ -350,13 +415,18 @@ paths:
description: User link .
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/groups/{groupID}/users:
get:
operationId: listUsersInGroup
tags:
- Users
summary: List users in a group
@@ -383,6 +453,8 @@ paths:
description: |
Missing or invalid access token provided.
This endpoint is available only for administrators.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
@@ -392,6 +464,7 @@ paths:
/channels/{channelID}/users:
get:
operationId: listUsersInChannel
tags:
- Users
summary: List users in a channel
@@ -418,6 +491,8 @@ paths:
description: |
Missing or invalid access token provided.
This endpoint is available only for administrators.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
@@ -427,6 +502,7 @@ paths:
/users/tokens/issue:
post:
operationId: issueToken
summary: Issue Token
description: |
Issue Access and Refresh Token used for authenticating into the system.
@@ -437,8 +513,12 @@ paths:
responses:
"200":
$ref: "#/components/responses/TokenRes"
"400":
description: Failed due to malformed JSON.
"404":
description: A non-existent entity request.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -446,6 +526,7 @@ paths:
/users/tokens/refresh:
post:
operationId: refreshToken
summary: Refresh Token
description: |
Refreshes Access and Refresh Token used for authenticating into the system.
@@ -456,8 +537,12 @@ paths:
responses:
"200":
$ref: "#/components/responses/TokenRes"
"400":
description: Failed due to malformed JSON.
"404":
description: A non-existent entity request.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -465,6 +550,7 @@ paths:
/groups:
post:
operationId: createGroup
tags:
- Groups
summary: Creates new group
@@ -482,14 +568,19 @@ paths:
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listGroups
summary: Lists groups.
description: |
Lists groups up to a max level of hierarchy that can be fetched in one
@@ -515,13 +606,18 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/groups/{groupID}:
get:
operationId: getGroup
summary: Gets group info.
description: |
Gets info on a group specified by id.
@@ -538,12 +634,17 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateGroup
summary: Updates group data.
description: |
Updates Name, Description or Metadata of a group.
@@ -562,8 +663,16 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
@@ -589,6 +698,7 @@ paths:
/groups/{groupID}/children:
get:
operationId: listChildren
summary: List children of a certain group
description: |
Lists groups up to a max level of hierarchy that can be fetched in one
@@ -615,13 +725,18 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/groups/{groupID}/parents:
get:
operationId: listParents
summary: List parents of a certain group
description: |
Lists groups up to a max level of hierarchy that can be fetched in one
@@ -648,13 +763,18 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/groups/{groupID}/enable:
post:
operationId: enableGroup
summary: Enables a group
description: |
Enables a specific group that is identifier by the group ID.
@@ -671,8 +791,14 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already enabled group.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -680,6 +806,7 @@ paths:
/groups/{groupID}/disable:
post:
operationId: disableGroup
summary: Disables a group
description: |
Disables a specific group that is identifier by the group ID.
@@ -696,8 +823,14 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to already disabled group.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -705,6 +838,7 @@ paths:
/groups/{groupID}/users/assign:
post:
operationId: assignUser
summary: Assigns a user to a group
description: |
Assigns a specific user to a group that is identifier by the group ID.
@@ -723,8 +857,12 @@ paths:
description: Failed due to malformed group's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -732,6 +870,7 @@ paths:
/groups/{groupID}/users/unassign:
post:
operationId: unassignUser
summary: Unassigns a user to a group
description: |
Unassigns a specific user to a group that is identifier by the group ID.
@@ -750,8 +889,12 @@ paths:
description: Failed due to malformed group's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
@@ -759,6 +902,7 @@ paths:
/channels/{memberID}/groups:
get:
operationId: listGroupsInChannel
summary: Get group associated with the member
description: |
Gets groups associated with the channel member specified by id.
@@ -780,13 +924,18 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/users/{memberID}/groups:
get:
operationId: listGroupsByUser
summary: Get group associated with the member
description: |
Gets groups associated with the user member specified by id.
@@ -808,8 +957,12 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Group does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/users:
@@ -845,6 +998,7 @@ paths:
$ref: "#/components/responses/ServiceError"
/health:
get:
operationId: health
summary: Retrieves service health check info.
tags:
- health
@@ -1128,7 +1282,7 @@ components:
required:
- groups
- total
- level
- offset
MembersPage:
type: object
@@ -1212,7 +1366,7 @@ components:
properties:
role:
type: string
enum: ["admin","user"]
enum: ["admin", "user"]
example: user
description: User role example.
required:
@@ -1351,6 +1505,9 @@ components:
schema:
type: string
format: uuid
minLength: 36
maxLength: 36
pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$"
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -1369,6 +1526,7 @@ components:
in: query
schema:
type: string
pattern: "^[^\u0000-\u001F]*$"
required: false
example: "admin@example.com"
@@ -1429,6 +1587,9 @@ components:
schema:
type: string
format: uuid
minLength: 36
maxLength: 36
pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$"
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -1439,6 +1600,9 @@ components:
schema:
type: string
format: uuid
minLength: 36
maxLength: 36
pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$"
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -1449,6 +1613,9 @@ components:
schema:
type: string
format: uuid
minLength: 36
maxLength: 36
pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$"
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -1667,6 +1834,43 @@ components:
application/json:
schema:
$ref: "#/components/schemas/User"
links:
get:
operationId: getUser
parameters:
userID: $response.body#/id
get_groups:
operationId: listUsersInGroup
parameters:
groupID: $response.body#/id
get_channels:
operationId: listUsersInChannel
parameters:
channelID: $response.body#/id
update:
operationId: updateUser
parameters:
userID: $response.body#/id
update_tags:
operationId: updateUserTags
parameters:
userID: $response.body#/id
update_identity:
operationId: updateUserIdentity
parameters:
userID: $response.body#/id
update_role:
operationId: updateUserRole
parameters:
userID: $response.body#/id
disable:
operationId: disableUser
parameters:
userID: $response.body#/id
enable:
operationId: enableUser
parameters:
userID: $response.body#/id
UserRes:
description: Data retrieved.
@@ -1674,6 +1878,15 @@ components:
application/json:
schema:
$ref: "#/components/schemas/User"
links:
get_groups:
operationId: listUsersInGroup
parameters:
groupID: $response.body#/id
get_channels:
operationId: listUsersInChannel
parameters:
channelID: $response.body#/id
UserPageRes:
description: Data retrieved.
@@ -1694,6 +1907,47 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Group"
links:
get:
operationId: getGroup
parameters:
groupID: $response.body#/id
get_children:
operationId: listChildren
parameters:
groupID: $response.body#/id
get_parent:
operationId: listParents
parameters:
groupID: $response.body#/id
get_channels:
operationId: listGroupsInChannel
parameters:
memberID: $response.body#/id
get_users:
operationId: listGroupsByUser
parameters:
memberID: $response.body#/id
update:
operationId: updateGroup
parameters:
groupID: $response.body#/id
disable:
operationId: disableGroup
parameters:
groupID: $response.body#/id
enable:
operationId: enableGroup
parameters:
groupID: $response.body#/id
assign:
operationId: assignUser
parameters:
groupID: $response.body#/id
unassign:
operationId: unassignUser
parameters:
groupID: $response.body#/id
GroupRes:
description: Data retrieved.
@@ -1701,6 +1955,31 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Group"
links:
get_children:
operationId: listChildren
parameters:
groupID: $response.body#/id
get_parent:
operationId: listParents
parameters:
groupID: $response.body#/id
get_channels:
operationId: listGroupsInChannel
parameters:
memberID: $response.body#/id
get_users:
operationId: listGroupsByUser
parameters:
memberID: $response.body#/id
assign:
operationId: assignUser
parameters:
groupID: $response.body#/id
unassign:
operationId: unassignUser
parameters:
groupID: $response.body#/id
GroupPageRes:
description: Data retrieved.
+10 -10
View File
@@ -107,13 +107,13 @@ func (repo domainRepo) RetrievePermissions(ctx context.Context, subject, id stri
rows, err := repo.db.QueryxContext(ctx, q, id, subject)
if err != nil {
return []string{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return []string{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
domains, err := repo.processRows(rows)
if err != nil {
return []string{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return []string{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
permissions := []string{}
@@ -142,18 +142,18 @@ func (repo domainRepo) RetrieveAllByIDs(ctx context.Context, pm auth.Page) (auth
dbPage, err := toDBClientsPage(pm)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.db.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
domains, err := repo.processRows(rows)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
cq := "SELECT COUNT(*) FROM domains d"
@@ -163,7 +163,7 @@ func (repo domainRepo) RetrieveAllByIDs(ctx context.Context, pm auth.Page) (auth
total, err := postgres.Total(ctx, repo.db, cq, dbPage)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
pm.Total = total
@@ -199,18 +199,18 @@ func (repo domainRepo) ListDomains(ctx context.Context, pm auth.Page) (auth.Doma
dbPage, err := toDBClientsPage(pm)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.db.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
domains, err := repo.processRows(rows)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
cq := "SELECT COUNT(*) FROM domains d JOIN policies pc ON pc.object_id = d.id"
@@ -220,7 +220,7 @@ func (repo domainRepo) ListDomains(ctx context.Context, pm auth.Page) (auth.Doma
total, err := postgres.Total(ctx, repo.db, cq, dbPage)
if err != nil {
return auth.DomainsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return auth.DomainsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
pm.Total = total
+9 -22
View File
@@ -18,27 +18,6 @@ import (
const recoveryDuration = 5 * time.Minute
var (
errRollbackPolicy = errors.New("failed to rollback policy")
errRemoveLocalPolicy = errors.New("failed to remove from local policy copy")
errRemovePolicyEngine = errors.New("failed to remove from policy engine")
)
var (
// ErrFailedToRetrieveMembers failed to retrieve group members.
ErrFailedToRetrieveMembers = errors.New("failed to retrieve group members")
// ErrFailedToRetrieveMembership failed to retrieve memberships.
ErrFailedToRetrieveMembership = errors.New("failed to retrieve memberships")
// ErrFailedToRetrieveAll failed to retrieve groups.
ErrFailedToRetrieveAll = errors.New("failed to retrieve all groups")
// ErrFailedToRetrieveParents failed to retrieve groups.
ErrFailedToRetrieveParents = errors.New("failed to retrieve all groups")
// ErrFailedToRetrieveChildren failed to retrieve groups.
ErrFailedToRetrieveChildren = errors.New("failed to retrieve all groups")
// ErrExpiry indicates that the token is expired.
ErrExpiry = errors.New("token is expired")
@@ -51,6 +30,9 @@ var (
errCreateDomainPolicy = errors.New("failed to create domain policy")
errAddPolicies = errors.New("failed to add policies")
errRemovePolicies = errors.New("failed to remove the policies")
errRollbackPolicy = errors.New("failed to rollback policy")
errRemoveLocalPolicy = errors.New("failed to remove from local policy copy")
errRemovePolicyEngine = errors.New("failed to remove from policy engine")
)
// Authn specifies an API that must be fullfiled by the domain service
@@ -358,7 +340,12 @@ func (svc service) CountSubjects(ctx context.Context, pr PolicyReq) (int, error)
}
func (svc service) ListPermissions(ctx context.Context, pr PolicyReq, filterPermisions []string) (Permissions, error) {
return svc.agent.RetrievePermissions(ctx, pr, filterPermisions)
pers, err := svc.agent.RetrievePermissions(ctx, pr, filterPermisions)
if err != nil {
return []string{}, errors.Wrap(svcerr.ErrViewEntity, err)
}
return pers, nil
}
func (svc service) tmpKey(duration time.Duration, key Key) (Token, error) {
+18 -9
View File
@@ -10,7 +10,6 @@ import (
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/internal/apiutil"
"github.com/absmach/magistrala/internal/postgres"
mgclients "github.com/absmach/magistrala/pkg/clients"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
@@ -115,25 +114,32 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
errors.Contains(err, apiutil.ErrLimitSize),
errors.Contains(err, apiutil.ErrBearerKey),
errors.Contains(err, apiutil.ErrNameSize),
errors.Contains(err, svcerr.ErrInvalidStatus),
errors.Contains(err, apiutil.ErrInvalidIDFormat),
errors.Contains(err, apiutil.ErrInvalidQueryParams),
errors.Contains(err, apiutil.ErrInvalidStatus),
errors.Contains(err, apiutil.ErrMissingRelation),
errors.Contains(err, apiutil.ErrValidation),
errors.Contains(err, svcerr.ErrInvalidStatus),
errors.Contains(err, apiutil.ErrInvitationState),
errors.Contains(err, apiutil.ErrInvalidRole),
errors.Contains(err, apiutil.ErrMissingEmail),
errors.Contains(err, apiutil.ErrMissingHost),
errors.Contains(err, apiutil.ErrMissingIdentity),
errors.Contains(err, apiutil.ErrMissingSecret),
errors.Contains(err, apiutil.ErrMissingPass),
errors.Contains(err, apiutil.ErrMissingConfPass),
errors.Contains(err, apiutil.ErrPasswordFormat):
errors.Contains(err, apiutil.ErrInvalidResetPass),
errors.Contains(err, apiutil.ErrMissingRelation),
errors.Contains(err, svcerr.ErrPasswordFormat),
errors.Contains(err, apiutil.ErrInvalidLevel),
errors.Contains(err, apiutil.ErrInvalidQueryParams),
errors.Contains(err, apiutil.ErrValidation):
w.WriteHeader(http.StatusBadRequest)
case errors.Contains(err, svcerr.ErrAuthentication),
errors.Contains(err, svcerr.ErrLogin),
errors.Contains(err, apiutil.ErrBearerToken):
w.WriteHeader(http.StatusUnauthorized)
case errors.Contains(err, svcerr.ErrNotFound):
w.WriteHeader(http.StatusNotFound)
case errors.Contains(err, postgres.ErrMemberAlreadyAssigned),
errors.Contains(err, svcerr.ErrConflict):
case errors.Contains(err, svcerr.ErrConflict),
errors.Contains(err, errors.ErrStatusAlreadyAssigned):
w.WriteHeader(http.StatusConflict)
case errors.Contains(err, svcerr.ErrAuthorization),
errors.Contains(err, svcerr.ErrDomainAuthorization):
@@ -142,9 +148,12 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
w.WriteHeader(http.StatusUnsupportedMediaType)
case errors.Contains(err, svcerr.ErrCreateEntity),
errors.Contains(err, svcerr.ErrUpdateEntity),
errors.Contains(err, svcerr.ErrFailedUpdateRole),
errors.Contains(err, svcerr.ErrViewEntity),
errors.Contains(err, svcerr.ErrAddPolicies),
errors.Contains(err, svcerr.ErrDeletePolicies),
errors.Contains(err, svcerr.ErrRemoveEntity):
w.WriteHeader(http.StatusInternalServerError)
w.WriteHeader(http.StatusUnprocessableEntity)
default:
w.WriteHeader(http.StatusInternalServerError)
}
+2 -2
View File
@@ -294,14 +294,14 @@ func TestEncodeError(t *testing.T) {
code: http.StatusUnsupportedMediaType,
},
{
desc: "InternalServerError",
desc: "StatusUnprocessableEntity",
errs: []error{
svcerr.ErrCreateEntity,
svcerr.ErrUpdateEntity,
svcerr.ErrViewEntity,
svcerr.ErrRemoveEntity,
},
code: http.StatusInternalServerError,
code: http.StatusUnprocessableEntity,
},
{
desc: "InternalServerError",
+3 -3
View File
@@ -114,12 +114,12 @@ var (
// ErrMissingRelation indicates missing relation.
ErrMissingRelation = errors.New("missing relation")
// ErrInvalidRelation indicates an invalid relation.
ErrInvalidRelation = errors.New("invalid relation")
// ErrInvalidAPIKey indicates an invalid API key type.
ErrInvalidAPIKey = errors.New("invalid api key type")
// ErrMaxLevelExceeded indicates an invalid group level.
ErrMaxLevelExceeded = errors.New("invalid group level (should be lower than 5)")
// ErrBootstrapState indicates an invalid bootstrap state.
ErrBootstrapState = errors.New("invalid bootstrap state")
+2 -2
View File
@@ -86,9 +86,9 @@ type groupPageRes struct {
}
type pageRes struct {
Limit uint64 `json:"limit"`
Limit uint64 `json:"limit,omitempty"`
Offset uint64 `json:"offset"`
Total uint64 `json:"total,omitempty"`
Total uint64 `json:"total"`
Level uint64 `json:"level,omitempty"`
}
+8 -8
View File
@@ -160,17 +160,17 @@ func (repo groupRepository) RetrieveAll(ctx context.Context, gm mggroups.Page) (
dbPage, err := toDBGroupPage(gm)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.db.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
items, err := repo.processRows(rows)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
cq := "SELECT COUNT(*) FROM groups g"
@@ -180,7 +180,7 @@ func (repo groupRepository) RetrieveAll(ctx context.Context, gm mggroups.Page) (
total, err := postgres.Total(ctx, repo.db, cq, dbPage)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
page := gm
@@ -208,17 +208,17 @@ func (repo groupRepository) RetrieveByIDs(ctx context.Context, gm mggroups.Page,
dbPage, err := toDBGroupPage(gm)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.db.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
items, err := repo.processRows(rows)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
cq := "SELECT COUNT(*) FROM groups g"
@@ -228,7 +228,7 @@ func (repo groupRepository) RetrieveByIDs(ctx context.Context, gm mggroups.Page,
total, err := postgres.Total(ctx, repo.db, cq, dbPage)
if err != nil {
return mggroups.Page{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mggroups.Page{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
page := gm
+6 -8
View File
@@ -22,8 +22,6 @@ import (
var (
errParentUnAuthz = errors.New("failed to authorize parent group")
errMemberKind = errors.New("invalid member kind")
errAddPolicies = errors.New("failed to add policies")
errDeletePolicies = errors.New("failed to delete policies")
errRetrieveGroups = errors.New("failed to retrieve groups")
errGroupIDs = errors.New("invalid group ids")
)
@@ -286,7 +284,7 @@ func (svc service) checkSuperAdmin(ctx context.Context, userID string) error {
Object: auth.MagistralaObject,
})
if err != nil {
return err
return errors.Wrap(svcerr.ErrAuthorization, err)
}
if !res.Authorized {
return svcerr.ErrAuthorization
@@ -447,7 +445,7 @@ func (svc service) Assign(ctx context.Context, token, groupID, relation, memberK
}
if _, err := svc.auth.AddPolicies(ctx, &policies); err != nil {
return errors.Wrap(errAddPolicies, err)
return errors.Wrap(svcerr.ErrAddPolicies, err)
}
return nil
@@ -598,7 +596,7 @@ func (svc service) Unassign(ctx context.Context, token, groupID, relation, membe
}
if _, err := svc.auth.DeletePolicies(ctx, &policies); err != nil {
return errors.Wrap(errDeletePolicies, err)
return errors.Wrap(svcerr.ErrDeletePolicies, err)
}
return nil
}
@@ -696,7 +694,7 @@ func (svc service) changeGroupStatus(ctx context.Context, token string, group gr
return groups.Group{}, err
}
if dbGroup.Status == group.Status {
return groups.Group{}, mgclients.ErrStatusAlreadyAssigned
return groups.Group{}, errors.ErrStatusAlreadyAssigned
}
group.UpdatedBy = id
@@ -725,7 +723,7 @@ func (svc service) authorizeToken(ctx context.Context, subjectType, subject, per
}
res, err := svc.auth.Authorize(ctx, req)
if err != nil {
return "", err
return "", errors.Wrap(svcerr.ErrAuthorization, err)
}
if !res.GetAuthorized() {
return "", svcerr.ErrAuthorization
@@ -745,7 +743,7 @@ func (svc service) authorizeKind(ctx context.Context, domainID, subjectType, sub
}
res, err := svc.auth.Authorize(ctx, req)
if err != nil {
return "", err
return "", errors.Wrap(svcerr.ErrAuthorization, err)
}
if !res.GetAuthorized() {
return "", svcerr.ErrAuthorization
+2 -3
View File
@@ -17,7 +17,6 @@ import (
"github.com/absmach/magistrala/internal/groups"
"github.com/absmach/magistrala/internal/testsutil"
"github.com/absmach/magistrala/pkg/clients"
mgclients "github.com/absmach/magistrala/pkg/clients"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
@@ -587,7 +586,7 @@ func TestEnableGroup(t *testing.T) {
retrieveResp: mggroups.Group{
Status: clients.Status(groups.EnabledStatus),
},
err: mgclients.ErrStatusAlreadyAssigned,
err: errors.ErrStatusAlreadyAssigned,
},
{
desc: "with retrieve error",
@@ -687,7 +686,7 @@ func TestDisableGroup(t *testing.T) {
retrieveResp: mggroups.Group{
Status: clients.Status(groups.DisabledStatus),
},
err: mgclients.ErrStatusAlreadyAssigned,
err: errors.ErrStatusAlreadyAssigned,
},
{
desc: "with retrieve error",
-33
View File
@@ -6,42 +6,9 @@ package postgres
import (
"context"
"encoding/json"
"errors"
"fmt"
)
var (
// ErrAssignToGroup indicates failure to assign member to a group.
ErrAssignToGroup = errors.New("failed to assign member to a group")
// ErrUnassignFromGroup indicates failure to unassign member from a group.
ErrUnassignFromGroup = errors.New("failed to unassign member from a group")
// ErrMissingParent indicates that parent can't be found.
ErrMissingParent = errors.New("failed to retrieve parent")
// ErrGroupNotEmpty indicates group is not empty, can't be deleted.
ErrGroupNotEmpty = errors.New("group is not empty")
// ErrMemberAlreadyAssigned indicates that members is already assigned.
ErrMemberAlreadyAssigned = errors.New("member is already assigned")
// ErrFailedToRetrieveMembers failed to retrieve group members.
ErrFailedToRetrieveMembers = errors.New("failed to retrieve group members")
// ErrFailedToRetrieveMembership failed to retrieve memberships.
ErrFailedToRetrieveMembership = errors.New("failed to retrieve memberships")
// ErrFailedToRetrieveAll failed to retrieve groups.
ErrFailedToRetrieveAll = errors.New("failed to retrieve all groups")
// ErrFailedToRetrieveParents failed to retrieve groups.
ErrFailedToRetrieveParents = errors.New("failed to retrieve all groups")
// ErrFailedToRetrieveChildren failed to retrieve groups.
ErrFailedToRetrieveChildren = errors.New("failed to retrieve all groups")
)
func CreateMetadataQuery(entity string, um map[string]interface{}) (string, []byte, error) {
if len(um) == 0 {
return "", nil, nil
+1 -1
View File
@@ -266,7 +266,7 @@ func TestListInvitation(t *testing.T) {
desc: "with invalid state",
token: validToken,
query: "state=invalid",
status: http.StatusInternalServerError,
status: http.StatusBadRequest,
contentType: validContenType,
svcErr: nil,
},
+3 -8
View File
@@ -4,7 +4,6 @@
package api
import (
"errors"
"fmt"
"testing"
@@ -14,11 +13,7 @@ import (
"github.com/stretchr/testify/assert"
)
var (
errMissingRelation = errors.New("missing relation")
errInvalidRelation = errors.New("invalid relation")
valid = "valid"
)
var valid = "valid"
func TestSendInvitationReqValidation(t *testing.T) {
cases := []struct {
@@ -79,7 +74,7 @@ func TestSendInvitationReqValidation(t *testing.T) {
Relation: "",
Resend: true,
},
err: errMissingRelation,
err: apiutil.ErrMissingRelation,
},
{
desc: "invalid relation",
@@ -90,7 +85,7 @@ func TestSendInvitationReqValidation(t *testing.T) {
Relation: "invalid",
Resend: true,
},
err: errInvalidRelation,
err: apiutil.ErrInvalidRelation,
},
}
+3 -8
View File
@@ -6,15 +6,10 @@ package invitations
import (
"context"
"encoding/json"
"errors"
"time"
"github.com/absmach/magistrala/auth"
)
var (
errMissingRelation = errors.New("missing relation")
errInvalidRelation = errors.New("invalid relation")
"github.com/absmach/magistrala/internal/apiutil"
)
// Invitation is an invitation to join a domain.
@@ -122,7 +117,7 @@ type Repository interface {
// It returns an error if the relation is empty or invalid.
func CheckRelation(relation string) error {
if relation == "" {
return errMissingRelation
return apiutil.ErrMissingRelation
}
if relation != auth.AdministratorRelation &&
relation != auth.EditorRelation &&
@@ -133,7 +128,7 @@ func CheckRelation(relation string) error {
relation != auth.RoleGroupRelation &&
relation != auth.GroupRelation &&
relation != auth.PlatformRelation {
return errInvalidRelation
return apiutil.ErrInvalidRelation
}
return nil
+3 -8
View File
@@ -4,19 +4,14 @@
package invitations_test
import (
"errors"
"fmt"
"testing"
"github.com/absmach/magistrala/internal/apiutil"
"github.com/absmach/magistrala/invitations"
"github.com/stretchr/testify/assert"
)
var (
errMissingRelation = errors.New("missing relation")
errInvalidRelation = errors.New("invalid relation")
)
func TestInvitation_MarshalJSON(t *testing.T) {
cases := []struct {
desc string
@@ -60,8 +55,8 @@ func TestCheckRelation(t *testing.T) {
relation string
err error
}{
{"", errMissingRelation},
{"admin", errInvalidRelation},
{"", apiutil.ErrMissingRelation},
{"admin", apiutil.ErrInvalidRelation},
{"editor", nil},
{"viewer", nil},
{"member", nil},
+2 -2
View File
@@ -5,7 +5,6 @@ package invitations_test
import (
"context"
"errors"
"math/rand"
"testing"
"time"
@@ -13,6 +12,7 @@ import (
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
authmocks "github.com/absmach/magistrala/auth/mocks"
"github.com/absmach/magistrala/internal/apiutil"
"github.com/absmach/magistrala/internal/testsutil"
"github.com/absmach/magistrala/invitations"
"github.com/absmach/magistrala/invitations/mocks"
@@ -79,7 +79,7 @@ func TestSendInvitation(t *testing.T) {
token: validToken,
tokenUserID: testsutil.GenerateUUID(t),
req: invitations.Invitation{Relation: "invalid"},
err: errors.New("invalid relation"),
err: apiutil.ErrInvalidRelation,
authNErr: nil,
domainErr: nil,
adminErr: nil,
+6 -6
View File
@@ -149,11 +149,11 @@ func (repo *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clien
dbPage, err := ToDBClientsPage(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
@@ -197,12 +197,12 @@ func (repo *Repository) RetrieveAllBasicInfo(ctx context.Context, pm clients.Pag
dbPage, err := ToDBClientsPage(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
@@ -255,11 +255,11 @@ func (repo *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (
dbPage, err := ToDBClientsPage(pm)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return clients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
-4
View File
@@ -5,7 +5,6 @@ package clients
import (
"encoding/json"
"errors"
"strings"
"github.com/absmach/magistrala/internal/apiutil"
@@ -36,9 +35,6 @@ const (
Unknown = "unknown"
)
// ErrStatusAlreadyAssigned indicated that the client or group has already been assigned the status.
var ErrStatusAlreadyAssigned = errors.New("status already assigned")
// String converts client/group status to string literal.
func (s Status) String() string {
switch s {
+3
View File
@@ -48,4 +48,7 @@ var (
// ErrInvalidSecret indicates invalid secret.
ErrInvalidSecret = errors.New("missing secret")
// ErrFailedToRetrieveAllGroups failed to retrieve groups.
ErrFailedToRetrieveAllGroups = errors.New("failed to retrieve all groups")
)
+18
View File
@@ -48,4 +48,22 @@ var (
// ErrInvalidPolicy indicates that an invalid policy.
ErrInvalidPolicy = errors.New("invalid policy")
// ErrRecoveryToken indicates error in generating password recovery token.
ErrRecoveryToken = errors.New("failed to generate password recovery token")
// ErrFailedPolicyUpdate indicates a failure to update user policy.
ErrFailedPolicyUpdate = errors.New("failed to update user policy")
// ErrAddPolicies indicates failed to add policies.
ErrAddPolicies = errors.New("failed to add policies")
// ErrDeletePolicies indicates failed to delete policies.
ErrDeletePolicies = errors.New("failed to delete policies")
// ErrPasswordFormat indicates weak password.
ErrPasswordFormat = errors.New("password does not meet the requirements")
// ErrFailedUpdateRole indicates a failure to update user role.
ErrFailedUpdateRole = errors.New("failed to update user role")
)
+3
View File
@@ -17,4 +17,7 @@ var (
// ErrEmptyPath indicates empty file path.
ErrEmptyPath = errors.New("empty file path")
// ErrStatusAlreadyAssigned indicated that the client or group has already been assigned the status.
ErrStatusAlreadyAssigned = errors.New("status already assigned")
)
-3
View File
@@ -14,7 +14,4 @@ var (
// ErrDisableGroup indicates error in disabling group.
ErrDisableGroup = errors.New("failed to disable group")
// ErrStatusAlreadyAssigned indicated that the group has already been assigned the status.
ErrStatusAlreadyAssigned = errors.New("status already assigned")
)
+4 -4
View File
@@ -110,7 +110,7 @@ func TestCreateChannel(t *testing.T) {
Status: mgclients.EnabledStatus.String(),
},
token: token,
err: errors.NewSDKErrorWithStatus(repoerr.ErrCreateEntity, http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(repoerr.ErrCreateEntity, http.StatusUnprocessableEntity),
},
{
desc: "create channel with missing name",
@@ -464,7 +464,7 @@ func TestUpdateChannel(t *testing.T) {
},
response: sdk.Channel{},
token: invalidToken,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusForbidden),
},
{
desc: "update channel description with invalid token",
@@ -474,7 +474,7 @@ func TestUpdateChannel(t *testing.T) {
},
response: sdk.Channel{},
token: invalidToken,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusForbidden),
},
{
desc: "update channel metadata with invalid token",
@@ -486,7 +486,7 @@ func TestUpdateChannel(t *testing.T) {
},
response: sdk.Channel{},
token: invalidToken,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusForbidden),
},
{
desc: "update channel that can't be marshalled",
+4 -4
View File
@@ -98,7 +98,7 @@ func TestCreateGroup(t *testing.T) {
ParentID: wrongID,
Status: clients.EnabledStatus.String(),
},
err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(svcerr.ErrCreateEntity, http.StatusUnprocessableEntity),
},
{
desc: "create group with missing name",
@@ -721,7 +721,7 @@ func TestUpdateGroup(t *testing.T) {
},
response: sdk.Group{},
token: invalidToken,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusForbidden),
},
{
desc: "update group description with invalid token",
@@ -731,7 +731,7 @@ func TestUpdateGroup(t *testing.T) {
},
response: sdk.Group{},
token: invalidToken,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusForbidden),
},
{
desc: "update group metadata with invalid token",
@@ -743,7 +743,7 @@ func TestUpdateGroup(t *testing.T) {
},
response: sdk.Group{},
token: invalidToken,
err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusForbidden),
},
{
desc: "update a group that can't be marshalled",
+4 -4
View File
@@ -97,7 +97,7 @@ func TestCreateThing(t *testing.T) {
response: sdk.Thing{},
token: token,
repoErr: sdk.ErrFailedCreation,
err: errors.NewSDKErrorWithStatus(errors.Wrap(sdk.ErrFailedCreation, repoerr.ErrCreateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(sdk.ErrFailedCreation, repoerr.ErrCreateEntity), http.StatusUnprocessableEntity),
},
{
desc: "register empty thing",
@@ -246,7 +246,7 @@ func TestCreateThings(t *testing.T) {
things: thingsList,
response: []sdk.Thing{},
token: token,
err: errors.NewSDKErrorWithStatus(errors.Wrap(sdk.ErrFailedCreation, sdk.ErrFailedCreation), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(sdk.ErrFailedCreation, sdk.ErrFailedCreation), http.StatusUnprocessableEntity),
},
{
desc: "register empty things",
@@ -725,7 +725,7 @@ func TestUpdateThing(t *testing.T) {
thing: thing2,
response: sdk.Thing{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusUnprocessableEntity),
},
{
desc: "update thing that can't be marshalled",
@@ -810,7 +810,7 @@ func TestUpdateThingTags(t *testing.T) {
thing: thing2,
response: sdk.Thing{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusUnprocessableEntity),
},
{
desc: "update thing that can't be marshalled",
+6 -7
View File
@@ -89,7 +89,7 @@ func TestCreateClient(t *testing.T) {
client: user,
response: sdk.User{},
token: token,
err: errors.NewSDKErrorWithStatus(errors.Wrap(sdk.ErrFailedCreation, sdk.ErrFailedCreation), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(sdk.ErrFailedCreation, sdk.ErrFailedCreation), http.StatusUnprocessableEntity),
},
{
desc: "register empty user",
@@ -350,7 +350,6 @@ func TestListClients(t *testing.T) {
for _, tc := range cases {
pm := sdk.PageMetadata{
Status: tc.status,
Total: total,
Offset: tc.offset,
Limit: tc.limit,
Name: tc.name,
@@ -552,7 +551,7 @@ func TestUpdateClient(t *testing.T) {
client: client2,
response: sdk.User{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusUnprocessableEntity),
},
{
desc: "update a user that can't be marshalled",
@@ -643,7 +642,7 @@ func TestUpdateClientTags(t *testing.T) {
client: client2,
response: sdk.User{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusUnprocessableEntity),
},
{
desc: "update a user that can't be marshalled",
@@ -733,7 +732,7 @@ func TestUpdateClientIdentity(t *testing.T) {
client: client2,
response: sdk.User{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusUnprocessableEntity),
},
{
desc: "update a user that can't be marshalled",
@@ -749,7 +748,7 @@ func TestUpdateClientIdentity(t *testing.T) {
},
response: sdk.User{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, svcerr.ErrUpdateEntity), http.StatusUnprocessableEntity),
},
}
@@ -901,7 +900,7 @@ func TestUpdateClientRole(t *testing.T) {
client: client2,
response: sdk.User{},
token: validToken,
err: errors.NewSDKErrorWithStatus(errors.Wrap(users.ErrFailedUpdateRole, users.ErrFailedUpdateRole), http.StatusInternalServerError),
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrFailedUpdateRole, svcerr.ErrFailedUpdateRole), http.StatusUnprocessableEntity),
},
{
desc: "update a user that can't be marshalled",
+1 -1
View File
@@ -507,7 +507,7 @@ func (svc service) changeClientStatus(ctx context.Context, token string, client
return mgclients.Client{}, errors.Wrap(repoerr.ErrNotFound, err)
}
if dbClient.Status == client.Status {
return mgclients.Client{}, mgclients.ErrStatusAlreadyAssigned
return mgclients.Client{}, errors.ErrStatusAlreadyAssigned
}
client.UpdatedBy = userID
+4 -4
View File
@@ -1079,8 +1079,8 @@ func TestEnableClient(t *testing.T) {
changeStatusResponse: enabledClient1,
retrieveByIDResponse: enabledClient1,
authorizeResponse: &magistrala.AuthorizeRes{Authorized: true},
changeStatusErr: mgclients.ErrStatusAlreadyAssigned,
err: mgclients.ErrStatusAlreadyAssigned,
changeStatusErr: errors.ErrStatusAlreadyAssigned,
err: errors.ErrStatusAlreadyAssigned,
},
{
desc: "enable non-existing client",
@@ -1236,8 +1236,8 @@ func TestDisableClient(t *testing.T) {
changeStatusResponse: mgclients.Client{},
retrieveByIDResponse: disabledClient1,
authorizeResponse: &magistrala.AuthorizeRes{Authorized: true},
changeStatusErr: mgclients.ErrStatusAlreadyAssigned,
err: mgclients.ErrStatusAlreadyAssigned,
changeStatusErr: errors.ErrStatusAlreadyAssigned,
err: errors.ErrStatusAlreadyAssigned,
},
{
desc: "disable non-existing client",
+17 -15
View File
@@ -32,6 +32,7 @@ func clientsHandler(svc users.Service, r *chi.Mux, logger *slog.Logger, pr *rege
opts := []kithttp.ServerOption{
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)),
}
r.Route("/users", func(r chi.Router) {
r.Post("/", otelhttp.NewHandler(kithttp.NewServer(
registrationEndpoint(svc),
@@ -89,20 +90,6 @@ func clientsHandler(svc users.Service, r *chi.Mux, logger *slog.Logger, pr *rege
opts...,
), "update_client_identity").ServeHTTP)
r.Post("/password/reset-request", otelhttp.NewHandler(kithttp.NewServer(
passwordResetRequestEndpoint(svc),
decodePasswordResetRequest,
api.EncodeResponse,
opts...,
), "password_reset_req").ServeHTTP)
r.Put("/password/reset", otelhttp.NewHandler(kithttp.NewServer(
passwordResetEndpoint(svc),
decodePasswordReset,
api.EncodeResponse,
opts...,
), "password_reset").ServeHTTP)
r.Patch("/{id}/role", otelhttp.NewHandler(kithttp.NewServer(
updateClientRoleEndpoint(svc),
decodeUpdateClientRole,
@@ -139,6 +126,22 @@ func clientsHandler(svc users.Service, r *chi.Mux, logger *slog.Logger, pr *rege
), "disable_client").ServeHTTP)
})
r.Route("/password", func(r chi.Router) {
r.Post("/reset-request", otelhttp.NewHandler(kithttp.NewServer(
passwordResetRequestEndpoint(svc),
decodePasswordResetRequest,
api.EncodeResponse,
opts...,
), "password_reset_req").ServeHTTP)
r.Put("/reset", otelhttp.NewHandler(kithttp.NewServer(
passwordResetEndpoint(svc),
decodePasswordReset,
api.EncodeResponse,
opts...,
), "password_reset").ServeHTTP)
})
// Ideal location: users service, groups endpoint.
// Reason for placing here :
// SpiceDB provides list of user ids in given user_group_id
@@ -228,7 +231,6 @@ func decodeListClients(_ context.Context, r *http.Request) (interface{}, error)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
order, err := apiutil.ReadStringQuery(r, api.OrderKey, api.DefOrder)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
+4 -53
View File
@@ -456,13 +456,6 @@ func TestListClients(t *testing.T) {
status: http.StatusOK,
err: nil,
},
{
desc: "list users with invalid name",
token: validToken,
query: "name=invalid",
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate name",
token: validToken,
@@ -510,13 +503,6 @@ func TestListClients(t *testing.T) {
status: http.StatusOK,
err: nil,
},
{
desc: "list users with invalid tags",
token: validToken,
query: "tag=invalid",
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate tags",
token: validToken,
@@ -564,13 +550,6 @@ func TestListClients(t *testing.T) {
status: http.StatusOK,
err: nil,
},
{
desc: "list users with invalid permissions",
token: validToken,
query: "permission=invalid",
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate permissions",
token: validToken,
@@ -591,13 +570,6 @@ func TestListClients(t *testing.T) {
status: http.StatusOK,
err: nil,
},
{
desc: "list users with invalid list perms",
token: validToken,
query: "list_perms=invalid",
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate list perms",
token: validToken,
@@ -620,13 +592,6 @@ func TestListClients(t *testing.T) {
status: http.StatusOK,
err: nil,
},
{
desc: "list users with invalid identity",
token: validToken,
query: "identity=invalid",
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate identity",
token: validToken,
@@ -649,13 +614,6 @@ func TestListClients(t *testing.T) {
status: http.StatusOK,
err: nil,
},
{
desc: "list users with invalid order",
token: validToken,
query: "order=invalid",
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate order",
token: validToken,
@@ -663,13 +621,6 @@ func TestListClients(t *testing.T) {
status: http.StatusBadRequest,
err: apiutil.ErrInvalidQueryParams,
},
{
desc: "list users with invalid order direction",
token: validToken,
query: "dir=invalid",
status: http.StatusInternalServerError,
err: apiutil.ErrValidation,
},
{
desc: "list users with duplicate order direction",
token: validToken,
@@ -1082,7 +1033,7 @@ func TestPasswordResetRequest(t *testing.T) {
desc: "password reset request with empty email",
data: fmt.Sprintf(`{"email": "%s", "host": "%s"}`, "", testhost),
contentType: contentType,
status: http.StatusInternalServerError,
status: http.StatusBadRequest,
err: apiutil.ErrValidation,
},
{
@@ -1119,7 +1070,7 @@ func TestPasswordResetRequest(t *testing.T) {
req := testRequest{
client: us.Client(),
method: http.MethodPost,
url: fmt.Sprintf("%s/users/password/reset-request", us.URL),
url: fmt.Sprintf("%s/password/reset-request", us.URL),
contentType: tc.contentType,
body: strings.NewReader(tc.data),
}
@@ -1207,7 +1158,7 @@ func TestPasswordReset(t *testing.T) {
req := testRequest{
client: us.Client(),
method: http.MethodPut,
url: fmt.Sprintf("%s/users/password/reset", us.URL),
url: fmt.Sprintf("%s/password/reset", us.URL),
contentType: tc.contentType,
token: tc.token,
body: strings.NewReader(tc.data),
@@ -1276,7 +1227,7 @@ func TestUpdateClientRole(t *testing.T) {
clientID: client.ID,
token: validToken,
contentType: contentType,
status: http.StatusInternalServerError,
status: http.StatusBadRequest,
err: svcerr.ErrInvalidRole,
},
{
+2 -2
View File
@@ -25,8 +25,8 @@ var (
type pageRes struct {
Limit uint64 `json:"limit,omitempty"`
Offset uint64 `json:"offset,omitempty"`
Total uint64 `json:"total,omitempty"`
Offset uint64 `json:"offset"`
Total uint64 `json:"total"`
}
type createClientRes struct {
+6 -6
View File
@@ -12,7 +12,6 @@ import (
pgclients "github.com/absmach/magistrala/pkg/clients/postgres"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
)
var _ mgclients.Repository = (*clientRepo)(nil)
@@ -79,17 +78,18 @@ func (repo clientRepo) CheckSuperAdmin(ctx context.Context, adminID string) erro
q := "SELECT 1 FROM clients WHERE id = $1 AND role = $2"
rows, err := repo.DB.QueryContext(ctx, q, adminID, mgclients.AdminRole)
if err != nil {
return errors.Wrap(svcerr.ErrAuthorization, err)
return postgres.HandleError(repoerr.ErrViewEntity, err)
}
defer rows.Close()
if rows.Next() {
if err := rows.Err(); err != nil {
return errors.Wrap(svcerr.ErrAuthorization, err)
return postgres.HandleError(repoerr.ErrViewEntity, err)
}
return nil
}
return svcerr.ErrAuthorization
return repoerr.ErrNotFound
}
func (repo clientRepo) RetrieveByID(ctx context.Context, id string) (mgclients.Client, error) {
@@ -134,11 +134,11 @@ func (repo clientRepo) RetrieveAll(ctx context.Context, pm mgclients.Page) (mgcl
dbPage, err := pgclients.ToDBClientsPage(pm)
if err != nil {
return mgclients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mgclients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
if err != nil {
return mgclients.ClientsPage{}, errors.Wrap(postgres.ErrFailedToRetrieveAll, err)
return mgclients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
}
defer rows.Close()
+1 -2
View File
@@ -14,7 +14,6 @@ import (
mgclients "github.com/absmach/magistrala/pkg/clients"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
cpostgres "github.com/absmach/magistrala/users/postgres"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -232,7 +231,7 @@ func TestIsPlatformAdmin(t *testing.T) {
Status: mgclients.EnabledStatus,
Role: mgclients.UserRole,
},
err: svcerr.ErrAuthorization,
err: repoerr.ErrNotFound,
},
}
+6 -15
View File
@@ -20,22 +20,13 @@ import (
)
var (
// ErrRecoveryToken indicates error in generating password recovery token.
ErrRecoveryToken = errors.New("failed to generate password recovery token")
// ErrFailedPolicyUpdate indicates a failure to update user policy.
ErrFailedPolicyUpdate = errors.New("failed to update user policy")
// ErrFailedUpdateRole indicates a failure to update user role.
ErrFailedUpdateRole = errors.New("failed to update user role")
// ErrAddPolicies indictaed a failre to add policies.
errAddPolicies = errors.New("failed to add policies")
// ErrIssueToken indicates a failure to issue token.
ErrIssueToken = errors.New("failed to issue token")
// ErrAddPolicies indictaed a failre to add policies.
// errDeletePolicies indictaed a failre to add policies.
errDeletePolicies = errors.New("failed to delete policies")
)
@@ -288,7 +279,7 @@ func (svc service) GenerateResetToken(ctx context.Context, email, host string) e
}
token, err := svc.auth.Issue(ctx, issueReq)
if err != nil {
return errors.Wrap(ErrRecoveryToken, err)
return errors.Wrap(svcerr.ErrRecoveryToken, err)
}
return svc.SendPasswordReset(ctx, host, email, client.Name, token.AccessToken)
@@ -374,7 +365,7 @@ func (svc service) UpdateClientRole(ctx context.Context, token string, cli mgcli
}
if err := svc.updateClientPolicy(ctx, cli.ID, cli.Role); err != nil {
return mgclients.Client{}, errors.Wrap(ErrFailedPolicyUpdate, err)
return mgclients.Client{}, errors.Wrap(svcerr.ErrFailedPolicyUpdate, err)
}
client, err = svc.clients.UpdateRole(ctx, client)
if err != nil {
@@ -382,7 +373,7 @@ func (svc service) UpdateClientRole(ctx context.Context, token string, cli mgcli
if errRollback := svc.updateClientPolicy(ctx, cli.ID, mgclients.UserRole); errRollback != nil {
return mgclients.Client{}, errors.Wrap(err, errors.Wrap(repoerr.ErrRollbackTx, errRollback))
}
return mgclients.Client{}, errors.Wrap(ErrFailedUpdateRole, err)
return mgclients.Client{}, errors.Wrap(svcerr.ErrFailedUpdateRole, err)
}
return client, nil
}
@@ -428,7 +419,7 @@ func (svc service) changeClientStatus(ctx context.Context, token string, client
return mgclients.Client{}, errors.Wrap(repoerr.ErrNotFound, err)
}
if dbClient.Status == client.Status {
return mgclients.Client{}, mgclients.ErrStatusAlreadyAssigned
return mgclients.Client{}, errors.ErrStatusAlreadyAssigned
}
client.UpdatedBy = tokenUserID
@@ -570,7 +561,7 @@ func (svc *service) authorize(ctx context.Context, subjType, subjKind, subj, per
}
if !res.GetAuthorized() {
return "", errors.Wrap(svcerr.ErrAuthorization, err)
return "", svcerr.ErrAuthorization
}
return res.GetId(), nil
}
+3 -3
View File
@@ -1327,7 +1327,7 @@ func TestEnableClient(t *testing.T) {
identifyResponse: &magistrala.IdentityRes{UserId: enabledClient1.ID},
authorizeResponse: &magistrala.AuthorizeRes{Authorized: true},
retrieveByIDResponse: enabledClient1,
err: mgclients.ErrStatusAlreadyAssigned,
err: errors.ErrStatusAlreadyAssigned,
},
{
desc: "enable disabled client with failed to change status",
@@ -1514,7 +1514,7 @@ func TestDisableClient(t *testing.T) {
identifyResponse: &magistrala.IdentityRes{UserId: disabledClient1.ID},
authorizeResponse: &magistrala.AuthorizeRes{Authorized: true},
retrieveByIDResponse: disabledClient1,
err: mgclients.ErrStatusAlreadyAssigned,
err: errors.ErrStatusAlreadyAssigned,
},
{
desc: "disable enabled client with failed to change status",
@@ -2256,7 +2256,7 @@ func TestGenerateResetToken(t *testing.T) {
retrieveByIdentityResponse: client,
issueResponse: &magistrala.Token{},
issueErr: svcerr.ErrAuthorization,
err: users.ErrRecoveryToken,
err: svcerr.ErrRecoveryToken,
},
}