1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-26 13:48:53 +08:00
Dušan Borovčanin 55e09c1921
MF-1506 - Group-based Access Control (#1716)
* Move Things and Users to Clients

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Update Add and Delete Policies (#1792)

* Remove Policy Action Ranks

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Rebase Issues

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix CI Test Errors

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Adding Check on Subject For Clients

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove Check Client Exists

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Check When Sharing Clients

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Only Add User to Group When Sharing Things

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove clientType

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Minor Fix on ShareClient and Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Policies Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Clean Up Things Authorization

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests on RetrieveAll

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Test ShareThing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Merge Conflicts

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove Adding Policies. Only Use Ownership

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Check If Subject is same as Object

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Move Back To Union As Sometimes Policy is Empty and Fails to Evaluate on Ownership

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Entity Type For Failing Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix BUG in policy evaluation

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Comments Regarding checkAdmin

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests On Rebase

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Combine Authorize For Things and Users

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests On Rebase

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Error on Things SVC `unsupported protocol scheme`

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Fix Bug on Things Authorization Cache (#1810)

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Use Password instead of username in MQTT handler

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Simplify MQTT authorization

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Fix MQTT tests

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add More Functions to SDK (#1811)

* Add More Functions to SDK

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Examples to GoDoc

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Update Unassign Interface

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Pass Subject as ID and Not Token on List Channels By Thing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Bootstrap Errors For Element Check

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add empty line Before Return

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Reorder URLS in things mux

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Listing Things Policies

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Share Thing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Examples to CLI Docs

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Update Identity To Update Another User

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Identify an Update Policies on Things

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Update Things Policies

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix GoDocs on Disconnect

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Change Authorize To Use AccessRequest

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* For Evaluate Policy Use AccessRequest (#1814)

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add SDK Tests (#1812)

* Add Things Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Channel Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Certs Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Consumer Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Enrich Group Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Tests For Health

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Tests For Tokens

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename SDK for Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Policies Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Linter

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Make Variable Defination Inline

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Make Cache Key Duration Configurable (#1815)

* Make Cache Key Duration Configurable

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename ENV Var

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Update GoDocs (#1816)

* Add GoDocs

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Missing GoDoc Files

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Enable godot

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add License Information

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add Call Home Client to Mainflux services (#1751)

* Move Things and Users to Clients

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>

* collect and send data package

Signed-off-by: SammyOina <sammyoina@gmail.com>

* create telemetry migrations

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add telemetry endpoints

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add transport

Signed-off-by: SammyOina <sammyoina@gmail.com>

* create service

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove homing server

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home to adapters

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add last seen

Signed-off-by: SammyOina <sammyoina@gmail.com>

* rename logger

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove homing client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use unmerged repo

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use renamed module

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* edit documentation

Signed-off-by: SammyOina <sammyoina@gmail.com>

* align table

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use alias for call home client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update callhome

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home pkg

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home

Signed-off-by: SammyOina <sammyoina@gmail.com>

* fix modules

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use mf build version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use mf build version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore default

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home for users and things

Signed-off-by: SammyOina <sammyoina@gmail.com>

* enable opting on call home

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove full stops

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update callhome client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home to all services

Signed-off-by: SammyOina <sammyoina@gmail.com>

* fix build

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore sdk tests

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove unnecessary changes

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore health_test.go

Signed-off-by: SammyOina <sammyoina@gmail.com>

---------

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>
Co-authored-by: b1ackd0t <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

---------

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>
Co-authored-by: b1ackd0t <blackd0t@protonmail.com>
Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com>
2023-06-14 12:40:37 +02:00

1063 lines
29 KiB
Go

// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
package sdk
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/mainflux/mainflux/pkg/errors"
)
const (
// CTJSON represents JSON content type.
CTJSON ContentType = "application/json"
// CTJSONSenML represents JSON SenML content type.
CTJSONSenML ContentType = "application/senml+json"
// CTBinary represents binary content type.
CTBinary ContentType = "application/octet-stream"
// EnabledStatus represents enable status for a client.
EnabledStatus = "enabled"
// DisabledStatus represents disabled status for a client.
DisabledStatus = "disabled"
BearerPrefix = "Bearer "
ThingPrefix = "Thing "
)
// ContentType represents all possible content types.
type ContentType string
var _ SDK = (*mfSDK)(nil)
var (
// ErrFailedCreation indicates that entity creation failed.
ErrFailedCreation = errors.New("failed to create entity in the db")
// ErrFailedList indicates that entities list failed.
ErrFailedList = errors.New("failed to list entities")
// ErrFailedUpdate indicates that entity update failed.
ErrFailedUpdate = errors.New("failed to update entity")
// ErrFailedFetch indicates that fetching of entity data failed.
ErrFailedFetch = errors.New("failed to fetch entity")
// ErrFailedRemoval indicates that entity removal failed.
ErrFailedRemoval = errors.New("failed to remove entity")
// ErrFailedEnable indicates that client enable failed.
ErrFailedEnable = errors.New("failed to enable client")
// ErrFailedDisable indicates that client disable failed.
ErrFailedDisable = errors.New("failed to disable client")
)
type PageMetadata struct {
Total uint64 `json:"total"`
Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"`
Level uint64 `json:"level,omitempty"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
Status string `json:"status,omitempty"`
Action string `json:"action,omitempty"`
Subject string `json:"subject,omitempty"`
Object string `json:"object,omitempty"`
Tag string `json:"tag,omitempty"`
Owner string `json:"owner,omitempty"`
SharedBy string `json:"shared_by,omitempty"`
Visibility string `json:"visibility,omitempty"`
OwnerID string `json:"owner_id,omitempty"`
Topic string `json:"topic,omitempty"`
Contact string `json:"contact,omitempty"`
State string `json:"state,omitempty"`
}
// Credentials represent client credentials: it contains
// "identity" which can be a username, email, generated name;
// and "secret" which can be a password or access token.
type Credentials struct {
Identity string `json:"identity,omitempty"` // username or generated login ID
Secret string `json:"secret,omitempty"` // password or token
}
// SDK contains Mainflux API.
type SDK interface {
// CreateUser registers mainflux user.
//
// example:
// user := sdk.User{
// Name: "John Doe",
// Credentials: sdk.Credentials{
// Identity: "john.doe@example",
// Secret: "12345678",
// },
// }
// user, _ := sdk.CreateUser(user)
// fmt.Println(user)
CreateUser(user User, token string) (User, errors.SDKError)
// User returns user object by id.
//
// example:
// user, _ := sdk.User("userID", "token")
// fmt.Println(user)
User(id, token string) (User, errors.SDKError)
// Users returns list of users.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "John Doe",
// }
// users, _ := sdk.Users(pm, "token")
// fmt.Println(users)
Users(pm PageMetadata, token string) (UsersPage, errors.SDKError)
// Members retrieves everything that is assigned to a group identified by groupID.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// }
// members, _ := sdk.Members("groupID", pm, "token")
// fmt.Println(members)
Members(groupID string, meta PageMetadata, token string) (MembersPage, errors.SDKError)
// UserProfile returns user logged in.
//
// example:
// user, _ := sdk.UserProfile("token")
// fmt.Println(user)
UserProfile(token string) (User, errors.SDKError)
// UpdateUser updates existing user.
//
// example:
// user := sdk.User{
// ID: "userID",
// Name: "John Doe",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// user, _ := sdk.UpdateUser(user, "token")
// fmt.Println(user)
UpdateUser(user User, token string) (User, errors.SDKError)
// UpdateUserTags updates the user's tags.
//
// example:
// user := sdk.User{
// ID: "userID",
// Tags: []string{"tag1", "tag2"},
// }
// user, _ := sdk.UpdateUserTags(user, "token")
// fmt.Println(user)
UpdateUserTags(user User, token string) (User, errors.SDKError)
// UpdateUserIdentity updates the user's identity
//
// example:
// user := sdk.User{
// ID: "userID",
// Credentials: sdk.Credentials{
// Identity: "john.doe@example",
// },
// }
// user, _ := sdk.UpdateUserIdentity(user, "token")
// fmt.Println(user)
UpdateUserIdentity(user User, token string) (User, errors.SDKError)
// UpdateUserOwner updates the user's owner.
//
// example:
// user := sdk.User{
// ID: "userID",
// Owner: "ownerID",
// }
// user, _ := sdk.UpdateUserOwner(user, "token")
// fmt.Println(user)
UpdateUserOwner(user User, token string) (User, errors.SDKError)
// UpdatePassword updates user password.
//
// example:
// user, _ := sdk.UpdatePassword("oldPass", "newPass", "token")
// fmt.Println(user)
UpdatePassword(oldPass, newPass, token string) (User, errors.SDKError)
// EnableUser changes the status of the user to enabled.
//
// example:
// user, _ := sdk.EnableUser("userID", "token")
// fmt.Println(user)
EnableUser(id, token string) (User, errors.SDKError)
// DisableUser changes the status of the user to disabled.
//
// example:
// user, _ := sdk.DisableUser("userID", "token")
// fmt.Println(user)
DisableUser(id, token string) (User, errors.SDKError)
// CreateToken receives credentials and returns user token.
//
// example:
// user := sdk.User{
// Credentials: sdk.Credentials{
// Identity: "john.doe@example",
// Secret: "12345678",
// },
// }
// token, _ := sdk.CreateToken(user)
// fmt.Println(token)
CreateToken(user User) (Token, errors.SDKError)
// RefreshToken receives credentials and returns user token.
//
// example:
// token, _ := sdk.RefreshToken("refresh_token")
// fmt.Println(token)
RefreshToken(token string) (Token, errors.SDKError)
// CreateThing registers new thing and returns its id.
//
// example:
// thing := sdk.Thing{
// Name: "My Thing",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// thing, _ := sdk.CreateThing(thing, "token")
// fmt.Println(thing)
CreateThing(thing Thing, token string) (Thing, errors.SDKError)
// CreateThings registers new things and returns their ids.
//
// example:
// things := []sdk.Thing{
// {
// Name: "My Thing 1",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// },
// {
// Name: "My Thing 2",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// },
// }
// things, _ := sdk.CreateThings(things, "token")
// fmt.Println(things)
CreateThings(things []Thing, token string) ([]Thing, errors.SDKError)
// Filters things and returns a page result.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Thing",
// }
// things, _ := sdk.Things(pm, "token")
// fmt.Println(things)
Things(pm PageMetadata, token string) (ThingsPage, errors.SDKError)
// ThingsByChannel returns page of things that are connected to specified channel.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Thing",
// }
// things, _ := sdk.ThingsByChannel("channelID", pm, "token")
// fmt.Println(things)
ThingsByChannel(chanID string, pm PageMetadata, token string) (ThingsPage, errors.SDKError)
// Thing returns thing object by id.
//
// example:
// thing, _ := sdk.Thing("thingID", "token")
// fmt.Println(thing)
Thing(id, token string) (Thing, errors.SDKError)
// UpdateThing updates existing thing.
//
// example:
// thing := sdk.Thing{
// ID: "thingID",
// Name: "My Thing",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// thing, _ := sdk.UpdateThing(thing, "token")
// fmt.Println(thing)
UpdateThing(thing Thing, token string) (Thing, errors.SDKError)
// UpdateThingTags updates the client's tags.
//
// example:
// thing := sdk.Thing{
// ID: "thingID",
// Tags: []string{"tag1", "tag2"},
// }
// thing, _ := sdk.UpdateThingTags(thing, "token")
// fmt.Println(thing)
UpdateThingTags(thing Thing, token string) (Thing, errors.SDKError)
// UpdateThingSecret updates the client's secret
//
// example:
// thing, err := sdk.UpdateThingSecret("thingID", "newSecret", "token")
// fmt.Println(thing)
UpdateThingSecret(id, secret, token string) (Thing, errors.SDKError)
// UpdateThingOwner updates the client's owner.
//
// example:
// thing := sdk.Thing{
// ID: "thingID",
// Owner: "ownerID",
// }
// thing, _ := sdk.UpdateThingOwner(thing, "token")
// fmt.Println(thing)
UpdateThingOwner(thing Thing, token string) (Thing, errors.SDKError)
// EnableThing changes client status to enabled.
//
// example:
// thing, _ := sdk.EnableThing("thingID", "token")
// fmt.Println(thing)
EnableThing(id, token string) (Thing, errors.SDKError)
// DisableThing changes client status to disabled - soft delete.
//
// example:
// thing, _ := sdk.DisableThing("thingID", "token")
// fmt.Println(thing)
DisableThing(id, token string) (Thing, errors.SDKError)
// IdentifyThing validates thing's key and returns its ID
//
// example:
// id, _ := sdk.IdentifyThing("thingKey")
// fmt.Println(id)
IdentifyThing(key string) (string, errors.SDKError)
// ShareThing shares thing with other user.
//
// example:
// err := sdk.ShareThing("thingID", "groupID", "userID", []string{"c_list", "c_delete"}, "token")
// fmt.Println(err)
ShareThing(thingID, groupID, userID string, actions []string, token string) errors.SDKError
// CreateGroup creates new group and returns its id.
//
// example:
// group := sdk.Group{
// Name: "My Group",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// group, _ := sdk.CreateGroup(group, "token")
// fmt.Println(group)
CreateGroup(group Group, token string) (Group, errors.SDKError)
// Memberships
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Group",
// }
// groups, _ := sdk.Memberships("userID", pm, "token")
// fmt.Println(groups)
Memberships(clientID string, pm PageMetadata, token string) (MembershipsPage, errors.SDKError)
// Groups returns page of groups.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Group",
// }
// groups, _ := sdk.Groups(pm, "token")
// fmt.Println(groups)
Groups(pm PageMetadata, token string) (GroupsPage, errors.SDKError)
// Parents returns page of users groups.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Group",
// }
// groups, _ := sdk.Parents("groupID", pm, "token")
// fmt.Println(groups)
Parents(id string, pm PageMetadata, token string) (GroupsPage, errors.SDKError)
// Children returns page of users groups.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Group",
// }
// groups, _ := sdk.Children("groupID", pm, "token")
// fmt.Println(groups)
Children(id string, pm PageMetadata, token string) (GroupsPage, errors.SDKError)
// Group returns users group object by id.
//
// example:
// group, _ := sdk.Group("groupID", "token")
// fmt.Println(group)
Group(id, token string) (Group, errors.SDKError)
// UpdateGroup updates existing group.
//
// example:
// group := sdk.Group{
// ID: "groupID",
// Name: "My Group",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// group, _ := sdk.UpdateGroup(group, "token")
// fmt.Println(group)
UpdateGroup(group Group, token string) (Group, errors.SDKError)
// EnableGroup changes group status to enabled.
//
// example:
// group, _ := sdk.EnableGroup("groupID", "token")
// fmt.Println(group)
EnableGroup(id, token string) (Group, errors.SDKError)
// DisableGroup changes group status to disabled - soft delete.
//
// example:
// group, _ := sdk.DisableGroup("groupID", "token")
// fmt.Println(group)
DisableGroup(id, token string) (Group, errors.SDKError)
// CreateChannel creates new channel and returns its id.
//
// example:
// channel := sdk.Channel{
// Name: "My Channel",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// channel, _ := sdk.CreateChannel(channel, "token")
// fmt.Println(channel)
CreateChannel(channel Channel, token string) (Channel, errors.SDKError)
// CreateChannels registers new channels and returns their ids.
//
// example:
// channels := []sdk.Channel{
// {
// Name: "My Channel 1",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// },
// {
// Name: "My Channel 2",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// },
// }
// channels, _ := sdk.CreateChannels(channels, "token")
// fmt.Println(channels)
CreateChannels(channels []Channel, token string) ([]Channel, errors.SDKError)
// Channels returns page of channels.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Channel",
// }
// channels, _ := sdk.Channels(pm, "token")
// fmt.Println(channels)
Channels(pm PageMetadata, token string) (ChannelsPage, errors.SDKError)
// ChannelsByThing returns page of channels that are connected to specified thing.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Name: "My Channel",
// }
// channels, _ := sdk.ChannelsByThing("thingID", pm, "token")
// fmt.Println(channels)
ChannelsByThing(thingID string, pm PageMetadata, token string) (ChannelsPage, errors.SDKError)
// Channel returns channel data by id.
//
// example:
// channel, _ := sdk.Channel("channelID", "token")
// fmt.Println(channel)
Channel(id, token string) (Channel, errors.SDKError)
// UpdateChannel updates existing channel.
//
// example:
// channel := sdk.Channel{
// ID: "channelID",
// Name: "My Channel",
// Metadata: sdk.Metadata{
// "key": "value",
// },
// }
// channel, _ := sdk.UpdateChannel(channel, "token")
// fmt.Println(channel)
UpdateChannel(channel Channel, token string) (Channel, errors.SDKError)
// EnableChannel changes channel status to enabled.
//
// example:
// channel, _ := sdk.EnableChannel("channelID", "token")
// fmt.Println(channel)
EnableChannel(id, token string) (Channel, errors.SDKError)
// DisableChannel changes channel status to disabled - soft delete.
//
// example:
// channel, _ := sdk.DisableChannel("channelID", "token")
// fmt.Println(channel)
DisableChannel(id, token string) (Channel, errors.SDKError)
// CreatePolicy creates a policy for the given subject, so that, after
// CreatePolicy, `subject` has a `relation` on `object`. Returns a non-nil
// error in case of failures.
//
// example:
// policy := sdk.Policy{
// Subject: "userID:1",
// Object: "groupID:1",
// Actions: []string{"g_add"},
// }
// err := sdk.CreatePolicy(policy, "token")
// fmt.Println(err)
CreatePolicy(policy Policy, token string) errors.SDKError
// DeletePolicy deletes policies.
//
// example:
// policy := sdk.Policy{
// Subject: "userID:1",
// Object: "groupID:1",
// Actions: []string{"g_add"},
// }
// err := sdk.DeletePolicy(policy, "token")
// fmt.Println(err)
DeletePolicy(policy Policy, token string) errors.SDKError
// UpdatePolicy updates policies based on the given policy structure.
//
// example:
// policy := sdk.Policy{
// Subject: "userID:1",
// Object: "groupID:1",
// Actions: []string{"g_add"},
// }
// err := sdk.UpdatePolicy(policy, "token")
// fmt.Println(err)
UpdatePolicy(p Policy, token string) errors.SDKError
// ListPolicies lists policies based on the given policy structure.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Subject: "userID:1",
// }
// policies, _ := sdk.ListPolicies(pm, "token")
// fmt.Println(policies)
ListPolicies(pm PageMetadata, token string) (PolicyPage, errors.SDKError)
// Authorize returns true if the given policy structure allows the action.
//
// example:
// aReq := sdk.AccessRequest{
// Subject: "userID:1",
// Object: "groupID:1",
// Actions: "g_add",
// EntityType: "clients",
// }
// ok, _ := sdk.Authorize(aReq, "token")
// fmt.Println(ok)
Authorize(accessReq AccessRequest, token string) (bool, errors.SDKError)
// Assign assigns member of member type (thing or user) to a group.
//
// example:
// err := sdk.Assign([]string{"g_add"}, "userID:1", "groupID:1", "token")
// fmt.Println(err)
Assign(memberType []string, memberID, groupID, token string) errors.SDKError
// Unassign removes member from a group.
//
// example:
// err := sdk.Unassign("userID:1", "groupID:1", "token")
// fmt.Println(err)
Unassign(memberID, groupID, token string) errors.SDKError
// Connect bulk connects things to channels specified by id.
//
// example:
// conns := sdk.ConnectionIDs{
// ChannelIDs: []string{"thingID:1", "thingID:2"},
// ThingIDs: []string{"channelID:1", "channelID:2"},
// Actions: []string{"m_read"},
// }
// err := sdk.Connect(conns, "token")
// fmt.Println(err)
Connect(conns ConnectionIDs, token string) errors.SDKError
// Disconnect
//
// example:
// conns := sdk.ConnectionIDs{
// ChannelIDs: []string{"thingID:1", "thingID:2"},
// ThingIDs: []string{"channelID:1", "channelID:2"},
// }
// err := sdk.Disconnect(conns, "token")
// fmt.Println(err)
Disconnect(connIDs ConnectionIDs, token string) errors.SDKError
// ConnectThing
//
// example:
// err := sdk.ConnectThing("thingID", "channelID", "token")
// fmt.Println(err)
ConnectThing(thingID, chanID, token string) errors.SDKError
// DisconnectThing disconnect thing from specified channel by id.
//
// example:
// err := sdk.DisconnectThing("thingID", "channelID", "token")
// fmt.Println(err)
DisconnectThing(thingID, chanID, token string) errors.SDKError
// UpdateThingsPolicy updates policies based on the given policy structure.
//
// example:
// policy := sdk.Policy{
// Subject: "thingID",
// Object: "channelID",
// Actions: []string{"m_read"},
// }
// err := sdk.UpdateThingsPolicy(policy, "token")
// fmt.Println(err)
UpdateThingsPolicy(p Policy, token string) errors.SDKError
// ListThingsPolicies lists policies based on the given policy structure.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// Subject: "thingID:1",
// }
// policies, _ := sdk.ListThingsPolicies(pm, "token")
// fmt.Println(policies)
ListThingsPolicies(pm PageMetadata, token string) (PolicyPage, errors.SDKError)
// ThingCanAccess returns true if the given policy structure allows the action.
//
// example:
// aReq := sdk.AccessRequest{
// Subject: "thingID",
// Object: "channelID",
// Actions: "m_read",
// EntityType: "things",
// }
// ok, _ := sdk.ThingCanAccess(aReq "token")
// fmt.Println(ok)
ThingCanAccess(accessReq AccessRequest, token string) (bool, string, errors.SDKError)
// SendMessage send message to specified channel.
//
// example:
// msg := '[{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]'
// err := sdk.SendMessage("channelID", msg, "thingSecret")
// fmt.Println(err)
SendMessage(chanID, msg, key string) errors.SDKError
// ReadMessages read messages of specified channel.
//
// example:
// msgs, _ := sdk.ReadMessages("channelID", "token")
// fmt.Println(msgs)
ReadMessages(chanID, token string) (MessagesPage, errors.SDKError)
// SetContentType sets message content type.
//
// example:
// err := sdk.SetContentType("application/json")
// fmt.Println(err)
SetContentType(ct ContentType) errors.SDKError
// Health returns things service health check.
//
// example:
// health, _ := sdk.Health()
// fmt.Println(health)
Health() (HealthInfo, errors.SDKError)
// AddBootstrap add bootstrap configuration
//
// example:
// cfg := sdk.BootstrapConfig{
// ThingID: "thingID",
// Name: "bootstrap",
// ExternalID: "externalID",
// ExternalKey: "externalKey",
// Channels: []string{"channel1", "channel2"},
// }
// id, _ := sdk.AddBootstrap(cfg, "token")
// fmt.Println(id)
AddBootstrap(cfg BootstrapConfig, token string) (string, errors.SDKError)
// View returns Thing Config with given ID belonging to the user identified by the given token.
//
// example:
// bootstrap, _ := sdk.ViewBootstrap("id", "token")
// fmt.Println(bootstrap)
ViewBootstrap(id, token string) (BootstrapConfig, errors.SDKError)
// Update updates editable fields of the provided Config.
//
// example:
// cfg := sdk.BootstrapConfig{
// ThingID: "thingID",
// Name: "bootstrap",
// ExternalID: "externalID",
// ExternalKey: "externalKey",
// Channels: []string{"channel1", "channel2"},
// }
// err := sdk.UpdateBootstrap(cfg, "token")
// fmt.Println(err)
UpdateBootstrap(cfg BootstrapConfig, token string) errors.SDKError
// Update bootstrap config certificates.
//
// example:
// err := sdk.UpdateBootstrapCerts("id", "clientCert", "clientKey", "ca", "token")
// fmt.Println(err)
UpdateBootstrapCerts(id string, clientCert, clientKey, ca string, token string) errors.SDKError
// UpdateBootstrapConnection updates connections performs update of the channel list corresponding Thing is connected to.
//
// example:
// err := sdk.UpdateBootstrapConnection("id", []string{"channel1", "channel2"}, "token")
// fmt.Println(err)
UpdateBootstrapConnection(id string, channels []string, token string) errors.SDKError
// Remove removes Config with specified token that belongs to the user identified by the given token.
//
// example:
// err := sdk.RemoveBootstrap("id", "token")
// fmt.Println(err)
RemoveBootstrap(id, token string) errors.SDKError
// Bootstrap returns Config to the Thing with provided external ID using external key.
//
// example:
// bootstrap, _ := sdk.Bootstrap("externalID", "externalKey")
// fmt.Println(bootstrap)
Bootstrap(externalID, externalKey string) (BootstrapConfig, errors.SDKError)
// BootstrapSecure retrieves a configuration with given external ID and encrypted external key.
//
// example:
// bootstrap, _ := sdk.BootstrapSecure("externalID", "externalKey")
// fmt.Println(bootstrap)
BootstrapSecure(externalID, externalKey string) (BootstrapConfig, errors.SDKError)
// Bootstraps retrieves a list of managed configs.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// }
// bootstraps, _ := sdk.Bootstraps(pm, "token")
// fmt.Println(bootstraps)
Bootstraps(pm PageMetadata, token string) (BoostrapsPage, errors.SDKError)
// Whitelist updates Thing state Config with given ID belonging to the user identified by the given token.
//
// example:
// cfg := sdk.BootstrapConfig{
// ThingID: "thingID",
// Name: "bootstrap",
// ExternalID: "externalID",
// ExternalKey: "externalKey",
// Channels: []string{"channel1", "channel2"},
// }
// err := sdk.Whitelist(cfg, "token")
// fmt.Println(err)
Whitelist(cfg BootstrapConfig, token string) errors.SDKError
// IssueCert issues a certificate for a thing required for mTLS.
//
// example:
// cert, _ := sdk.IssueCert("thingID", "valid", "token")
// fmt.Println(cert)
IssueCert(thingID, valid, token string) (Cert, errors.SDKError)
// ViewCert returns a certificate given certificate ID
//
// example:
// cert, _ := sdk.ViewCert("certID", "token")
// fmt.Println(cert)
ViewCert(certID, token string) (Cert, errors.SDKError)
// ViewCertByThing retrieves a list of certificates' serial IDs for a given thing ID.
//
// example:
// cserial, _ := sdk.ViewCertByThing("thingID", "token")
// fmt.Println(cserial)
ViewCertByThing(thingID, token string) (CertSerials, errors.SDKError)
// RevokeCert revokes certificate for thing with thingID
//
// example:
// tm, _ := sdk.RevokeCert("thingID", "token")
// fmt.Println(tm)
RevokeCert(thingID, token string) (time.Time, errors.SDKError)
// CreateSubscription creates a new subscription
//
// example:
// subscription, _ := sdk.CreateSubscription("topic", "contact", "token")
// fmt.Println(subscription)
CreateSubscription(topic, contact, token string) (string, errors.SDKError)
// ListSubscriptions list subscriptions given list parameters.
//
// example:
// pm := sdk.PageMetadata{
// Offset: 0,
// Limit: 10,
// }
// subscriptions, _ := sdk.ListSubscriptions(pm, "token")
// fmt.Println(subscriptions)
ListSubscriptions(pm PageMetadata, token string) (SubscriptionPage, errors.SDKError)
// ViewSubscription retrieves a subscription with the provided id.
//
// example:
// subscription, _ := sdk.ViewSubscription("id", "token")
// fmt.Println(subscription)
ViewSubscription(id, token string) (Subscription, errors.SDKError)
// DeleteSubscription removes a subscription with the provided id.
//
// example:
// err := sdk.DeleteSubscription("id", "token")
// fmt.Println(err)
DeleteSubscription(id, token string) errors.SDKError
}
type mfSDK struct {
bootstrapURL string
certsURL string
httpAdapterURL string
readerURL string
thingsURL string
usersURL string
msgContentType ContentType
client *http.Client
}
// Config contains sdk configuration parameters.
type Config struct {
BootstrapURL string
CertsURL string
HTTPAdapterURL string
ReaderURL string
ThingsURL string
UsersURL string
MsgContentType ContentType
TLSVerification bool
}
// NewSDK returns new mainflux SDK instance.
func NewSDK(conf Config) SDK {
return &mfSDK{
bootstrapURL: conf.BootstrapURL,
certsURL: conf.CertsURL,
httpAdapterURL: conf.HTTPAdapterURL,
readerURL: conf.ReaderURL,
thingsURL: conf.ThingsURL,
usersURL: conf.UsersURL,
msgContentType: conf.MsgContentType,
client: &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: !conf.TLSVerification,
},
},
},
}
}
// processRequest creates and send a new HTTP request, and checks for errors in the HTTP response.
// It then returns the response headers, the response body, and the associated error(s) (if any).
func (sdk mfSDK) processRequest(method, url, token, contentType string, data []byte, expectedRespCodes ...int) (http.Header, []byte, errors.SDKError) {
req, err := http.NewRequest(method, url, bytes.NewReader(data))
if err != nil {
return make(http.Header), []byte{}, errors.NewSDKError(err)
}
if token != "" {
if !strings.Contains(token, ThingPrefix) {
token = BearerPrefix + token
}
req.Header.Set("Authorization", token)
}
if contentType != "" {
req.Header.Add("Content-Type", contentType)
}
resp, err := sdk.client.Do(req)
if err != nil {
return make(http.Header), []byte{}, errors.NewSDKError(err)
}
defer resp.Body.Close()
sdkerr := errors.CheckError(resp, expectedRespCodes...)
if sdkerr != nil {
return make(http.Header), []byte{}, sdkerr
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return make(http.Header), []byte{}, errors.NewSDKError(err)
}
return resp.Header, body, nil
}
func (sdk mfSDK) withQueryParams(baseURL, endpoint string, pm PageMetadata) (string, error) {
q, err := pm.query()
if err != nil {
return "", err
}
return fmt.Sprintf("%s/%s?%s", baseURL, endpoint, q), nil
}
func (pm PageMetadata) query() (string, error) {
q := url.Values{}
if pm.Offset != 0 {
q.Add("offset", strconv.FormatUint(pm.Offset, 10))
}
if pm.Limit != 0 {
q.Add("limit", strconv.FormatUint(pm.Limit, 10))
}
if pm.Total != 0 {
q.Add("total", strconv.FormatUint(pm.Total, 10))
}
if pm.Level != 0 {
q.Add("level", strconv.FormatUint(pm.Level, 10))
}
if pm.Email != "" {
q.Add("email", pm.Email)
}
if pm.Name != "" {
q.Add("name", pm.Name)
}
if pm.Type != "" {
q.Add("type", pm.Type)
}
if pm.Visibility != "" {
q.Add("visibility", pm.Visibility)
}
if pm.Status != "" {
q.Add("status", pm.Status)
}
if pm.Metadata != nil {
md, err := json.Marshal(pm.Metadata)
if err != nil {
return "", errors.NewSDKError(err)
}
q.Add("metadata", string(md))
}
if pm.Action != "" {
q.Add("action", pm.Action)
}
if pm.Subject != "" {
q.Add("subject", pm.Subject)
}
if pm.Object != "" {
q.Add("object", pm.Object)
}
if pm.Tag != "" {
q.Add("tag", pm.Tag)
}
if pm.Owner != "" {
q.Add("owner", pm.Owner)
}
if pm.SharedBy != "" {
q.Add("shared_by", pm.SharedBy)
}
if pm.Topic != "" {
q.Add("topic", pm.Topic)
}
if pm.Contact != "" {
q.Add("contact", pm.Contact)
}
if pm.State != "" {
q.Add("state", pm.State)
}
return q.Encode(), nil
}