Skip to content

Commit d7bce99

Browse files
authored
Merge pull request #24 from Alos-no/develop
Extended R2 Buckets management API + Converted Zone Settings to exten…
2 parents 2dec022 + 60f5564 commit d7bce99

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5159
-418
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
<Authors>Alos</Authors>
5959
<Copyright>Copyright (c) $([System.DateTime]::Now.Year) Alos Engineering</Copyright>
6060
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
61-
<PackageProjectUrl>https://cfnet.alos.no</PackageProjectUrl>
61+
<PackageProjectUrl>https://alos.no/cfnet</PackageProjectUrl>
6262
<RepositoryUrl>https://github.com/Alos-no/Cloudflare.NET</RepositoryUrl>
6363
<PackageReadmeFile>README.md</PackageReadmeFile>
6464

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Cloudflare.NET SDK
22

33
[![.NET Build and Test](https://github.com/Alos-no/Cloudflare.NET/actions/workflows/CI.yml/badge.svg)](https://github.com/Alos-no/Cloudflare.NET/actions/workflows/CI.yml)
4-
[![Documentation](https://img.shields.io/badge/docs-cfnet.alos.no-27ae60)](https://cfnet.alos.no)
4+
[![Documentation](https://img.shields.io/badge/docs-cfnet.alos.no-27ae60)](https://alos.no/cfnet)
55
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-27ae60)](https://github.com/Alos-no/Cloudflare.NET/blob/main/LICENSE.txt)
66

77
[![NuGet (Cloudflare.NET.Api)](https://img.shields.io/nuget/v/Cloudflare.NET.Api?label=Cloudflare.NET.Api&color=27ae60)](https://www.nuget.org/packages/Cloudflare.NET.Api/)
@@ -10,7 +10,7 @@
1010

1111
An unofficial, strongly-typed .NET SDK for the Cloudflare API. Built with testability and maintainability in mind.
1212

13-
**[Documentation](https://cfnet.alos.no)** | **[Getting Started](https://cfnet.alos.no/articles/getting-started.html)** | **[API Reference](https://cfnet.alos.no/api/)**
13+
**[Documentation](https://alos.no/cfnet)** | **[Getting Started](https://alos.no/cfnet/articles/getting-started.html)** | **[API Reference](https://alos.no/cfnet/api/)**
1414

1515
## Packages
1616

@@ -63,7 +63,7 @@ public class MyService(ICloudflareApiClient cf)
6363

6464
### 📚 Ready to dive in?
6565

66-
**[Explore the Full Documentation →](https://cfnet.alos.no)**
66+
**[Explore the Full Documentation →](https://alos.no/cfnet)**
6767

6868
*Comprehensive guides, configuration options, multi-account setup, and more.*
6969

@@ -85,7 +85,7 @@ public class MyService(ICloudflareApiClient cf)
8585
| **R2 Client** | Upload, Download, Multipart, Presigned URLs, Batch Delete |
8686
| **Analytics** | GraphQL queries for traffic, security, and R2 metrics |
8787

88-
See [API Coverage](https://cfnet.alos.no/articles/api-coverage.html) for full details and roadmap.
88+
See [API Coverage](https://alos.no/cfnet/articles/api-coverage.html) for full details and roadmap.
8989

9090
## Supported Frameworks
9191

@@ -102,7 +102,7 @@ See [API Coverage](https://cfnet.alos.no/articles/api-coverage.html) for full de
102102
We welcome contributions! Whether it's bug reports, feature requests, or code contributions.
103103

104104
- [Report an Issue](https://github.com/Alos-no/Cloudflare.NET/issues)
105-
- [View Documentation](https://cfnet.alos.no)
105+
- [View Documentation](https://alos.no/cfnet)
106106

107107
## License
108108

docs/api/.manifest

Lines changed: 166 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
# R2 Bucket Locks
2+
3+
Configure object retention policies to prevent deletion and modification of objects in R2 buckets. Bucket locks are essential for compliance requirements like WORM (Write Once Read Many) storage.
4+
5+
## Overview
6+
7+
```csharp
8+
public class RetentionService(ICloudflareApiClient cf)
9+
{
10+
public async Task SetRetentionAsync(string bucket, int days)
11+
{
12+
var policy = new BucketLockPolicy([
13+
new BucketLockRule(
14+
Id: "retention-rule",
15+
Enabled: true,
16+
Condition: BucketLockCondition.ForDays(days)
17+
)
18+
]);
19+
20+
await cf.Accounts.Buckets.SetLockAsync(bucket, policy);
21+
}
22+
}
23+
```
24+
25+
## Getting Lock Policy
26+
27+
Retrieve the current lock rules for a bucket:
28+
29+
```csharp
30+
var policy = await cf.Accounts.Buckets.GetLockAsync("my-bucket");
31+
32+
foreach (var rule in policy.Rules)
33+
{
34+
Console.WriteLine($"Rule: {rule.Id}");
35+
Console.WriteLine($" Enabled: {rule.Enabled}");
36+
Console.WriteLine($" Prefix: {rule.Prefix ?? "(all objects)"}");
37+
Console.WriteLine($" Type: {rule.Condition?.Type}");
38+
}
39+
```
40+
41+
## Setting Lock Policy
42+
43+
### Age-Based Retention (Days)
44+
45+
Lock objects for a specific number of days after creation:
46+
47+
```csharp
48+
await cf.Accounts.Buckets.SetLockAsync("my-bucket", new BucketLockPolicy([
49+
new BucketLockRule(
50+
Id: "30-day-retention",
51+
Enabled: true,
52+
Condition: BucketLockCondition.ForDays(30)
53+
)
54+
]));
55+
```
56+
57+
### Age-Based Retention (Seconds)
58+
59+
For precise control, specify retention in seconds:
60+
61+
```csharp
62+
await cf.Accounts.Buckets.SetLockAsync("my-bucket", new BucketLockPolicy([
63+
new BucketLockRule(
64+
Id: "1-hour-retention",
65+
Enabled: true,
66+
Condition: BucketLockCondition.ForSeconds(3600)
67+
)
68+
]));
69+
```
70+
71+
### Date-Based Retention
72+
73+
Lock objects until a specific date:
74+
75+
```csharp
76+
await cf.Accounts.Buckets.SetLockAsync("my-bucket", new BucketLockPolicy([
77+
new BucketLockRule(
78+
Id: "retain-until-2026",
79+
Enabled: true,
80+
Condition: BucketLockCondition.UntilDate(new DateTime(2026, 1, 1))
81+
)
82+
]));
83+
```
84+
85+
### Indefinite Retention
86+
87+
Lock objects permanently (cannot be deleted):
88+
89+
```csharp
90+
await cf.Accounts.Buckets.SetLockAsync("my-bucket", new BucketLockPolicy([
91+
new BucketLockRule(
92+
Id: "permanent-lock",
93+
Enabled: true,
94+
Condition: BucketLockCondition.Indefinitely()
95+
)
96+
]));
97+
```
98+
99+
> [!CAUTION]
100+
> Indefinite locks cannot be removed. Objects will be retained forever. Use with extreme caution.
101+
102+
### Prefix-Scoped Rules
103+
104+
Apply retention to objects with a specific prefix:
105+
106+
```csharp
107+
await cf.Accounts.Buckets.SetLockAsync("my-bucket", new BucketLockPolicy([
108+
new BucketLockRule(
109+
Id: "archive-retention",
110+
Enabled: true,
111+
Prefix: "archive/",
112+
Condition: BucketLockCondition.ForDays(365)
113+
),
114+
new BucketLockRule(
115+
Id: "logs-retention",
116+
Enabled: true,
117+
Prefix: "logs/",
118+
Condition: BucketLockCondition.ForDays(90)
119+
)
120+
]));
121+
```
122+
123+
### Multiple Rules
124+
125+
Configure different retention policies for different object prefixes:
126+
127+
```csharp
128+
await cf.Accounts.Buckets.SetLockAsync("compliance-bucket", new BucketLockPolicy([
129+
// Financial records: 7 years
130+
new BucketLockRule(
131+
Id: "financial-records",
132+
Enabled: true,
133+
Prefix: "financial/",
134+
Condition: BucketLockCondition.ForDays(2555) // ~7 years
135+
),
136+
// Legal documents: indefinite
137+
new BucketLockRule(
138+
Id: "legal-documents",
139+
Enabled: true,
140+
Prefix: "legal/",
141+
Condition: BucketLockCondition.Indefinitely()
142+
),
143+
// General data: 1 year
144+
new BucketLockRule(
145+
Id: "general-retention",
146+
Enabled: true,
147+
Condition: BucketLockCondition.ForDays(365)
148+
)
149+
]));
150+
```
151+
152+
## Deleting Lock Policy
153+
154+
Remove all lock rules from a bucket:
155+
156+
```csharp
157+
await cf.Accounts.Buckets.DeleteLockAsync("my-bucket");
158+
```
159+
160+
> [!NOTE]
161+
> Deleting the lock policy does not affect objects that are currently within their retention period. Those objects remain locked until their retention expires.
162+
163+
## Models Reference
164+
165+
### BucketLockPolicy
166+
167+
| Property | Type | Description |
168+
|----------|------|-------------|
169+
| `Rules` | `IReadOnlyList<BucketLockRule>` | List of lock rules (max 1000) |
170+
171+
### BucketLockRule
172+
173+
| Property | Type | Description |
174+
|----------|------|-------------|
175+
| `Id` | `string?` | Optional rule identifier |
176+
| `Enabled` | `bool` | Whether the rule is active (default: true) |
177+
| `Prefix` | `string?` | Object key prefix filter (optional) |
178+
| `Condition` | `BucketLockCondition?` | Retention condition |
179+
180+
### BucketLockCondition
181+
182+
| Property | Type | Description |
183+
|----------|------|-------------|
184+
| `Type` | `BucketLockConditionType` | Type of condition (Age, Date, Indefinite) |
185+
| `MaxAgeSeconds` | `int?` | Retention duration in seconds (for Age type) |
186+
| `Date` | `DateTime?` | Retention end date (for Date type) |
187+
188+
### BucketLockCondition Factory Methods
189+
190+
| Method | Description |
191+
|--------|-------------|
192+
| `ForDays(int days)` | Create age-based condition in days |
193+
| `ForSeconds(int seconds)` | Create age-based condition in seconds |
194+
| `UntilDate(DateTime date)` | Create date-based condition |
195+
| `Indefinitely()` | Create permanent lock condition |
196+
197+
### BucketLockConditionType
198+
199+
| Value | Description |
200+
|-------|-------------|
201+
| `Age` | Retention based on object age |
202+
| `Date` | Retention until specific date |
203+
| `Indefinite` | Permanent retention |
204+
205+
## Common Patterns
206+
207+
### Compliance Configuration
208+
209+
```csharp
210+
public async Task ConfigureComplianceAsync(
211+
string bucket,
212+
int retentionDays,
213+
string? prefix = null)
214+
{
215+
var rules = new List<BucketLockRule>
216+
{
217+
new BucketLockRule(
218+
Id: $"compliance-{retentionDays}d",
219+
Enabled: true,
220+
Prefix: prefix,
221+
Condition: BucketLockCondition.ForDays(retentionDays)
222+
)
223+
};
224+
225+
await cf.Accounts.Buckets.SetLockAsync(bucket, new BucketLockPolicy(rules));
226+
}
227+
```
228+
229+
### Check Lock Status
230+
231+
```csharp
232+
public async Task<bool> IsLockedAsync(string bucket)
233+
{
234+
var policy = await cf.Accounts.Buckets.GetLockAsync(bucket);
235+
return policy.Rules.Any(r => r.Enabled);
236+
}
237+
```
238+
239+
### Extend Retention
240+
241+
```csharp
242+
public async Task ExtendRetentionAsync(string bucket, int additionalDays)
243+
{
244+
var policy = await cf.Accounts.Buckets.GetLockAsync(bucket);
245+
246+
var updatedRules = policy.Rules.Select(rule =>
247+
{
248+
if (rule.Condition?.Type == BucketLockConditionType.Age && rule.Condition.MaxAgeSeconds.HasValue)
249+
{
250+
var newSeconds = rule.Condition.MaxAgeSeconds.Value + (additionalDays * 86400);
251+
return rule with { Condition = BucketLockCondition.ForSeconds(newSeconds) };
252+
}
253+
return rule;
254+
}).ToList();
255+
256+
await cf.Accounts.Buckets.SetLockAsync(bucket, new BucketLockPolicy(updatedRules));
257+
}
258+
```
259+
260+
## Required Permissions
261+
262+
| Permission | Scope | Level |
263+
|------------|-------|-------|
264+
| Workers R2 Storage | Account | Write |
265+
266+
## Important Notes
267+
268+
1. **Precedence**: If multiple rules apply to the same object, the strictest (longest) retention takes precedence
269+
2. **Maximum rules**: Up to 1000 lock rules per bucket
270+
3. **Immutable objects**: Locked objects cannot be deleted or overwritten until retention expires
271+
4. **Versioning**: Lock rules apply to individual object versions
272+
5. **Billing**: Locked objects continue to incur storage costs during retention
273+
274+
## Compliance Use Cases
275+
276+
| Requirement | Recommended Configuration |
277+
|-------------|---------------------------|
278+
| HIPAA | 6-year retention for medical records |
279+
| SOX | 7-year retention for financial data |
280+
| GDPR | Date-based retention with deletion |
281+
| Legal Hold | Indefinite retention |
282+
283+
## Related
284+
285+
- [Bucket Management](buckets.md) - Create and manage buckets
286+
- [Lifecycle Policies](lifecycle.md) - Automatic object management

0 commit comments

Comments
 (0)