An open API service indexing awesome lists of open source software.

https://github.com/digitalruby/s3objectstore

Allow storing json objects in S3 easily
https://github.com/digitalruby/s3objectstore

Last synced: 7 months ago
JSON representation

Allow storing json objects in S3 easily

Awesome Lists containing this project

README

          

# S3 Object Store

## Allow storing json objects in S3 easily

Goals:
- Map objects to a sensible s3 hierarchy
- Use json for fast-ish and flexible serialization and model updates + human readability
- Control the folder template name with options

Please see the Sandbox project, `Program.cs` which shows a simple example of using sessions.

### Usage

#### Define an object that implements the `IStorageObject` interface:

```cs
///
/// Example session object
///
public sealed class Session : IStorageObject
{
///
/// The session identifier, probably a guid
///
[JsonPropertyName("k")]
public string? Key { get; set; } = string.Empty;

///
/// The account id the session belongs to, probably a guid. Can be null if no owner.
///
[JsonPropertyName("o")]
public string? Owner { get; set; }

///
/// IP address
///
[JsonPropertyName("i")]
public string IPAddress { get; set; } = string.Empty;

///
/// User agent
///
[JsonPropertyName("a")]
public string UserAgent { get; set; } = string.Empty;

///
/// When the session expires
///
[JsonPropertyName("e")]
public DateTimeOffset Expires { get; set; }

///
/// Could put permissions for the session here
///
[JsonPropertyName("p")]
public string Permissions { get; set; } = string.Empty;

///
public override string ToString()
{
return $"{Key} {Owner} {IPAddress} {UserAgent} {Expires} {Permissions}";
}
}
```

Using `JsonPropertyName` to shorten property names is highly recommended as it will save you on storage space.

The `IStorageObject` interface will return null for both `Key` and `Owner` by default.

In most cases, you will usually implement both the `Key` and `Owner` properties yourself and return `Guid` or some other identifier.

Exceptions to this case:
- You can return null for the `Owner` if your service options (see down below) do not have a format specifier for the owner in the folder template - `{0}`.
- You can return null for the `Key` if your service options specify that the folder format has the file name in it. By default, the `Key` is used as the file name, with a `.json` extension.

#### Create your s3 repository

```cs
// note disable signing is required for cloudflare r2
// set disable signing to false as long as your s3 provider works
var config = new S3Config(accessKey, secretKey, url, disableSigning);

// in production, deleting and creating buckets is not allowed for safety
// you can get both the environment and logger from `IServiceProvider` when using a full .net 6 app.
var repository = new S3StorageRepository(config, new FakeEnvironment(), new NullLogger());
```

#### Create your object service

```cs
var serviceOptions = new StorageObjectServiceOptions
{
Bucket = "bucketname",

// the folder format does not need a {0} if there is no owner for the object (owner is null)
// by default the key will be appended to this folder with a .json extension
FolderFormat = "users/{0}/sessions",

// if your folder format contains the file name, for example to store a user profile, you could use:
// users/{0}/profile.json, which would ignore the key as part of the file name
FolderFormatIncludesFileName = false
};

// create s3 object service, wrapping the s3 repository
var service = new S3StorageObjectService(serviceOptions, repository);
```

#### Perform operations

The storage object service interface is as follows:

```cs
///
/// Storage object service interface. Stores one or more objects (like sessions) with an owner (like a user).
///
/// Types of objects to work with, must be json serializable
public interface IStorageObjectService where T : class, IStorageObject
{
///
/// Get an object by key and owner
///
/// Key
/// Owner identifier
/// Object or null if not found
Task GetObjectAsync(string key, string owner);

///
/// Set an object. The key and owner properties are used to determine the folder path
///
/// Object
/// Task
Task SetObjectAsync(T obj);

///
/// Get all objects for the owner.
///
/// Owner identifier
/// Task of found objects
Task> GetObjectsAsync(string owner);

///
/// Get just the keys for the owner, much more lightweight operation
///
/// Owner
/// Task of keys
Task> GetKeys(string owner);

///
/// Delete object.
///
/// Key
/// Owner identifier
/// Task
Task DeleteObjectAsync(string key, string owner);
}
```

Please email support@digitalruby.com if you have questions or feedback.

-- Jeff