Add authentication

Signed-off-by: 0x6f736f646f <blackd0t@protonmail.com>
This commit is contained in:
0x6f736f646f
2022-02-09 14:51:04 +03:00
parent 98e61863be
commit 46a9124a56
3 changed files with 319 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
package memfault
import (
"encoding/json"
"fmt"
"net/http"
"strings"
)
// GetMe Return information about the logged in User
func (sdk mfSDK) GetMe() (string, error) {
endpoint := "auth/me"
url := fmt.Sprintf("%s/%s", sdk.apiURL, endpoint)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return "", err
}
resp, err := sdk.makeRequest(req)
if err != nil {
return "", err
}
return string(resp), err
}
// Generate (or re-generate) an API Key for logged in User.
func (sdk mfSDK) GenerateUserApiKey() (string, error) {
endpoint := "auth/api_key"
url := fmt.Sprintf("%s/%s", sdk.apiURL, endpoint)
payload := strings.NewReader(``)
req, err := http.NewRequest(http.MethodPost, url, payload)
if err != nil {
return "", err
}
resp, err := sdk.makeRequest(req)
if err != nil {
return "", err
}
var akr UserApiKeyRes
if err := json.Unmarshal(resp, &akr); err != nil {
return "", err
}
return string(akr.Data.ApiKey), nil
}
// GetUserApiKey Get a previously generated API Key for the logged in User
func (sdk mfSDK) GetUserApiKey() (string, error) {
endpoint := "auth/api_key"
url := fmt.Sprintf("%s/%s", sdk.apiURL, endpoint)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return "", err
}
resp, err := sdk.makeRequest(req)
if err != nil {
return "", err
}
var akr UserApiKeyRes
if err := json.Unmarshal(resp, &akr); err != nil {
return "", err
}
return string(akr.Data.ApiKey), nil
}
// DeleteUserApiKey Invalidate the previously generated API Key for the logged in User and do not create another one
func (sdk mfSDK) DeleteUserApiKey() (string, error) {
endpoint := "auth/api_key"
url := fmt.Sprintf("%s/%s", sdk.apiURL, endpoint)
payload := strings.NewReader(``)
req, err := http.NewRequest(http.MethodDelete, url, payload)
if err != nil {
return "", err
}
resp, err := sdk.makeRequest(req)
if err != nil {
return "", err
}
return string(resp), nil
}
// GetOrganizationSlug
func (sdk mfSDK) GetOrganizationSlug(multiple bool) (string, error) {
endpoint := "auth/me"
url := fmt.Sprintf("%s/%s", sdk.apiURL, endpoint)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return "", err
}
resp, err := sdk.makeRequest(req)
if err != nil {
return "", err
}
var ur UserRes
if err := json.Unmarshal(resp, &ur); err != nil {
return "", err
}
if multiple {
var list []string
for _, organization := range ur.Organizations {
list = append(list, organization.Slug)
}
organizationSlugs := fmt.Sprint(list)
return organizationSlugs, nil
}
return string(ur.Organizations[0].Slug), nil
}
+140
View File
@@ -0,0 +1,140 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
package memfault
import (
"encoding/base64"
"errors"
"io/ioutil"
"net/http"
"time"
)
// ContentType represents all possible content types.
type ContentType string
var _ SDK = (*mfSDK)(nil)
// SDK contains Mainflux API.
type SDK interface {
// GetMe
GetMe() (string, error)
// Generate a user api key
GenerateUserApiKey() (string, error)
// Get the issued user api key
GetUserApiKey() (string, error)
// Deletes the issued user api key
DeleteUserApiKey() (string, error)
// Gets the organization slug
GetOrganizationSlug(multiple bool) (string, error)
// Creates project
CreateProject(project Project) (string, error)
}
// Credentials contains the credentials
type Credentials struct {
Email string `json:"email"`
Password string `json:"password"`
ApiKey string `json:"api_key"`
OrganisationToken string `json:"organisation_token"`
ProjectKey string `json:"project_key"`
}
type mfSDK struct {
apiURL string
chunksURL string
ingressURL string
filesURL string
credentials Credentials
msgContentType ContentType
client *http.Client
}
// Config contains sdk configuration parameters.
type Config struct {
ApiURL string
ChunksURL string
IngressURL string
FilesURL string
Credentials Credentials
MaxIdleConns int
IdleConnTimeout time.Duration
}
type Project struct {
Name string `json:"name"`
Slug string `json:"slug"`
Os string `json:"os"`
Platform string `json:"platform"`
}
// NewSDK returns new mainflux SDK instance.
func NewSDK(conf Config) SDK {
return &mfSDK{
apiURL: conf.ApiURL,
chunksURL: conf.ChunksURL,
ingressURL: conf.IngressURL,
filesURL: conf.FilesURL,
credentials: conf.Credentials,
client: &http.Client{
Transport: &http.Transport{
MaxIdleConns: conf.MaxIdleConns,
IdleConnTimeout: conf.IdleConnTimeout,
},
},
}
}
func (sdk mfSDK) makeRequest(req *http.Request) ([]byte, error) {
token, err := sdk.authenticate()
if err != nil {
return nil, err
}
resp, err := sdk.sendRequest(req, token)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return body, nil
}
func (sdk mfSDK) sendRequest(req *http.Request, token string) (*http.Response, error) {
if token != "" {
req.Header.Add("Authorization", "Basic "+token)
}
req.Header.Add("Content-Type", "application/json")
res, err := sdk.client.Do(req)
if err != nil {
return res, err
}
return res, nil
}
func (sdk mfSDK) authenticate() (string, error) {
if sdk.credentials.Email != "" && sdk.credentials.Password != "" {
auth := []byte(sdk.credentials.Email + ":" + sdk.credentials.Password)
return base64.StdEncoding.EncodeToString(auth), nil
} else if sdk.credentials.ApiKey != "" && sdk.credentials.Email != "" {
auth := []byte(sdk.credentials.Email + ":" + sdk.credentials.ApiKey)
return base64.StdEncoding.EncodeToString(auth), nil
} else if sdk.credentials.OrganisationToken != "" {
auth := []byte(":" + sdk.credentials.OrganisationToken)
return base64.StdEncoding.EncodeToString(auth), nil
}
return "", errors.New("Empty credentials")
}
+66
View File
@@ -0,0 +1,66 @@
package memfault
import "time"
type apiKey struct {
ApiKey string `json:"api_key,omitempty"`
}
type UserApiKeyRes struct {
Data apiKey `json:"data,omitempty"`
}
type organization struct {
Id int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Slug string `json:"slug"`
}
type organizationAcl struct {
Admin bool `json:"admin,omitempty"`
CustomerSupport bool `json:"customer_support,omitempty"`
Organization organization `json:"organization,omitempty"`
}
type organizations []organization
type UserRes struct {
CreatedDate time.Time `json:"created_date,omitempty"`
Email string `json:"email,omitempty"`
Id int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Organizations organizations `json:"organizations,omitempty"`
UpdatedDate time.Time `json:"updated_date,omitempty"`
PrivacyNotice bool `json:"has_accepted_privacy_notice"`
TermsOfService bool `json:"has_accepted_terms_of_service"`
Impersonated string `json:"impersonator"`
OrganizationsAcls []organizationAcl `json:"organization_acls"`
}
// type integrations struct {
// name string `json:"name,omitempty"`
// }
// type projectData struct {
// CreatedDate time.Time `json:"created_date,omitempty"`
// Slug string `json:"slug,omitempty": "smartsink"`
// LegacyLatestApiEnabled bool `json:"legacy_latest_api_enabled"`
// Integrations []integrations `json:"integrations"`
// AlertsEnabled bool `json:"alerts_enabled,omitempty"`
// UpdatedDate time.Time `json:"updated_date,omitempty"`
// CountDeployments int `json:"count_deployments"`
// DashboardEnabled bool `json:"dashboard_enabled"`
// DeviceLinkStrategies [] `json:"device_link_strategies"`
// PrimarySoftwareType string `json:"primary_software_type"`
// BugReportEnabled bool `json:"bugreport_export_enabled"`
// MetricChartEnabled bool `json:"metric_chart_enabled"`
// // "chunks_debug_log_length": 0,
// // "api_key": "3kfvYHivnNzFGtlKnNdUAAhETQU77Ldp",
// // "multi_component_enabled": false,
// VersioningScheme string `json:"versioning_scheme"`
// Name string `json:"name"`
// Os string `json:"os"`
// Platform string `json:"platform"`
// Id int `json:"id"`
// }
// type CreateProjectRes struct {
// Data projectData `json:"data,omitempty"`
// }