1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

//! Implementation of deserialization of AWS [S3 Bucket notifications][n]
//!
//! The structs can deserialize the [event message structure version 2.2][structure].
//!
//! [n]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
//! [structure]: https://docs.aws.amazon.com/AmazonS3/latest/dev/notification-content-structure.html

use serde::{Deserialize, Serialize};

/// The test message that AWS sends on initial configuration of events
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct TestEvent {
    pub service: String,
    pub event: String,
    pub time: String,
    pub bucket: String,
    pub request_id: String,
    pub host_id: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Event {
    pub records: Vec<Record>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Record {
    pub event_version: String,
    pub event_source: String,
    pub aws_region: String,
    pub event_time: String,
    #[serde(rename = "eventName")]
    pub event_type: EventType,
    pub user_identity: UserIdentity,
    pub request_parameters: RequestParameters,
    pub response_elements: ResponseElements,
    pub s3: S3,
    pub glacier_event_data: Option<GlacierEventData>,
}

/// The Event type
///
/// <https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#supported-notification-event-types>
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum EventType {
    #[serde(rename = "ObjectCreated:Put")]
    ObjectCreatedPut,
    #[serde(rename = "ObjectCreated:Post")]
    ObjectCreatedPost,
    #[serde(rename = "ObjectCreated:Copy")]
    ObjectCreatedCopy,
    #[serde(rename = "ObjectCreated:CompleteMultipartUpload")]
    ObjectCreatedCompleteMultipartUpload,
    #[serde(rename = "ObjectRemoved:Delete")]
    ObjectRemovedDelete,
    #[serde(rename = "ObjectRemoved:DeleteMarkerCreated")]
    ObjectRemovedDeleteMarkerCreated,
    #[serde(rename = "ObjectRestore:Post")]
    ObjectRestorePost,
    #[serde(rename = "ObjectRestore:Completed")]
    ObjectRestoreCompleted,
    #[serde(rename = "ReducedRedundancyLostObject")]
    ReducedRedundancyLostObject,
    #[serde(rename = "Replication:OperationFailedReplication")]
    ReplicationOperationFailedReplication,
    #[serde(rename = "Replication:OperationMissedThreshold")]
    ReplicationOperationMissedThreshold,
    #[serde(rename = "Replication:OperationReplicatedAfterThreshold")]
    ReplicationOperationReplicatedAfterThreshold,
    #[serde(rename = "Replication:OperationNotTracked")]
    ReplicationOperationNotTracked,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserIdentity {
    pub principal_id: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RequestParameters {
    #[serde(rename = "sourceIPAddress")]
    pub source_ip: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ResponseElements {
    #[serde(rename = "x-amz-request-id")]
    pub request_id: String,
    #[serde(rename = "x-amz-id-2")]
    pub id2: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct S3 {
    pub s3_schema_version: String,
    pub configuration_id: String,
    pub bucket: Bucket,
    pub object: Object,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Bucket {
    pub name: String,
    pub owner_identity: OwnerIdentity,
    pub arn: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OwnerIdentity {
    pub principal_id: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Object {
    pub key: String,
    pub size: usize,
    pub e_tag: String,
    pub version_id: Option<String>,
    pub sequencer: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GlacierEventData {
    pub restore_event_data: RestoreEventData,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RestoreEventData {
    pub lifecycle_restoration_expiry_time: String,
    pub lifecycle_restore_storage_class: String,
}