| DEVELOPER BUILDS | RELEASE BUILDS |
|---|---|
This package provides infrastructure templates to facilitate the creation of backend services. This is a personal project with no commercial backing and offers no guarantees regarding future development.
A sample usage scenario is available here.
using AutoBackend.Sdk;
await new AutoBackendHost<Program>().RunAsync(args);Refer to the sample project models for examples.
public class Budget
{
public Guid Id { get; set; }
//..
}
public class Transaction
{
public Guid Id { get; set; }
//..
}
public class TransactionVersion
{
//..
}
public class User
{
public long Id { get; set; }
//..
}
public class Participating
{
public long UserId { get; set; }
public Guid BudgetId { get; set; }
//..
}All features are detailed in the sections below.
The following relational databases are currently supported (including in-memory):
- SqlServer
- Postgres
AutoBackend.SDK will generate tables and establish relationships for your configured entities.
There are typically three types of database tables:
- Keyless,
- Single-column primary key,
- Multi-column primary key.
Depending on the number of primary key columns in your entity, follow the instructions below to enable AutoBackend.SDK to track changes.
Use the [GenericEntity] attribute to designate a model as a keyless entity.
[GenericEntity]
public class TransactionVersion
{
//...
}Use the [GenericEntity(<primary key property name>)] attribute to designate a model as an entity with a single-column primary key.
[GenericEntity(
nameof(Id)
)]
public class Budget
{
public Guid Id { get; set; }
// ...
}Use the [GenericEntity(<primary key property names>)] attribute to designate a model as an entity with a composite
primary key.
Currently, the maximum number of properties in a composite key is 8.
This limit should be sufficient for most use cases.
[GenericEntity(
nameof(UserId),
nameof(BudgetId)
)]
public class Participating
{
public long UserId { get; set; }
public Guid BudgetId { get; set; }
// ...
}To configure database connection management, set up the "Database" section in your configuration.
"Database": {
"PrimaryProvider": "InMemory",
"Providers": {
"InMemory": "InMemory database name",
"SqlServer": "SqlServer database connection string",
"Postgres": "Postgres database connection string"
}
}The PrimaryProvider property accepts one of the following string values:
InMemory,SqlServer,Postgres.
The Providers property must contain an object with optional properties: InMemory, SqlServer, or Postgres. The property corresponding to the selected PrimaryProvider value is required.
First, install Entity Framework Core Tools. You can create a new migration by executing one of the following commands from the project root directory:
- For SqlServer:
dotnet ef migrations add "<your migration name>" -o Migrations/SqlServer -c SqlServerGenericDbContext - For Postgres:
dotnet ef migrations add "<your migration name>" -o Migrations/Postgres -c PostgresGenericDbContext
Alternatively, you can use the provided scripts to add a new migration or to remove the last migration for both database providers.
If you choose not to use AutoBackend's migration management (see above), you can perform migrations manually by executing dotnet ef database update from the project root directory.
When using a relational database (e.g., SqlServer or Postgres), you can configure AutoBackend to automatically migrate the database at application startup by passing the migrateRelationalOnStartup parameter to the RunAsync method during AutoBackend initialization. For example:
await new AutoBackend.Sdk.AutoBackendHost<Program>().RunAsync(args, migrateRelationalOnStartup: true);AutoBackend.SDK currently supports two types of API interfaces:
- HTTP REST API
- GraphQL
Apply the [GenericController] attribute to your models to have AutoBackend generate HTTP API endpoints.
❗Disclaimer
The
[GenericController]attribute is compatible only with models also marked with[GenericEntity].
The current API version is v1. API v1 uses JSON and follows the following response container format:
{
"ok": boolean,
"error_code": number,
"description": string,
"request_time_ms": number,
"result": <response object>
}
For detailed information on generated endpoints, visit /swagger.
The [GenericController] attribute generates the following HTTP API endpoints:
| Method | Url | Keyless | Single-PK | Multi-PK | Description |
|---|---|---|---|---|---|
GET |
/api/v1/<model name> |
✔️ | ✔️ | ✔️ | Retrieve all entities of a specific model |
GET |
/api/v1/<model name>/count |
✔️ | ✔️ | ✔️ | Retrieve the count of entities of a specific model |
GET |
/api/v1/<model name>/<pk1> |
❌ | ✔️ | ❌ | Retrieve an entity with the requested primary key of a specific model |
GET |
/api/v1/<model name>/<pk1>/<pk2>/.../<pkN> |
❌ | ❌ | ✔️ | Retrieve an entity with the requested composite primary key of a model |
POST |
/api/v1/<model name> |
✔️ | ❌ | ❌ | Create a new keyless entity of a specific model |
POST |
/api/v1/<model name>/<pk1> |
❌ | ✔️ | ❌ | Create a new entity with the specified primary key of a specific model |
POST |
/api/v1/<model name>/<pk1>/<pk2>/.../<pkN> |
❌ | ❌ | ✔️ | Create a new entity with the specified composite primary key of a model |
PUT |
/api/v1/<model name>/<pk1> |
❌ | ✔️ | ❌ | Update an entity with the specified primary key of a specific model |
PUT |
/api/v1/<model name>/<pk1>/<pk2>/.../<pkN> |
❌ | ❌ | ✔️ | Update an entity with the specified composite primary key of a model |
DELETE |
/api/v1/<model name>/<pk1> |
❌ | ✔️ | ❌ | Delete an entity with the specified primary key of a specific model |
DELETE |
/api/v1/<model name>/<pk1>/<pk2>/.../<pkN> |
❌ | ❌ | ✔️ | Delete an entity with the specified composite primary key of a model |
📘Filtering Capabilities
Refer to the following section for more information on filtering.
[GenericEntity(
nameof(Id)
)]
[GenericController]
public class User
{
public long Id { get; set; }
// ...
}Apply the [GenericGqlQuery] and [GenericGqlMutation] attributes to your models to generate GraphQL queries and mutations, respectively.
❗Disclaimer
The
[GenericGqlQuery]and[GenericGqlMutation]attributes are compatible only with models also marked with[GenericEntity].
For detailed information on generated queries and mutations, visit /graphql.
The [GenericGqlQuery] attribute generates the following GraphQL queries:
| Query | Arguments | Keyless | Single-PK | Multi-PK | Description |
|---|---|---|---|---|---|
all |
filter: generic filter input model |
✔️ | ✔️ | ✔️ | Retrieve all entities of a specific model |
count |
filter: generic filter input model |
✔️ | ✔️ | ✔️ | Retrieve the count of entities of a specific model |
byKey |
key: entity primary key |
❌ | ✔️ | ❌ | Retrieve an entity with the requested primary key of a model |
byKey |
key1, key2, ..., keyN: entity PK-set |
❌ | ❌ | ✔️ | Retrieve an entity with the requested composite primary key |
📘Filtering Capabilities
Refer to the following section for more information on filtering.
[GenericEntity(
nameof(Id)
)]
[GenericGqlQuery]
public class User
{
public long Id { get; set; }
// ...
}The [GenericGqlMutation] attribute generates the following GraphQL mutations:
| Mutation | Arguments | Keyless | Single-PK | Multi-PK | Description |
|---|---|---|---|---|---|
create |
request: generic entity input model |
✔️ | ❌ | ❌ | Create a new keyless entity of a specific model |
create |
key: entity primary key, request: generic entity input model |
❌ | ✔️ | ❌ | Create a new entity with the specified primary key of a model |
create |
key1, key2, ..., keyN: entity PK-set, request: generic entity input model |
❌ | ❌ | ✔️ | Create a new entity with the specified composite primary key |
update |
key: entity primary key, request: generic entity input model |
❌ | ✔️ | ❌ | Update an entity with the specified primary key of a model |
update |
key1, key2, ..., keyN: entity PK-set, request: generic entity input model |
❌ | ❌ | ✔️ | Update an entity with the specified composite primary key |
delete |
key: entity primary key (for PK-holder entities only) |
❌ | ✔️ | ❌ | Delete an entity with the specified primary key |
delete |
key1, key2, ..., keyN: entity PK-set |
❌ | ❌ | ✔️ | Delete an entity with the specified composite primary key |
[GenericEntity(
nameof(Id)
)]
[GenericGqlMutation]
public class User
{
public long Id { get; set; }
// ...
}AutoBackend.SDK automatically generates request and response models for any entity with HTTP API or GraphQL generation configured.
By default, these models include all original entity properties. However, if you explicitly specify properties using the [GenericRequest] or [GenericResponse] attributes, only those specified properties will be included, and all others will be omitted.
The [GenericRequest] attribute specifies which properties can be mapped from the request model to the entity.
[GenericEntity(
nameof(Id)
)]
[GenericController]
[GenericGqlQuery]
[GenericGqlMutation]
[GenericRequest(
nameof(Id),
nameof(UserId),
nameof(BudgetId),
nameof(Amount),
nameof(DateTimeUtc),
nameof(Comment),
nameof(SecretKey)
)]
public class Transaction
{
// ...
}The [GenericResponse] attribute specifies which properties can be mapped from the entity to the response model.
[GenericEntity(
nameof(Id)
)]
[GenericController]
[GenericGqlQuery]
[GenericGqlMutation]
[GenericResponse(
nameof(Id),
nameof(UserId),
nameof(BudgetId),
nameof(Amount),
nameof(DateTimeUtc),
nameof(Comment)
)]
public class Transaction
{
// ...
}AutoBackend.SDK supports permission-based authorization using JWT tokens. You can control access to CRUD operations at both entity and property levels.
Configure JWT settings in your appsettings.json:
"Jwt": {
"PublicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
"ValidIssuer": "AutoBackendServer",
"ValidAudience": "AutoBackendUser"
}PublicKey: RSA public key in PEM format (required) - used to verify JWT token signaturesValidIssuer: Optional issuer validationValidAudience: Optional audience validation
Use permission attributes on entity classes to require authorization for specific operations:
[GenericCreatePermission]- Requires permission to create entities[GenericReadPermission]- Requires permission to read entities[GenericUpdatePermission]- Requires permission to update entities[GenericDeletePermission]- Requires permission to delete entities
[GenericEntity(
nameof(Id)
)]
[GenericController]
[GenericGqlQuery]
[GenericGqlMutation]
[GenericCreatePermission]
[GenericReadPermission]
[GenericUpdatePermission]
[GenericDeletePermission]
public class Budget
{
public Guid Id { get; set; }
// ...
}
⚠️ Note: Property-level permissions are currently only processed for Update operations.
You can apply permission attributes to individual properties for fine-grained access control during update operations:
[GenericEntity(
nameof(Id)
)]
[GenericController]
[GenericGqlMutation]
[GenericUpdatePermission]
public class Transaction
{
public Guid Id { get; set; }
[GenericUpdatePermission]
public string? SecretKey { get; set; }
// ...
}When updating an entity, AutoBackend will check property-level permissions only for properties that are actually being modified. This allows you to restrict access to sensitive fields while allowing updates to other properties.
JWT tokens must be sent in the Authorization header with the Bearer prefix:
Authorization: Bearer <your-jwt-token>
The JWT token must contain claims with:
- Type:
permissions - Value: Permission strings in the format
{EntityName}{PermissionType}or{EntityName}{PropertyName}{PermissionType}
- Entity permissions:
{EntityName}{PermissionType}- Examples:
BudgetCreate,BudgetRead,BudgetUpdate,BudgetDelete
- Examples:
- Property permissions:
{EntityName}{PropertyName}{PermissionType}(only for Update operations)- Examples:
TransactionSecretKeyUpdate
- Examples:
{
"permissions": [
"BudgetCreate",
"BudgetRead",
"BudgetUpdate",
"BudgetDelete",
"TransactionSecretKeyUpdate"
]
}When a request lacks required permissions, AutoBackend returns an Unauthorized error with details about missing permissions.
AutoBackend.SDK generates filter models for any entity with configured HTTP API or GraphQL generation. By default, these
models include only pagination management properties. To include specific entity properties in the filter model, use
the [GenericFilter] attribute.
By default, two filter parameters are always available for any GET request (returning a list of entities) or GraphQL queries to manage pagination:
skipCount: numbertakeCount: number
The [GenericFilter] attribute marks a model property as filterable in the generated filter model.
[GenericEntity(
nameof(Id)
)]
[GenericController]
[GenericGqlQuery]
[GenericGqlMutation]
public class Budget
{
[GenericFilter]
public Guid Id { get; set; }
[GenericFilter]
public string Name { get; set; }
[GenericFilter]
public long? OwnerId { get; set; }
// ...
}AutoBackend will construct a filter model with parameters that can be used in API endpoints like /api/v1/<model name> or /api/v1/<model name>/count, as well as in GraphQL queries.
- API filter parameter names follow the pattern:
<property's camelCase-name>.<condition name> - GraphQL queries will have filtering models with condition properties generated
The following filter conditions are supported:
equalnotEqualgreaterThangreaterThanOrEquallessThanlessThanOrEqualinisNull