Aker holds no key of its own. Your app passes its product name, its version and the root public keys it trusts, and decides itself what a lock blocks.
1. Keep the licence somewhere
The gate reads and writes the licence through a module that implements
Aker.Store. A record is any map or struct with :envelope, :licence_id,
:serial, :term_end and :last_seen_at.
defmodule MyApp.LicenceStore do
@behaviour Aker.Store
@impl true
def current(_opts), do: {:ok, MyApp.Repo.one(MyApp.Licence.newest())}
@impl true
def store(attrs, actor, _opts) do
if actor == :system or MyApp.Accounts.admin?(actor),
do: MyApp.Licence.insert(attrs),
else: {:error, :forbidden}
end
@impl true
def touch(record, last_seen_at, _opts), do: MyApp.Licence.touch(record, last_seen_at)
endThe gate passes the actor from your call to store/3 untouched, and a
renewal stores as :system. Your store decides who may write.
2. Start the gate
def gate_options do
{:ok, root_keys} = Aker.PublicKeys.decode(Application.fetch_env!(:my_app, :root_keys))
[
name: MyApp.Licence,
product: "my_app",
product_version: to_string(Application.spec(:my_app, :vsn)),
root_keys: root_keys,
licence_dir: System.get_env("MY_APP_LICENCE_DIR"),
machine_id_path: System.get_env("MY_APP_MACHINE_ID_PATH"),
store: {MyApp.LicenceStore, []},
server: [base_url: "https://licensing.example.com"],
on_lock: &MyApp.Workers.stop_all/0,
on_unlock: &MyApp.Workers.start_all/0,
settings: [licence_dir: "MY_APP_LICENCE_DIR", machine_id_path: "MY_APP_MACHINE_ID_PATH"]
]
end
# In your application's children:
{Aker.Gate, MyApp.gate_options()}The gate checks the licence at boot, then every hour. In the term's last week each hourly tick asks the server for the next term's licence.
3. Read the lock
Aker.Gate.locked?(MyApp.Licence)
# => true until a licence passesA gate name no check has run under reads {:locked, :not_checked}, so an app
that never starts the gate runs locked. Read the status on each page or job
that the licence guards.
4. Activate, load and refresh
Aker.Gate.activate(MyApp.gate_options(), "ABCD-EFGH-2345", current_user)
Aker.Gate.load(MyApp.gate_options(), File.read!("licence.json"), current_user)
Aker.Gate.refresh(MyApp.gate_options(), current_user)These trust your app to have checked who may call them. Check the caller before you call.