// Copyright (c) 2015-2021 MinIO, Inc. // // This file is part of MinIO Object Storage stack // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package event import ( "encoding/json" "encoding/xml" ) // Name - event type enum. // Refer http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#notification-how-to-event-types-and-destinations // for most basic values we have since extend this and its not really much applicable other than a reference point. // "s3:Replication:OperationCompletedReplication" is a MinIO extension. type Name int // Values of event Name const ( // Single event types (does not require expansion) ObjectAccessedGet Name = 1 + iota ObjectAccessedGetRetention ObjectAccessedGetLegalHold ObjectAccessedHead ObjectAccessedAttributes ObjectCreatedCompleteMultipartUpload ObjectCreatedCopy ObjectCreatedPost ObjectCreatedPut ObjectCreatedPutRetention ObjectCreatedPutLegalHold ObjectCreatedPutTagging ObjectCreatedDeleteTagging ObjectRemovedDelete ObjectRemovedDeleteMarkerCreated ObjectRemovedNoOP BucketCreated BucketRemoved ObjectReplicationFailed ObjectReplicationComplete ObjectReplicationMissedThreshold ObjectReplicationReplicatedAfterThreshold ObjectReplicationNotTracked ObjectRestorePost ObjectRestoreCompleted ObjectTransitionFailed ObjectTransitionComplete ObjectManyVersions PrefixManyFolders objectSingleTypesEnd // Start Compound types that require expansion: ObjectAccessedAll ObjectCreatedAll ObjectRemovedAll ObjectReplicationAll ObjectRestoreAll ObjectTransitionAll ObjectScannerAll Everything ) // The number of single names should not exceed 64. // This will break masking. Use bit 63 as extension. var _ = uint64(1 << objectSingleTypesEnd) // Expand - returns expanded values of abbreviated event type. func (name Name) Expand() []Name { switch name { case ObjectAccessedAll: return []Name{ ObjectAccessedGet, ObjectAccessedHead, ObjectAccessedGetRetention, ObjectAccessedGetLegalHold, ObjectAccessedAttributes, } case ObjectCreatedAll: return []Name{ ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, ObjectCreatedPost, ObjectCreatedPut, ObjectCreatedPutRetention, ObjectCreatedPutLegalHold, ObjectCreatedPutTagging, ObjectCreatedDeleteTagging, } case ObjectRemovedAll: return []Name{ ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated, ObjectRemovedNoOP, } case ObjectReplicationAll: return []Name{ ObjectReplicationFailed, ObjectReplicationComplete, ObjectReplicationNotTracked, ObjectReplicationMissedThreshold, ObjectReplicationReplicatedAfterThreshold, } case ObjectRestoreAll: return []Name{ ObjectRestorePost, ObjectRestoreCompleted, } case ObjectTransitionAll: return []Name{ ObjectTransitionFailed, ObjectTransitionComplete, } case ObjectScannerAll: return []Name{ ObjectManyVersions, PrefixManyFolders, } case Everything: res := make([]Name, objectSingleTypesEnd-1) for i := range res { res[i] = Name(i + 1) } return res default: return []Name{name} } } // Mask returns the type as mask. // Compound "All" types are expanded. func (name Name) Mask() uint64 { if name < objectSingleTypesEnd { return 1 << (name - 1) } var mask uint64 for _, n := range name.Expand() { mask |= 1 << (n - 1) } return mask } // String - returns string representation of event type. func (name Name) String() string { switch name { case BucketCreated: return "s3:BucketCreated:*" case BucketRemoved: return "s3:BucketRemoved:*" case ObjectAccessedAll: return "s3:ObjectAccessed:*" case ObjectAccessedGet: return "s3:ObjectAccessed:Get" case ObjectAccessedGetRetention: return "s3:ObjectAccessed:GetRetention" case ObjectAccessedGetLegalHold: return "s3:ObjectAccessed:GetLegalHold" case ObjectAccessedHead: return "s3:ObjectAccessed:Head" case ObjectAccessedAttributes: return "s3:ObjectAccessed:Attributes" case ObjectCreatedAll: return "s3:ObjectCreated:*" case ObjectCreatedCompleteMultipartUpload: return "s3:ObjectCreated:CompleteMultipartUpload" case ObjectCreatedCopy: return "s3:ObjectCreated:Copy" case ObjectCreatedPost: return "s3:ObjectCreated:Post" case ObjectCreatedPut: return "s3:ObjectCreated:Put" case ObjectCreatedPutTagging: return "s3:ObjectCreated:PutTagging" case ObjectCreatedDeleteTagging: return "s3:ObjectCreated:DeleteTagging" case ObjectCreatedPutRetention: return "s3:ObjectCreated:PutRetention" case ObjectCreatedPutLegalHold: return "s3:ObjectCreated:PutLegalHold" case ObjectRemovedAll: return "s3:ObjectRemoved:*" case ObjectRemovedDelete: return "s3:ObjectRemoved:Delete" case ObjectRemovedDeleteMarkerCreated: return "s3:ObjectRemoved:DeleteMarkerCreated" case ObjectRemovedNoOP: return "s3:ObjectRemoved:NoOP" case ObjectReplicationAll: return "s3:Replication:*" case ObjectReplicationFailed: return "s3:Replication:OperationFailedReplication" case ObjectReplicationComplete: return "s3:Replication:OperationCompletedReplication" case ObjectReplicationNotTracked: return "s3:Replication:OperationNotTracked" case ObjectReplicationMissedThreshold: return "s3:Replication:OperationMissedThreshold" case ObjectReplicationReplicatedAfterThreshold: return "s3:Replication:OperationReplicatedAfterThreshold" case ObjectRestoreAll: return "s3:ObjectRestore:*" case ObjectRestorePost: return "s3:ObjectRestore:Post" case ObjectRestoreCompleted: return "s3:ObjectRestore:Completed" case ObjectTransitionAll: return "s3:ObjectTransition:*" case ObjectTransitionFailed: return "s3:ObjectTransition:Failed" case ObjectTransitionComplete: return "s3:ObjectTransition:Complete" case ObjectManyVersions: return "s3:Scanner:ManyVersions" case PrefixManyFolders: return "s3:Scanner:BigPrefix" } return "" } // MarshalXML - encodes to XML data. func (name Name) MarshalXML(e *xml.Encoder, start xml.StartElement) error { return e.EncodeElement(name.String(), start) } // UnmarshalXML - decodes XML data. func (name *Name) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { var s string if err := d.DecodeElement(&s, &start); err != nil { return err } eventName, err := ParseName(s) if err != nil { return err } *name = eventName return nil } // MarshalJSON - encodes to JSON data. func (name Name) MarshalJSON() ([]byte, error) { return json.Marshal(name.String()) } // UnmarshalJSON - decodes JSON data. func (name *Name) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } eventName, err := ParseName(s) if err != nil { return err } *name = eventName return nil } // ParseName - parses string to Name. func ParseName(s string) (Name, error) { switch s { case "s3:BucketCreated:*": return BucketCreated, nil case "s3:BucketRemoved:*": return BucketRemoved, nil case "s3:ObjectAccessed:*": return ObjectAccessedAll, nil case "s3:ObjectAccessed:Get": return ObjectAccessedGet, nil case "s3:ObjectAccessed:GetRetention": return ObjectAccessedGetRetention, nil case "s3:ObjectAccessed:GetLegalHold": return ObjectAccessedGetLegalHold, nil case "s3:ObjectAccessed:Head": return ObjectAccessedHead, nil case "s3:ObjectAccessed:Attributes": return ObjectAccessedAttributes, nil case "s3:ObjectCreated:*": return ObjectCreatedAll, nil case "s3:ObjectCreated:CompleteMultipartUpload": return ObjectCreatedCompleteMultipartUpload, nil case "s3:ObjectCreated:Copy": return ObjectCreatedCopy, nil case "s3:ObjectCreated:Post": return ObjectCreatedPost, nil case "s3:ObjectCreated:Put": return ObjectCreatedPut, nil case "s3:ObjectCreated:PutRetention": return ObjectCreatedPutRetention, nil case "s3:ObjectCreated:PutLegalHold": return ObjectCreatedPutLegalHold, nil case "s3:ObjectCreated:PutTagging": return ObjectCreatedPutTagging, nil case "s3:ObjectCreated:DeleteTagging": return ObjectCreatedDeleteTagging, nil case "s3:ObjectRemoved:*": return ObjectRemovedAll, nil case "s3:ObjectRemoved:Delete": return ObjectRemovedDelete, nil case "s3:ObjectRemoved:DeleteMarkerCreated": return ObjectRemovedDeleteMarkerCreated, nil case "s3:ObjectRemoved:NoOP": return ObjectRemovedNoOP, nil case "s3:Replication:*": return ObjectReplicationAll, nil case "s3:Replication:OperationFailedReplication": return ObjectReplicationFailed, nil case "s3:Replication:OperationCompletedReplication": return ObjectReplicationComplete, nil case "s3:Replication:OperationMissedThreshold": return ObjectReplicationMissedThreshold, nil case "s3:Replication:OperationReplicatedAfterThreshold": return ObjectReplicationReplicatedAfterThreshold, nil case "s3:Replication:OperationNotTracked": return ObjectReplicationNotTracked, nil case "s3:ObjectRestore:*": return ObjectRestoreAll, nil case "s3:ObjectRestore:Post": return ObjectRestorePost, nil case "s3:ObjectRestore:Completed": return ObjectRestoreCompleted, nil case "s3:ObjectTransition:Failed": return ObjectTransitionFailed, nil case "s3:ObjectTransition:Complete": return ObjectTransitionComplete, nil case "s3:ObjectTransition:*": return ObjectTransitionAll, nil case "s3:Scanner:ManyVersions": return ObjectManyVersions, nil case "s3:Scanner:BigPrefix": return PrefixManyFolders, nil default: return 0, &ErrInvalidEventName{s} } }