ATProto utilities for the Ash Framework
elixir atproto ash
Elixir 96.3%
Shell 0.3%
Nix 0.1%
Other 3.4%
11 1 0

Clone this repository

https://tangled.org/lekkice.moe/ash-atproto https://tangled.org/did:plc:dgzvruva4jbzqbta335jtvoz/ash-atproto
git@tangled.org:lekkice.moe/ash-atproto git@tangled.org:did:plc:dgzvruva4jbzqbta335jtvoz/ash-atproto

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

AshAtproto#

Ash utilities built on top of atex to make integrating with ATProto easier. It includes:

  • An Ash extension that provides resource actions and attributes for an user.
  • An AshAuthentication strategy to enable the OAuth flow.
  • AN XRPC client to make requests using an user resource.

Installation#

The package can be installed by adding ash_atproto to your list of dependencies in mix.exs:

def deps do
  [
    {:ash_atproto, "~> 0.1.0"}
  ]
end

User resource extension#

This extension modifies your resource to add the following attributes:

  • :did: an user's DID. This will be used as a primary key.
  • :handle: an user's handle. This is cached for easier access, but it can become stale.
  • :oauth_tokens: a struct with the OAuth response data.

These attributes can be overridden if necessary, and new attributes can be added with no issues.

It also includes the following actions:

  • :register_with_atproto: upsert used for both registers and sign ins.
  • :refresh: updates the :oauth_tokens attribute.
  • :read
  • :destroy

Example#

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    otp_app: :my_app,
    domain: MyApp.Accounts,
    authorizers: [Ash.Policy.Authorizer],
    extensions: [AshAuthentication, AshAtproto.Auth, AshAtproto.UserResource],
    data_layer: AshPostgres.DataLayer

  authentication do
    tokens do
      enabled? true
      require_token_presence_for_authentication? true
      token_resource MyApp.Accounts.Token
      signing_secret MyApp.Secrets
      store_all_tokens? true
    end

    strategies do
      atproto do
        registration_enabled? true
        base_url MyApp.Secrets

        private_key MyApp.Secrets
        key_id(MyApp.Secrets)
      end
    end
  end

  postgres do
    table "users"
    repo MyApp.Repo
  end

  actions do
    read :get_by_subject do
      description "Get a user by the subject claim in a JWT"
      argument :subject, :string, allow_nil?: false
      get? true
      prepare AshAuthentication.Preparations.FilterBySubject
    end
  end

  policies do
    bypass AshAuthentication.Checks.AshAuthenticationInteraction do
      authorize_if always()
    end

    policy always() do
      forbid_if always()
    end
  end
end

AshAuthentication strategy#

A strategy that enables seamless integration with the rest of AshAuthentication. The atproto strategy is standalone, and can be used without the user resource extension (replacing it with AshAuthentication.UserIdentity, for example).

Example#

use Ash.Resource,
  extensions: [AshAuthentication, AshAtproto.Auth],

strategies do
  atproto do
    registration_enabled? true
    base_url MyApp.Secrets

    private_key MyApp.Secrets
    key_id(MyApp.Secrets)
  end
end

Configuration values can be passed directly, but using AshAuthentication.Secret is recommended.

OAuth client#

An HTTP API client that follows the XRPC conventions. Will automatically refresh tokens if needed.

Example#

user_resource = Ash.read_one!(MyApp.Accounts.User, authorize?: false)
{:ok, client} = AshAtproto.XRPC.OAuthClient.new(user_resource)

# Make XRPC requests
{:ok, response, client} =
  Atex.XRPC.get(client, "com.atproto.repo.listRecords",
    params: [repo: user.handle, collection: "app.bsky.graph.follow"]
  )

For more details, including lexicon code generation and typed parameters, check the Atex.XRPC module.

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/ash_atproto.