github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/api/apc/access.go (about)

     1  // Package apc: API control messages and constants
     2  /*
     3   * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package apc
     6  
     7  import (
     8  	"fmt"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  type AccessAttrs uint64
    14  
    15  // ACL aka access permissions
    16  const (
    17  	// object level
    18  	AceGET     = AccessAttrs(1) << iota
    19  	AceObjHEAD // permission to get object props
    20  	AcePUT
    21  	AceAPPEND
    22  	AceObjDELETE
    23  	AceObjMOVE
    24  	AcePromote
    25  	// TODO: reserving the only perm that must be checked on the target side (NIY)
    26  	AceObjUpdate
    27  	// bucket metadata
    28  	AceBckHEAD   // get bucket props and ACL
    29  	AceObjLIST   // list objects in a bucket
    30  	AcePATCH     // set bucket props
    31  	AceBckSetACL // set bucket permissions
    32  	// cluster level
    33  	AceListBuckets
    34  	AceShowCluster
    35  	AceCreateBucket
    36  	AceDestroyBucket
    37  	AceMoveBucket
    38  	AceAdmin
    39  	// note: must be the last one
    40  	AceMax
    41  )
    42  
    43  // access => operation
    44  var accessOp = map[AccessAttrs]string{
    45  	// object
    46  	AceGET:       "GET",
    47  	AceObjHEAD:   "HEAD-OBJECT",
    48  	AcePUT:       "PUT",
    49  	AceAPPEND:    "APPEND",
    50  	AceObjDELETE: "DELETE-OBJECT",
    51  	AceObjMOVE:   "MOVE-OBJECT",
    52  	AcePromote:   "PROMOTE",
    53  	AceObjUpdate: "UPDATE-OBJECT",
    54  	// bucket
    55  	AceBckHEAD:   "HEAD-BUCKET",
    56  	AceObjLIST:   "LIST-OBJECTS",
    57  	AcePATCH:     "PATCH",
    58  	AceBckSetACL: "SET-BUCKET-ACL",
    59  	// cluster
    60  	AceListBuckets:   "LIST-BUCKETS",
    61  	AceShowCluster:   "SHOW-CLUSTER",
    62  	AceCreateBucket:  "CREATE-BUCKET",
    63  	AceDestroyBucket: "DESTROY-BUCKET",
    64  	AceMoveBucket:    "MOVE-BUCKET",
    65  	AceAdmin:         "ADMIN",
    66  
    67  	// NOTE: update Describe() when adding/deleting
    68  }
    69  
    70  // derived (convenience) constants
    71  const (
    72  	// encompasses all ACEs, current and future
    73  	AccessAll      = AccessAttrs(^uint64(0))
    74  	AllowAllAccess = "su"
    75  
    76  	// read-only and read-write access to bucket
    77  	AccessRO             = AceGET | AceObjHEAD | AceListBuckets | AceBckHEAD | AceObjLIST
    78  	AllowReadOnlyAccess  = "ro"
    79  	AccessRW             = AccessRO | AcePUT | AceAPPEND | AceObjDELETE | AceObjMOVE
    80  	AllowReadWriteAccess = "rw"
    81  
    82  	AccessNone = AccessAttrs(0)
    83  
    84  	// permission to perform cluster-level ops
    85  	AccessCluster = AceListBuckets | AceCreateBucket | AceDestroyBucket | AceMoveBucket | AceAdmin
    86  )
    87  
    88  // verbs
    89  func SupportedPermissions() []string {
    90  	accList := []string{"ro", "rw", "su"}
    91  	for _, v := range accessOp {
    92  		accList = append(accList, v)
    93  	}
    94  	return accList
    95  }
    96  
    97  func (a AccessAttrs) Has(perms AccessAttrs) bool { return a&perms == perms }
    98  func (a AccessAttrs) String() string             { return strconv.FormatUint(uint64(a), 10) }
    99  
   100  func (a AccessAttrs) Describe(all bool) string {
   101  	if a == 0 {
   102  		return "none"
   103  	}
   104  	accList := make([]string, 0, 24)
   105  	if a.Has(AceGET) {
   106  		accList = append(accList, accessOp[AceGET])
   107  	}
   108  	if a.Has(AceObjHEAD) {
   109  		accList = append(accList, accessOp[AceObjHEAD])
   110  	}
   111  	if a.Has(AcePUT) {
   112  		accList = append(accList, accessOp[AcePUT])
   113  	}
   114  	if a.Has(AceAPPEND) {
   115  		accList = append(accList, accessOp[AceAPPEND])
   116  	}
   117  	if a.Has(AceObjDELETE) {
   118  		accList = append(accList, accessOp[AceObjDELETE])
   119  	}
   120  	if a.Has(AceObjMOVE) {
   121  		accList = append(accList, accessOp[AceObjMOVE])
   122  	}
   123  	if a.Has(AcePromote) {
   124  		accList = append(accList, accessOp[AcePromote])
   125  	}
   126  	if a.Has(AceObjUpdate) {
   127  		accList = append(accList, accessOp[AceObjUpdate])
   128  	}
   129  	//
   130  	if a.Has(AceBckHEAD) {
   131  		accList = append(accList, accessOp[AceBckHEAD])
   132  	}
   133  	if a.Has(AceObjLIST) {
   134  		accList = append(accList, accessOp[AceObjLIST])
   135  	}
   136  	if a.Has(AcePATCH) {
   137  		accList = append(accList, accessOp[AcePATCH])
   138  	}
   139  	if a.Has(AceBckSetACL) {
   140  		accList = append(accList, accessOp[AceBckSetACL])
   141  	}
   142  	//
   143  	if a.Has(AceListBuckets) {
   144  		accList = append(accList, accessOp[AceListBuckets])
   145  	}
   146  	if a.Has(AceShowCluster) {
   147  		accList = append(accList, accessOp[AceShowCluster])
   148  	}
   149  	if a.Has(AceCreateBucket) {
   150  		accList = append(accList, accessOp[AceCreateBucket])
   151  	}
   152  	if a.Has(AceDestroyBucket) {
   153  		accList = append(accList, accessOp[AceDestroyBucket])
   154  	}
   155  	if a.Has(AceMoveBucket) {
   156  		accList = append(accList, accessOp[AceMoveBucket])
   157  	}
   158  	if a.Has(AceAdmin) {
   159  		accList = append(accList, accessOp[AceAdmin])
   160  	}
   161  
   162  	// return
   163  	if all || len(accList) <= 4 {
   164  		return strings.Join(accList, ",")
   165  	}
   166  	accList = accList[:4]
   167  	return strings.Join(accList, ",") + ", ..."
   168  }
   169  
   170  func AccessOp(access AccessAttrs) string {
   171  	if s, ok := accessOp[access]; ok {
   172  		return s
   173  	}
   174  	return "<unknown access>"
   175  }
   176  
   177  func StrToAccess(accessStr string) (access AccessAttrs, err error) {
   178  	switch accessStr {
   179  	case AllowReadOnlyAccess:
   180  		access |= AccessRO
   181  	case AllowReadWriteAccess:
   182  		access |= AccessRW
   183  	case AllowAllAccess:
   184  		access = AccessAll
   185  	case "":
   186  		access = AccessNone
   187  	default:
   188  		found := false
   189  		for k, v := range accessOp {
   190  			if v == accessStr {
   191  				access |= k
   192  				found = true
   193  			}
   194  		}
   195  		if !found {
   196  			err = fmt.Errorf("invalid access value: %q", accessStr)
   197  		}
   198  	}
   199  	return
   200  }