2019-01-17 22:56:28 +00:00
package authorizer
import (
"context"
"fmt"
"github.com/influxdata/influxdb"
)
var _ influxdb . AuthorizationService = ( * AuthorizationService ) ( nil )
// AuthorizationService wraps a influxdb.AuthorizationService and authorizes actions
// against it appropriately.
type AuthorizationService struct {
s influxdb . AuthorizationService
}
// NewAuthorizationService constructs an instance of an authorizing authorization serivce.
func NewAuthorizationService ( s influxdb . AuthorizationService ) * AuthorizationService {
return & AuthorizationService {
s : s ,
}
}
func newAuthorizationPermission ( a influxdb . Action , id influxdb . ID ) ( * influxdb . Permission , error ) {
p := & influxdb . Permission {
Action : a ,
Resource : influxdb . Resource {
Type : influxdb . UsersResourceType ,
ID : & id ,
} ,
}
return p , p . Valid ( )
}
func authorizeReadAuthorization ( ctx context . Context , id influxdb . ID ) error {
p , err := newAuthorizationPermission ( influxdb . ReadAction , id )
if err != nil {
return err
}
if err := IsAllowed ( ctx , * p ) ; err != nil {
return err
}
return nil
}
func authorizeWriteAuthorization ( ctx context . Context , id influxdb . ID ) error {
p , err := newAuthorizationPermission ( influxdb . WriteAction , id )
if err != nil {
return err
}
if err := IsAllowed ( ctx , * p ) ; err != nil {
return err
}
return nil
}
// FindAuthorizationByID checks to see if the authorizer on context has read access to the id provided.
func ( s * AuthorizationService ) FindAuthorizationByID ( ctx context . Context , id influxdb . ID ) ( * influxdb . Authorization , error ) {
a , err := s . s . FindAuthorizationByID ( ctx , id )
if err != nil {
return nil , err
}
if err := authorizeReadAuthorization ( ctx , a . UserID ) ; err != nil {
return nil , err
}
return a , nil
}
// FindAuthorization retrieves the authorization and checks to see if the authorizer on context has read access to the authorization.
func ( s * AuthorizationService ) FindAuthorizationByToken ( ctx context . Context , t string ) ( * influxdb . Authorization , error ) {
a , err := s . s . FindAuthorizationByToken ( ctx , t )
if err != nil {
return nil , err
}
if err := authorizeReadAuthorization ( ctx , a . UserID ) ; err != nil {
return nil , err
}
return a , nil
}
// FindAuthorizations retrieves all authorizations that match the provided filter and then filters the list down to only the resources that are authorized.
func ( s * AuthorizationService ) FindAuthorizations ( ctx context . Context , filter influxdb . AuthorizationFilter , opt ... influxdb . FindOptions ) ( [ ] * influxdb . Authorization , int , error ) {
// TODO: we'll likely want to push this operation into the database eventually since fetching the whole list of data
// will likely be expensive.
as , _ , err := s . s . FindAuthorizations ( ctx , filter , opt ... )
if err != nil {
return nil , 0 , err
}
// This filters without allocating
// https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating
authorizations := as [ : 0 ]
for _ , a := range as {
err := authorizeReadAuthorization ( ctx , a . UserID )
if err != nil && influxdb . ErrorCode ( err ) != influxdb . EUnauthorized {
return nil , 0 , err
}
if influxdb . ErrorCode ( err ) == influxdb . EUnauthorized {
continue
}
authorizations = append ( authorizations , a )
}
return authorizations , len ( authorizations ) , nil
}
// CreateAuthorization checks to see if the authorizer on context has write access to the global authorizations resource.
func ( s * AuthorizationService ) CreateAuthorization ( ctx context . Context , a * influxdb . Authorization ) error {
if err := authorizeWriteAuthorization ( ctx , a . UserID ) ; err != nil {
return err
}
2019-02-15 17:57:57 +00:00
if err := VerifyPermissions ( ctx , a . Permissions ) ; err != nil {
return err
}
return s . s . CreateAuthorization ( ctx , a )
}
// VerifyPermission ensures that an authorization is allowed all of the appropriate permissions.
func VerifyPermissions ( ctx context . Context , ps [ ] influxdb . Permission ) error {
for _ , p := range ps {
2019-01-17 22:56:28 +00:00
if err := IsAllowed ( ctx , p ) ; err != nil {
return & influxdb . Error {
Err : err ,
2019-02-15 18:44:27 +00:00
Msg : fmt . Sprintf ( "permission %s is not allowed" , p ) ,
2019-01-17 22:56:28 +00:00
Code : influxdb . EForbidden ,
}
}
}
2019-02-15 17:57:57 +00:00
return nil
2019-01-17 22:56:28 +00:00
}
2019-03-27 19:02:45 +00:00
// UpdateAuthorization checks to see if the authorizer on context has write access to the authorization provided.
2019-04-01 16:16:37 +00:00
func ( s * AuthorizationService ) UpdateAuthorization ( ctx context . Context , id influxdb . ID , upd * influxdb . AuthorizationUpdate ) ( * influxdb . Authorization , error ) {
2019-01-17 22:56:28 +00:00
a , err := s . s . FindAuthorizationByID ( ctx , id )
if err != nil {
2019-04-01 16:16:37 +00:00
return nil , err
2019-01-17 22:56:28 +00:00
}
if err := authorizeWriteAuthorization ( ctx , a . UserID ) ; err != nil {
2019-04-01 16:16:37 +00:00
return nil , err
2019-01-17 22:56:28 +00:00
}
2019-03-27 19:02:45 +00:00
return s . s . UpdateAuthorization ( ctx , id , upd )
2019-01-17 22:56:28 +00:00
}
// DeleteAuthorization checks to see if the authorizer on context has write access to the authorization provided.
func ( s * AuthorizationService ) DeleteAuthorization ( ctx context . Context , id influxdb . ID ) error {
a , err := s . s . FindAuthorizationByID ( ctx , id )
if err != nil {
return err
}
if err := authorizeWriteAuthorization ( ctx , a . UserID ) ; err != nil {
return err
}
return s . s . DeleteAuthorization ( ctx , id )
}