From 590cd56c19b3d694b8de79abf7f38b9e2193d45c Mon Sep 17 00:00:00 2001 From: madclaws Date: Mon, 30 Oct 2023 05:01:14 +0530 Subject: [PATCH] feat: final refactor it seems --- README.md | 13 ++++++---- lib/ex_ucan/builder.ex | 17 ------------- lib/ex_ucan/core/capability/data.ex | 37 ++++++++++++++++++----------- lib/ex_ucan/core/structs.ex | 28 ++++++++++++++++++++-- lib/ex_ucan/core/token.ex | 2 +- test/capability_test.exs | 25 ------------------- 6 files changed, 58 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 5929c3e..db05031 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ![ticket](doc_assets/ticket-4.png?raw=true "ticket") + # ExUcan > Decentralized Auth with [UCANs](https://ucan.xyz/) @@ -171,7 +172,7 @@ ExUcan.validate_token(token) ### Adding Capabilities -`capabilities` are an list of `resources`, the `abilities` that we can make on the `resource` with some optional `caveats`. +`capabilities` are a list of `resources`, and the `abilities` that we can make on the `resource` with some optional `caveats`. ```elixir @@ -212,12 +213,14 @@ iex> ucan_payload = The library is no-where feature parity with ucan [rust](https://github.com/ucan-wg/rs-ucan/tree/main) library or with the spec. The spec itself is nearing a 1.0.0, and is under-review. But good thing is we have now laid the basic foundations. The next immediate additions would be, -- [ ] - Proof encodings as CID (Content Addressable Data) -- [ ] - Delegation semantics -- [ ] - Verifying UCAN invocations +- [ ] Proof encodings as CID (Content Addressable Data) +- [ ] Delegation semantics +- [ ] Verifying UCAN invocations ## Acknowledgement -This library has taken reference from both [ts-ucan](https://github.com/ucan-wg/ts-ucan) and rs-ucan. +- This library has taken reference from both [ts-ucan](https://github.com/ucan-wg/ts-ucan) and rs-ucan. + +- ExUcan logo - Validating ticket icons created by Good Ware - Flaticon diff --git a/lib/ex_ucan/builder.ex b/lib/ex_ucan/builder.ex index 5ca2b76..ee53feb 100644 --- a/lib/ex_ucan/builder.ex +++ b/lib/ex_ucan/builder.ex @@ -116,19 +116,6 @@ defmodule ExUcan.Builder do %{builder | add_nonce?: true} end - # TODO: try to do this function - @doc """ - Includes a UCAN in the list of proofs for the UCAN to be built. - Note that the proof's audience must match this UCAN's issuer - or else the proof chain will be invalidated! - The proof is encoded into a [Cid], hashed via the [UcanBuilder::default_hasher()] - algorithm, unless one is provided. - """ - @spec witnessed_by(__MODULE__.t()) :: __MODULE__.t() - def witnessed_by(builder) do - builder - end - @doc """ Claim a capability by inheritance (from an authorizing proof) or implicitly by ownership of the resource by this UCAN's issuer @@ -138,10 +125,6 @@ defmodule ExUcan.Builder do %{builder | capabilities: builder.capabilities ++ [capability]} end - def delegating_from(builder) do - builder - end - @doc """ Builds the UCAN `payload` from the `Builder` workflow diff --git a/lib/ex_ucan/core/capability/data.ex b/lib/ex_ucan/core/capability/data.ex index 241e4f7..15fbd0e 100644 --- a/lib/ex_ucan/core/capability/data.ex +++ b/lib/ex_ucan/core/capability/data.ex @@ -1,5 +1,8 @@ defmodule ExUcan.Core.Capability do - # TODO: All the docs needed + @moduledoc """ + Capabilities are a list of `resources`, and the `abilities` that we + can make on the `resource` with some optional `caveats`. + """ @type t :: %__MODULE__{ resource: String.t(), ability: String.t(), @@ -7,6 +10,11 @@ defmodule ExUcan.Core.Capability do } defstruct [:resource, :ability, :caveat] + @doc """ + Creates a new capability with given resource, ability and caveat + + See `/test/capability_test.exs` + """ @spec new(String.t(), String.t(), list()) :: __MODULE__.t() def new(resource, ability, caveat) do %__MODULE__{ @@ -19,23 +27,19 @@ end defmodule ExUcan.Core.Capabilities do @moduledoc """ - Capabilities always deals with capabilites as map of maps - map> - """ - alias ExUcan.Core.Capability - # TODO: All the docs needed + Handling conversions of different type of group of capabilities - # def validate(capabilities) when is_map(capabilities) do - # capabilities - # |> Enum.reduce_while(%{}, fn {resource, ability}, caps -> - # # ability should be map - # # iter through ability + `Capabilities` are always maps of maps - # end) - # end + type reference - map> + """ + alias ExUcan.Core.Capability - def validate(_), do: {:error, "Capabilities must be an object."} + @doc """ + Convert capabilites represented in maps to list of capabilites + See `/test/capability_test.exs` + """ @spec map_to_sequence(map()) :: list(Capability.t()) def map_to_sequence(capabilities) do capabilities @@ -45,6 +49,11 @@ defmodule ExUcan.Core.Capabilities do end) end + @doc """ + Convert capabilites represented as list of capabilities to maps of maps + + See `/test/capability_test.exs` + """ @spec sequence_to_map(list(Capability.t())) :: map() def sequence_to_map(capabilites) do capabilites diff --git a/lib/ex_ucan/core/structs.ex b/lib/ex_ucan/core/structs.ex index 9e94b7c..3738a3d 100644 --- a/lib/ex_ucan/core/structs.ex +++ b/lib/ex_ucan/core/structs.ex @@ -1,6 +1,11 @@ defmodule ExUcan.Core.Structs.UcanHeader do @moduledoc """ - Ucan header + Ucan header representation + """ + + @typedoc """ + alg - Algorithm used (ex EdDSA) + typ - Type of token format (ex JWT) """ @type t :: %__MODULE__{ alg: String.t(), @@ -13,10 +18,23 @@ end defmodule ExUcan.Core.Structs.UcanPayload do @moduledoc """ - Ucan Payload + Ucan Payload representation """ alias ExUcan.Core.Capability + @typedoc """ + + ucv: UCAN version. + iss: Issuer, the DID of who sent this. + aud: Audience, the DID of who it's intended for. + nbf: Not Before, unix timestamp of when the jwt becomes valid. + exp: Expiry, unix timestamp of when the jwt is no longer valid. + nnc: Nonce value to increase the uniqueness of UCAN token. + fct: Facts, an array of extra facts or information to attach to the jwt. + cap: A list of resources and capabilities that the ucan grants. + prf: Proof, an optional nested token with equal or greater privileges. + + """ @type t :: %__MODULE__{ ucv: String.t(), iss: String.t(), @@ -40,6 +58,12 @@ defmodule ExUcan.Core.Structs.Ucan do alias ExUcan.Core.Structs.UcanHeader alias ExUcan.Core.Structs.UcanPayload + @typedoc """ + header - Token Header + payload - Token payload + signed_data - Data that would be eventually signed + signature - Base64Url encoded signature + """ @type t :: %__MODULE__{ header: UcanHeader.t(), payload: UcanPayload.t(), diff --git a/lib/ex_ucan/core/token.ex b/lib/ex_ucan/core/token.ex index 3e8cc94..6d5d21c 100644 --- a/lib/ex_ucan/core/token.ex +++ b/lib/ex_ucan/core/token.ex @@ -1,6 +1,6 @@ defmodule ExUcan.Core.Token do @moduledoc """ - Creates and manages UCAN tokens + Core functions for the creation and management of UCAN tokens """ alias ExUcan.Builder alias ExUcan.Core.Structs.Ucan diff --git a/test/capability_test.exs b/test/capability_test.exs index 5aa7841..aa72cf3 100644 --- a/test/capability_test.exs +++ b/test/capability_test.exs @@ -14,29 +14,4 @@ defmodule CapabilityTest do cap_maps = Capabilities.sequence_to_map(cap_sequence) assert Capabilities.map_to_sequence(cap_maps) == cap_sequence end - - test "it_rejects_non_compliant_json" do - failure_cases = [ - { - [], - "resources must be map" - }, - { - %{"resource:foo" => []}, - "abilities must be map" - }, - { - %{"resource:foo" => {}}, - "resource must have at least one ability" - }, - { - %{"resource:foo" => %{"ability/read" => %{}}}, - "caveats must be a list" - }, - { - %{"resource:foo" => %{"ability/read" => [1]}}, - "caveat must be object" - } - ] - end end