2018-05-14 16:26:38 +00:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
2018-05-22 22:05:17 +00:00
|
|
|
"errors"
|
2018-09-10 20:56:11 +00:00
|
|
|
"fmt"
|
2018-05-14 16:26:38 +00:00
|
|
|
"net/http"
|
2018-05-16 18:59:35 +00:00
|
|
|
"path"
|
2018-09-10 20:56:11 +00:00
|
|
|
"strings"
|
2018-05-14 16:26:38 +00:00
|
|
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
|
"github.com/influxdata/platform"
|
2018-05-22 22:05:17 +00:00
|
|
|
kerrors "github.com/influxdata/platform/kit/errors"
|
2018-05-14 16:26:38 +00:00
|
|
|
"github.com/julienschmidt/httprouter"
|
|
|
|
)
|
|
|
|
|
|
|
|
// AuthorizationHandler represents an HTTP API handler for authorizations.
|
|
|
|
type AuthorizationHandler struct {
|
|
|
|
*httprouter.Router
|
|
|
|
Logger *zap.Logger
|
|
|
|
|
|
|
|
AuthorizationService platform.AuthorizationService
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewAuthorizationHandler returns a new instance of AuthorizationHandler.
|
|
|
|
func NewAuthorizationHandler() *AuthorizationHandler {
|
|
|
|
h := &AuthorizationHandler{
|
|
|
|
Router: httprouter.New(),
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:08:28 +00:00
|
|
|
h.HandlerFunc("POST", "/v2/authorizations", h.handlePostAuthorization)
|
|
|
|
h.HandlerFunc("GET", "/v2/authorizations", h.handleGetAuthorizations)
|
|
|
|
h.HandlerFunc("GET", "/v2/authorizations/:id", h.handleGetAuthorization)
|
|
|
|
h.HandlerFunc("PATCH", "/v2/authorizations/:id", h.handleSetAuthorizationStatus)
|
|
|
|
h.HandlerFunc("DELETE", "/v2/authorizations/:id", h.handleDeleteAuthorization)
|
2018-05-14 16:26:38 +00:00
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
type authResponse struct {
|
|
|
|
Links map[string]string `json:"links"`
|
|
|
|
platform.Authorization
|
|
|
|
}
|
|
|
|
|
|
|
|
func newAuthResponse(a *platform.Authorization) *authResponse {
|
|
|
|
return &authResponse{
|
|
|
|
Links: map[string]string{
|
2018-08-09 15:08:28 +00:00
|
|
|
"self": fmt.Sprintf("/v2/authorizations/%s", a.ID),
|
|
|
|
"user": fmt.Sprintf("/v2/users/%s", a.UserID),
|
2018-09-10 20:56:11 +00:00
|
|
|
},
|
|
|
|
Authorization: *a,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type authsResponse struct {
|
|
|
|
Links map[string]string `json:"links"`
|
|
|
|
Auths []*authResponse `json:"auths"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func newAuthsResponse(opts platform.FindOptions, f platform.AuthorizationFilter, as []*platform.Authorization) *authsResponse {
|
|
|
|
rs := make([]*authResponse, 0, len(as))
|
|
|
|
for _, a := range as {
|
|
|
|
rs = append(rs, newAuthResponse(a))
|
|
|
|
}
|
|
|
|
return &authsResponse{
|
|
|
|
// TODO(desa): update links to include paging and filter information
|
|
|
|
Links: map[string]string{
|
2018-08-09 15:08:28 +00:00
|
|
|
"self": "/v2/authorizations",
|
2018-09-10 20:56:11 +00:00
|
|
|
},
|
|
|
|
Auths: rs,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:08:28 +00:00
|
|
|
// handlePostAuthorization is the HTTP handler for the POST /v2/authorizations route.
|
2018-05-14 16:26:38 +00:00
|
|
|
func (h *AuthorizationHandler) handlePostAuthorization(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
req, err := decodePostAuthorizationRequest(ctx, r)
|
|
|
|
if err != nil {
|
|
|
|
h.Logger.Info("failed to decode request", zap.String("handler", "postAuthorization"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-14 16:26:38 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Need to do some validation of req.Authorization.Permissions
|
|
|
|
|
|
|
|
if err := h.AuthorizationService.CreateAuthorization(ctx, req.Authorization); err != nil {
|
|
|
|
// Don't log here, it should already be handled by the service
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-14 16:26:38 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
if err := encodeResponse(ctx, w, http.StatusCreated, newAuthResponse(req.Authorization)); err != nil {
|
2018-05-14 16:26:38 +00:00
|
|
|
h.Logger.Info("failed to encode response", zap.String("handler", "postAuthorization"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-14 16:26:38 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type postAuthorizationRequest struct {
|
|
|
|
Authorization *platform.Authorization
|
|
|
|
}
|
|
|
|
|
|
|
|
func decodePostAuthorizationRequest(ctx context.Context, r *http.Request) (*postAuthorizationRequest, error) {
|
|
|
|
a := &platform.Authorization{}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(a); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &postAuthorizationRequest{
|
|
|
|
Authorization: a,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:08:28 +00:00
|
|
|
// handleGetAuthorizations is the HTTP handler for the GET /v2/authorizations route.
|
2018-05-14 16:26:38 +00:00
|
|
|
func (h *AuthorizationHandler) handleGetAuthorizations(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
req, err := decodeGetAuthorizationsRequest(ctx, r)
|
|
|
|
if err != nil {
|
|
|
|
h.Logger.Info("failed to decode request", zap.String("handler", "getAuthorizations"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-14 16:26:38 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
opts := platform.FindOptions{}
|
|
|
|
as, _, err := h.AuthorizationService.FindAuthorizations(ctx, req.filter, opts)
|
2018-05-14 16:26:38 +00:00
|
|
|
if err != nil {
|
2018-09-10 20:56:11 +00:00
|
|
|
// TODO(desa): fix this when using real errors library
|
|
|
|
if strings.Contains(err.Error(), "not found") {
|
|
|
|
err = kerrors.New(err.Error(), kerrors.NotFound)
|
|
|
|
}
|
2018-05-14 16:26:38 +00:00
|
|
|
// Don't log here, it should already be handled by the service
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-14 16:26:38 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
if err := encodeResponse(ctx, w, http.StatusOK, newAuthsResponse(opts, req.filter, as)); err != nil {
|
2018-05-14 16:26:38 +00:00
|
|
|
h.Logger.Info("failed to encode response", zap.String("handler", "getAuthorizations"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-14 16:26:38 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type getAuthorizationsRequest struct {
|
|
|
|
filter platform.AuthorizationFilter
|
|
|
|
}
|
|
|
|
|
|
|
|
func decodeGetAuthorizationsRequest(ctx context.Context, r *http.Request) (*getAuthorizationsRequest, error) {
|
|
|
|
qp := r.URL.Query()
|
|
|
|
|
|
|
|
req := &getAuthorizationsRequest{}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
userID := qp.Get("userID")
|
2018-05-14 16:26:38 +00:00
|
|
|
if userID != "" {
|
2018-08-01 18:54:32 +00:00
|
|
|
req.filter.UserID = &platform.ID{}
|
|
|
|
if err := req.filter.UserID.DecodeFromString(userID); err != nil {
|
2018-05-14 16:26:38 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2018-05-16 18:59:35 +00:00
|
|
|
}
|
2018-05-14 16:26:38 +00:00
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
user := qp.Get("user")
|
|
|
|
if user != "" {
|
|
|
|
req.filter.User = &user
|
|
|
|
}
|
|
|
|
|
|
|
|
authID := qp.Get("id")
|
|
|
|
if authID != "" {
|
2018-08-01 18:54:32 +00:00
|
|
|
req.filter.ID = &platform.ID{}
|
|
|
|
if err := req.filter.ID.DecodeFromString(authID); err != nil {
|
2018-05-16 18:59:35 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return req, nil
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:08:28 +00:00
|
|
|
// handleGetAuthorization is the HTTP handler for the GET /v2/authorizations/:id route.
|
2018-05-16 18:59:35 +00:00
|
|
|
func (h *AuthorizationHandler) handleGetAuthorization(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
req, err := decodeGetAuthorizationRequest(ctx, r)
|
|
|
|
if err != nil {
|
|
|
|
h.Logger.Info("failed to decode request", zap.String("handler", "getAuthorization"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-16 18:59:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
a, err := h.AuthorizationService.FindAuthorizationByID(ctx, req.ID)
|
|
|
|
if err != nil {
|
2018-09-10 20:56:11 +00:00
|
|
|
// TODO(desa): fix this when using real errors library
|
|
|
|
if strings.Contains(err.Error(), "not found") {
|
|
|
|
err = kerrors.New(err.Error(), kerrors.NotFound)
|
|
|
|
}
|
2018-05-16 18:59:35 +00:00
|
|
|
// Don't log here, it should already be handled by the service
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-16 18:59:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
if err := encodeResponse(ctx, w, http.StatusOK, newAuthResponse(a)); err != nil {
|
2018-05-16 18:59:35 +00:00
|
|
|
h.Logger.Info("failed to encode response", zap.String("handler", "getAuthorization"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-16 18:59:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type getAuthorizationRequest struct {
|
|
|
|
ID platform.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
func decodeGetAuthorizationRequest(ctx context.Context, r *http.Request) (*getAuthorizationRequest, error) {
|
|
|
|
params := httprouter.ParamsFromContext(ctx)
|
|
|
|
id := params.ByName("id")
|
|
|
|
if id == "" {
|
2018-05-22 22:05:17 +00:00
|
|
|
return nil, kerrors.InvalidDataf("url missing id")
|
2018-05-16 18:59:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var i platform.ID
|
|
|
|
if err := i.DecodeFromString(id); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &getAuthorizationRequest{
|
|
|
|
ID: i,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:08:28 +00:00
|
|
|
// handleSetAuthorizationStatus is the HTTP handler for the PATCH /v2/authorizations/:id route that updates the authorization's status.
|
2018-08-28 17:58:38 +00:00
|
|
|
func (h *AuthorizationHandler) handleSetAuthorizationStatus(w http.ResponseWriter, r *http.Request) {
|
2018-08-27 19:18:11 +00:00
|
|
|
ctx := r.Context()
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
req, err := decodeSetAuthorizationStatusRequest(ctx, r)
|
2018-08-27 19:18:11 +00:00
|
|
|
if err != nil {
|
|
|
|
h.Logger.Info("failed to decode request", zap.String("handler", "updateAuthorization"), zap.Error(err))
|
|
|
|
EncodeError(ctx, err, w)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
a, err := h.AuthorizationService.FindAuthorizationByID(ctx, req.ID)
|
|
|
|
if err != nil {
|
2018-09-10 20:56:11 +00:00
|
|
|
// TODO(desa): fix this when using real errors library
|
|
|
|
if strings.Contains(err.Error(), "not found") {
|
|
|
|
err = kerrors.New(err.Error(), kerrors.NotFound)
|
|
|
|
}
|
2018-08-27 19:18:11 +00:00
|
|
|
EncodeError(ctx, err, w)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
if req.Status != a.Status {
|
|
|
|
a.Status = req.Status
|
|
|
|
if err := h.AuthorizationService.SetAuthorizationStatus(ctx, a.ID, a.Status); err != nil {
|
2018-08-27 19:18:11 +00:00
|
|
|
EncodeError(ctx, err, w)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
if err := encodeResponse(ctx, w, http.StatusOK, newAuthResponse(a)); err != nil {
|
2018-08-27 19:18:11 +00:00
|
|
|
h.Logger.Info("failed to encode response", zap.String("handler", "updateAuthorization"), zap.Error(err))
|
|
|
|
EncodeError(ctx, err, w)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type updateAuthorizationRequest struct {
|
2018-08-28 17:58:38 +00:00
|
|
|
ID platform.ID
|
|
|
|
Status platform.Status
|
2018-08-27 19:18:11 +00:00
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
func decodeSetAuthorizationStatusRequest(ctx context.Context, r *http.Request) (*updateAuthorizationRequest, error) {
|
2018-08-27 19:18:11 +00:00
|
|
|
params := httprouter.ParamsFromContext(ctx)
|
|
|
|
id := params.ByName("id")
|
|
|
|
if id == "" {
|
|
|
|
return nil, kerrors.InvalidDataf("url missing id")
|
|
|
|
}
|
|
|
|
|
|
|
|
var i platform.ID
|
|
|
|
if err := i.DecodeFromString(id); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
a := &setAuthorizationStatusRequest{}
|
2018-08-27 19:18:11 +00:00
|
|
|
if err := json.NewDecoder(r.Body).Decode(a); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
switch a.Status {
|
|
|
|
case platform.Active, platform.Inactive:
|
|
|
|
default:
|
|
|
|
return nil, kerrors.InvalidDataf("unknown status option")
|
|
|
|
}
|
|
|
|
|
2018-08-27 19:18:11 +00:00
|
|
|
return &updateAuthorizationRequest{
|
2018-08-28 17:58:38 +00:00
|
|
|
ID: i,
|
|
|
|
Status: a.Status,
|
2018-08-27 19:18:11 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:08:28 +00:00
|
|
|
// handleDeleteAuthorization is the HTTP handler for the DELETE /v2/authorizations/:id route.
|
2018-05-16 18:59:35 +00:00
|
|
|
func (h *AuthorizationHandler) handleDeleteAuthorization(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
req, err := decodeDeleteAuthorizationRequest(ctx, r)
|
|
|
|
if err != nil {
|
|
|
|
h.Logger.Info("failed to decode request", zap.String("handler", "deleteAuthorization"), zap.Error(err))
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-16 18:59:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.AuthorizationService.DeleteAuthorization(ctx, req.ID); err != nil {
|
2018-09-10 20:56:11 +00:00
|
|
|
// TODO(desa): fix this when using real errors library
|
|
|
|
if strings.Contains(err.Error(), "not found") {
|
|
|
|
err = kerrors.New(err.Error(), kerrors.NotFound)
|
|
|
|
}
|
2018-05-16 18:59:35 +00:00
|
|
|
// Don't log here, it should already be handled by the service
|
2018-06-28 19:32:16 +00:00
|
|
|
EncodeError(ctx, err, w)
|
2018-05-16 18:59:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
w.WriteHeader(http.StatusNoContent)
|
2018-05-16 18:59:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type deleteAuthorizationRequest struct {
|
|
|
|
ID platform.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
func decodeDeleteAuthorizationRequest(ctx context.Context, r *http.Request) (*deleteAuthorizationRequest, error) {
|
|
|
|
params := httprouter.ParamsFromContext(ctx)
|
|
|
|
id := params.ByName("id")
|
|
|
|
if id == "" {
|
2018-05-22 22:05:17 +00:00
|
|
|
return nil, kerrors.InvalidDataf("url missing id")
|
2018-05-16 18:59:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var i platform.ID
|
|
|
|
if err := i.DecodeFromString(id); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &deleteAuthorizationRequest{
|
|
|
|
ID: i,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-05-14 16:26:38 +00:00
|
|
|
// AuthorizationService connects to Influx via HTTP using tokens to manage authorizations
|
|
|
|
type AuthorizationService struct {
|
|
|
|
Addr string
|
|
|
|
Token string
|
|
|
|
InsecureSkipVerify bool
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ platform.AuthorizationService = (*AuthorizationService)(nil)
|
|
|
|
|
2018-08-27 19:18:11 +00:00
|
|
|
// FindAuthorizationByID finds the authorization against a remote influx server.
|
2018-05-16 18:59:35 +00:00
|
|
|
func (s *AuthorizationService) FindAuthorizationByID(ctx context.Context, id platform.ID) (*platform.Authorization, error) {
|
|
|
|
u, err := newURL(s.Addr, authorizationIDPath(id))
|
2018-05-14 16:26:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequest("GET", u.String(), nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-08-27 19:18:11 +00:00
|
|
|
SetToken(s.Token, req)
|
2018-05-14 16:26:38 +00:00
|
|
|
|
|
|
|
hc := newClient(u.Scheme, s.InsecureSkipVerify)
|
|
|
|
resp, err := hc.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-05-23 18:29:01 +00:00
|
|
|
if err := CheckError(resp); err != nil {
|
|
|
|
return nil, err
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var b platform.Authorization
|
2018-05-16 18:59:35 +00:00
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&b); err != nil {
|
2018-05-14 16:26:38 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2018-05-16 18:59:35 +00:00
|
|
|
defer resp.Body.Close()
|
2018-05-14 16:26:38 +00:00
|
|
|
|
|
|
|
return &b, nil
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
// FindAuthorizationByToken returns a single authorization by Token.
|
|
|
|
func (s *AuthorizationService) FindAuthorizationByToken(ctx context.Context, token string) (*platform.Authorization, error) {
|
2018-05-22 22:05:17 +00:00
|
|
|
return nil, errors.New("not supported in HTTP authorization service")
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FindAuthorizations returns a list of authorizations that match filter and the total count of matching authorizations.
|
|
|
|
// Additional options provide pagination & sorting.
|
|
|
|
func (s *AuthorizationService) FindAuthorizations(ctx context.Context, filter platform.AuthorizationFilter, opt ...platform.FindOptions) ([]*platform.Authorization, int, error) {
|
|
|
|
u, err := newURL(s.Addr, authorizationPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
query := u.Query()
|
|
|
|
|
|
|
|
req, err := http.NewRequest("GET", u.String(), nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
if filter.ID != nil {
|
|
|
|
query.Add("id", filter.ID.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
if filter.UserID != nil {
|
|
|
|
query.Add("userID", filter.UserID.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
if filter.User != nil {
|
|
|
|
query.Add("user", *filter.User)
|
|
|
|
}
|
|
|
|
|
2018-05-14 16:26:38 +00:00
|
|
|
req.URL.RawQuery = query.Encode()
|
2018-08-27 19:18:11 +00:00
|
|
|
SetToken(s.Token, req)
|
2018-05-14 16:26:38 +00:00
|
|
|
|
|
|
|
hc := newClient(u.Scheme, s.InsecureSkipVerify)
|
|
|
|
resp, err := hc.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
|
2018-05-23 18:29:01 +00:00
|
|
|
if err := CheckError(resp); err != nil {
|
|
|
|
return nil, 0, err
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
var bs authsResponse
|
2018-05-16 18:59:35 +00:00
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&bs); err != nil {
|
2018-05-14 16:26:38 +00:00
|
|
|
return nil, 0, err
|
|
|
|
}
|
2018-05-16 18:59:35 +00:00
|
|
|
defer resp.Body.Close()
|
2018-05-14 16:26:38 +00:00
|
|
|
|
2018-09-10 20:56:11 +00:00
|
|
|
auths := make([]*platform.Authorization, 0, len(bs.Auths))
|
|
|
|
for _, b := range bs.Auths {
|
|
|
|
auths = append(auths, &b.Authorization)
|
|
|
|
}
|
|
|
|
|
|
|
|
return auths, len(auths), nil
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2018-08-09 15:08:28 +00:00
|
|
|
authorizationPath = "/v2/authorizations"
|
2018-05-14 16:26:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// CreateAuthorization creates a new authorization and sets b.ID with the new identifier.
|
2018-05-16 18:59:35 +00:00
|
|
|
func (s *AuthorizationService) CreateAuthorization(ctx context.Context, a *platform.Authorization) error {
|
2018-05-14 16:26:38 +00:00
|
|
|
u, err := newURL(s.Addr, authorizationPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
octets, err := json.Marshal(a)
|
2018-05-14 16:26:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(octets))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
2018-08-27 19:18:11 +00:00
|
|
|
SetToken(s.Token, req)
|
2018-05-14 16:26:38 +00:00
|
|
|
|
|
|
|
hc := newClient(u.Scheme, s.InsecureSkipVerify)
|
|
|
|
|
|
|
|
resp, err := hc.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-05-23 18:29:01 +00:00
|
|
|
// TODO(jsternberg): Should this check for a 201 explicitly?
|
|
|
|
if err := CheckError(resp); err != nil {
|
|
|
|
return err
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
if err := json.NewDecoder(resp.Body).Decode(a); err != nil {
|
2018-05-14 16:26:38 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
type setAuthorizationStatusRequest struct {
|
|
|
|
Status platform.Status `json:"status"`
|
2018-08-27 19:18:11 +00:00
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
// SetAuthorizationStatus updates an authorization's status.
|
|
|
|
func (s *AuthorizationService) SetAuthorizationStatus(ctx context.Context, id platform.ID, status platform.Status) error {
|
2018-08-27 19:18:11 +00:00
|
|
|
u, err := newURL(s.Addr, authorizationIDPath(id))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:58:38 +00:00
|
|
|
b, err := json.Marshal(setAuthorizationStatusRequest{
|
|
|
|
Status: status,
|
2018-08-27 19:18:11 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequest("PATCH", u.String(), bytes.NewReader(b))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
SetToken(s.Token, req)
|
|
|
|
|
|
|
|
hc := newClient(u.Scheme, s.InsecureSkipVerify)
|
|
|
|
|
|
|
|
resp, err := hc.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := CheckError(resp); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
// DeleteAuthorization removes a authorization by id.
|
|
|
|
func (s *AuthorizationService) DeleteAuthorization(ctx context.Context, id platform.ID) error {
|
|
|
|
u, err := newURL(s.Addr, authorizationIDPath(id))
|
2018-05-14 16:26:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequest("DELETE", u.String(), nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-08-27 19:18:11 +00:00
|
|
|
SetToken(s.Token, req)
|
2018-05-14 16:26:38 +00:00
|
|
|
|
|
|
|
hc := newClient(u.Scheme, s.InsecureSkipVerify)
|
|
|
|
resp, err := hc.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-05-23 18:29:01 +00:00
|
|
|
return CheckError(resp)
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 18:59:35 +00:00
|
|
|
func authorizationIDPath(id platform.ID) string {
|
|
|
|
return path.Join(authorizationPath, id.String())
|
2018-05-14 16:26:38 +00:00
|
|
|
}
|