Your Jinaga configuration provides these essential pieces of information:
Start simple and expand as you build more features.
Create a class to hold your Jinaga configuration.
Use JinagaClient.Create
to initialize a client having an in-memory store.
public static class JinagaConfig
{
public static JinagaClient CreateJinagaClient(IServiceProvider services)
{
return JinagaClient.Create(opt =>
{
// Configuration options will go here
});
}
}
Register the client in MauiProgram
.
Add the following line to the CreateMauiApp
method.
builder.Services.AddSingleton(JinagaConfig.CreateJinagaClient);
This initial configuration will you get started. Use the following options to add features as you need them.
The Jinaga client can log messages to your provided logger.
Set the LoggerFactory
property to an ILoggerFactory
implementation that you have configured.
return JinagaClient.Create(opt =>
{
opt.LoggerFactory = services.GetRequiredService<ILoggerFactory>();
});
A replicator is your application backend.
It stores the facts and distributes them to other clients.
Set the HttpEndpoint
property to the URL of the replicator.
return JinagaClient.Create(opt =>
{
var settings = new Settings();
opt.HttpEndpoint = new Uri(settings.ReplicatorUrl);
});
Be sure to register an HTTP client factory in MauiProgram
.
builder.Services.AddHttpClient();
Your mobile app users will likely have either a Google or Apple account.
Allow them to log into your app using their existing credentials.
The replicator in Azure has built-in support for Google and Apple authentication.
Set the HttpAuthenticationProvider
to a class that implements IHttpAuthenticationProvider
.
return JinagaClient.Create(opt =>
{
opt.HttpAuthenticationProvider = services.GetRequiredService<IHttpAuthenticationProvider>();
});
The Jinaga.Maui
package includes an implementation that authenticates a Jinaga replicator using Google or Apple.
Create settings for the authentication provider in your JinagaConfig
class.
public static AuthenticationSettings CreateAuthenticationSettings(IServiceProvider services)
{
var settings = new Settings();
var authUrlByProvider = ImmutableDictionary<string, string>.Empty;
authUrlByProvider = authUrlByProvider.Add("Apple", settings.AppleAuthUrl);
authUrlByProvider = authUrlByProvider.Add("Google", settings.GoogleAuthUrl);
var authenticationSettings = new AuthenticationSettings(
authUrlByProvider,
settings.AccessTokenUrl,
settings.RevokeUrl,
settings.CallbackUrl,
settings.ClientId,
settings.Scope,
UpdateUserName);
return authenticationSettings;
}
private static async Task UpdateUserName(JinagaClient jinagaClient, User user, UserProfile profile)
{
// Called when the user logs in so that the app can record the user's name.
}
Register these components in MauiProgram
.
builder.Services.AddSingleton(JinagaConfig.CreateAuthenticationSettings);
builder.Services.AddSingleton(WebAuthenticator.Default);
builder.Services.AddJinagaAuthentication();
To initiate login, call the Login
method on IAuthenticationService
.
Pass the name of the provider to use.
This is typically done in an application view model.
public partial class AppShellViewModel : ObservableObject
{
private readonly IAuthenticationService authenticationService;
private readonly UserProvider userProvider;
public ICommand LogIn { get; }
public ICommand LogOut { get; }
public AppShellViewModel(IAuthenticationService authenticationService, UserProvider userProvider)
{
LogIn = new AsyncRelayCommand<string>(HandleLogIn);
LogOut = new AsyncRelayCommand(HandleLogOut);
this.authenticationService = authenticationService;
this.userProvider = userProvider;
}
private async Task HandleLogIn(string? provider)
{
var isLoggedIn = await authenticationService.LogIn(provider ?? "Apple");
if (isLoggedIn)
{
// Use two slashes to prevent back navigation.
await Shell.Current.GoToAsync("//loggedin");
}
}
public async Task HandleLogOut()
{
await authenticationService.LogOut();
await Shell.Current.GoToAsync("//notloggedin");
}
}
Authorization rules determine who can create facts. Distribution rules determine who can read them. They are covered in Define Authorization Rules and Define Distribution Rules.
The Jinaga.Store.SQLite
package provides local storage for offline operation.
To use it, change JinagaClient.Create
to JinagaSQLiteClient.Create
and set the SQLitePath
property.
All other options remain the same.
return JinagaSQLiteClient.Create(opt =>
{
opt.SQLitePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "myapp.db");
});