Skip to content

Commit

Permalink
Merge pull request #43 from deveel/40-user-entities-docs
Browse files Browse the repository at this point in the history
Documenting the usage of User Entities Repository
  • Loading branch information
tsutomi authored Jan 26, 2025
2 parents ed40bc7 + 928fae6 commit c395caa
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [Getting Started](index.md)
* [Customize the Repository](custom-repository.md)
* [Multi-Tenancy of Data Sources](multi-tenancy.md)
* [User Entities](user-entities.md)
* [Repository Implementations](repository-implementations/README.md)
* [In-Memory Repositories](repository-implementations/in-memory.md)
* [Entity Framework Core Repositories](repository-implementations/ef-core.md)
Expand Down
75 changes: 75 additions & 0 deletions docs/user-entities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# User Entities

The repository pattern library provides a way to define user entities. These are entities that are specific to the user of the application, and that are not shared between different users.

Within the scope of a tenant, there might be several users, and each user might have its own set of entities (eg. configurations, preferences, etc.).

## Defining User Entities

The data model of an entity is free to be defined by the developer, and it can be any class, but to be used as a user entity, it should implement the `IHaveOwner<TKey>` contract.

Anyway, entities that are intended to be user-specific should provide a field that identifies the user that owns the entity.

For instance, a user entity might look like this:

```csharp
public class UserConfiguration : IHaveOwner<string>
{
public string Id { get; set; }

public string UserId { get; set; }

string IHaveOwner<string>.OwnerKey => UserId;

public string ConfigurationKey { get; set; }

public string ConfigurationValue { get; set; }
}
```

In this case, the `UserId` field is used to identify the user that owns the configuration, and the `ConfigurationKey` and `ConfigurationValue` fields are used to store the configuration data.

**Note**: _The above example uses the `IHaveOwner<TKey>` explicit implementation to provide the owner key of the entity. If you prefer, you can implement the `IHaveOwner<TKey>` interface directly on the entity class, and provide the `OwnerKey` property as a public property._

## Using User Entities Repository

The Deveel Repository framework provides a way to define a repository for user entities, that is specific to the user that is accessing the data.

The repository for user entities is defined by the `IUserRepository<TEntity, TKey, TOwnerKey>` interface, that extends the `IRepository<TEntity>` interface.

In this specific model, the `TEntity` is the type of the entity, `TKey` is the type of the key of the entity, and `TOwnerKey` is the type of the key of the owner of the entity.

With reference to the previous example, the repository for the `UserConfiguration` entity might look like this:

```csharp
public interface IUserConfigurationRepository : IUserRepository<UserConfiguration, string, string>
{
Task<UserConfiguration> FindByUserAsync(string userId, string configurationKey, CancellationToken cancellationToken = default);
}
```

In this case, the `IUserConfigurationRepository` interface extends the `IUserRepository<UserConfiguration, string, string>` interface, and provides an additional method to find a configuration by the user and the configuration key.

### Accessing the Current User at Runtime

The `IUserRepository` interface requires the implementation of a `IUserAccessor` service, that provides the current user identifier at runtime.

The `IUserAccessor` service is defined as follows:
```csharp
public interface IUserAccessor<TKey>
{
TKey? GetUserId();
}
```

The `GetUserId` method should return the identifier of the current user, or `null` if the user is not authenticated.

The `IUserAccessor` service should be registered in the dependency injection container of the application, and it should be provided to the repository implementation.

## Entity Framework Core User Entities Repository

The framework provides a specific implementation of the user entities repository for Entity Framework Core, that allows to store user-specific entities in a relational database.

The `EntityUserRepository<TEntity, TKey, TOwnerKey>` class is the base implementation of the user entities repository for Entity Framework Core, that implements the `IUserRepository<TEntity, TKey, TOwnerKey>` interface.

The logic behind the implementation of the user entities repository is to filter the entities by the owner key, that is provided by the `IUserAccessor` service.

0 comments on commit c395caa

Please sign in to comment.