Ltix.GradeService (Ltix v0.2.0)

Copy Markdown View Source

Manage line items, post scores, and read results from a platform's gradebook using the Assignment and Grade Services (AGS) v2.0.

AGS has two workflows depending on the launch claim.

Coupled. The platform creates a single line item for the resource link. The tool posts scores against that line item directly.

{:ok, client} = Ltix.GradeService.authenticate(launch_context)
:ok = Ltix.GradeService.post_score(client, score)

Programmatic. The tool manages its own line items and can create, update, or delete them.

{:ok, client} = Ltix.GradeService.authenticate(launch_context)
{:ok, items} = Ltix.GradeService.list_line_items(client)
{:ok, item} = Ltix.GradeService.create_line_item(client,
  label: "Quiz 1", score_maximum: 100
)
:ok = Ltix.GradeService.post_score(client, score, line_item: item)

Summary

Functions

Acquire an OAuth token for the grade service.

Create a new line item.

Fetch a single line item.

Fetch all line items from the container endpoint.

Fetch results for a line item.

Same as list_results/2 but raises on error.

Post a score for a user.

Fetch line items as a lazy stream.

Fetch results for a line item as a lazy stream.

Update a line item.

Functions

authenticate(context_or_registerable, opts \\ [])

@spec authenticate(Ltix.LaunchContext.t() | Ltix.Registerable.t(), keyword()) ::
  {:ok, Ltix.OAuth.Client.t()} | {:error, Exception.t()}

Acquire an OAuth token for the grade service.

Accepts a %LaunchContext{} or any struct implementing Ltix.Registerable (including Ltix.Registration). With a launch context, the endpoint and scopes are extracted from the AGS claim. With a registration, pass the endpoint via the :endpoint option, built with Ltix.LaunchClaims.AGSEndpoint.new/1.

From a launch context

{:ok, client} = Ltix.GradeService.authenticate(launch_context)

From a registration

{:ok, client} = Ltix.GradeService.authenticate(registration,
  endpoint:
    AGSEndpoint.new!(
      line_items: "https://lms.example.com/lineitems",
      scopes: ["https://purl.imsglobal.org/spec/lti-ags/scope/lineitem"]
    )
)

Options (launch context)

  • :req_options (keyword/0) - Options passed through to Req.request/2. The default value is [].

  • :local_network_access (nil | :none | :local | :loopback) - Addresses platform requests may connect to besides public ones. :local adds private network addresses, and :loopback adds those and this machine. Defaults to config :ltix, :local_network_access, then :none.

  • :storage_adapter (module/0) - Module implementing Ltix.StorageAdapter, which signs token requests. Defaults to the application configuration.

  • :storage_adapter_options (keyword/0) - Options passed to the storage adapter's signing callbacks. The default value is [].

  • :require_all_scopes (boolean/0) - Return a ScopeMismatch error unless every scope the endpoints need was granted. The default value is false.

Options (registration)

  • :endpoint (struct of type Ltix.LaunchClaims.AGSEndpoint) - Required. AGS endpoint struct.

  • :deployment (term/0) - The deployment the token is for, as a struct implementing Ltix.Deployable or a deployment ID. Token requests include it.

  • :req_options (keyword/0) - Options passed through to Req.request/2. The default value is [].

  • :local_network_access (nil | :none | :local | :loopback) - Addresses platform requests may connect to besides public ones. :local adds private network addresses, and :loopback adds those and this machine. Defaults to config :ltix, :local_network_access, then :none.

  • :storage_adapter (module/0) - Module implementing Ltix.StorageAdapter, which signs token requests. Defaults to the application configuration.

  • :storage_adapter_options (keyword/0) - Options passed to the storage adapter's signing callbacks. The default value is [].

  • :require_all_scopes (boolean/0) - Return a ScopeMismatch error unless every scope the endpoints need was granted. The default value is false.

authenticate!(context_or_registerable, opts \\ [])

Same as authenticate/2 but raises on error.

create_line_item(client, opts)

@spec create_line_item(Ltix.OAuth.Client.t(), keyword()) ::
  {:ok, Ltix.GradeService.LineItem.t()} | {:error, Exception.t()}

Create a new line item.

Options

  • :endpoint (struct of type Ltix.LaunchClaims.AGSEndpoint) - Override the endpoint stored on the client.

  • :label (String.t/0) - Required. Human-readable label.

  • :score_maximum (number/0) - Required. Maximum score (must be > 0).

  • :resource_link_id (String.t/0) - Bind to a resource link.

  • :resource_id (String.t/0) - Tool's resource identifier.

  • :tag (String.t/0) - Qualifier tag.

  • :start_date_time (struct of type DateTime) - When the line item starts accepting submissions.

  • :end_date_time (struct of type DateTime) - When the line item stops accepting submissions.

  • :grades_released (boolean/0) - Hint about releasing grades.

  • :extensions (nil | map/0) - Extension properties keyed by fully qualified URLs, given as strings or atoms. The default value is %{}.

create_line_item!(client, opts)

@spec create_line_item!(Ltix.OAuth.Client.t(), keyword()) ::
  Ltix.GradeService.LineItem.t()

Same as create_line_item/2 but raises on error.

delete_line_item(client, opts \\ [])

@spec delete_line_item(Ltix.OAuth.Client.t(), keyword()) ::
  :ok | {:error, Exception.t()}

Delete a line item.

Returns :ok on success.

By default, returns an error for the platform-coupled line item (the line_item URL from the launch claim). Pass force: true to override.

Options

delete_line_item!(client, opts \\ [])

@spec delete_line_item!(Ltix.OAuth.Client.t(), keyword()) :: :ok

Same as delete_line_item/2 but raises on error.

get_line_item(client, opts \\ [])

@spec get_line_item(Ltix.OAuth.Client.t(), keyword()) ::
  {:ok, Ltix.GradeService.LineItem.t()} | {:error, Exception.t()}

Fetch a single line item.

Options

get_line_item!(client, opts \\ [])

@spec get_line_item!(Ltix.OAuth.Client.t(), keyword()) ::
  Ltix.GradeService.LineItem.t()

Same as get_line_item/2 but raises on error.

list_line_items(client, opts \\ [])

@spec list_line_items(Ltix.OAuth.Client.t(), keyword()) ::
  {:ok, [Ltix.GradeService.LineItem.t()]} | {:error, Exception.t()}

Fetch all line items from the container endpoint.

Follows all rel="next" pagination links and returns a flat list of %LineItem{} structs.

Options

  • :endpoint (struct of type Ltix.LaunchClaims.AGSEndpoint) - Override the endpoint stored on the client.

  • :resource_link_id (String.t/0) - Filter to line items bound to this resource link.

  • :resource_id (String.t/0) - Filter by the tool's resource identifier.

  • :tag (String.t/0) - Filter by tag.

  • :per_page (integer/0) - Page size hint.

  • :max_line_items (integer/0 | :infinity) - Safety limit for eager fetch. Returns a CollectionTooLarge error if exceeded. Set to :infinity to disable, or use stream_line_items/2 for large gradebooks. The default value is 10000.

list_line_items!(client, opts \\ [])

@spec list_line_items!(Ltix.OAuth.Client.t(), keyword()) :: [
  Ltix.GradeService.LineItem.t()
]

Same as list_line_items/2 but raises on error.

list_results(client, opts \\ [])

@spec list_results(Ltix.OAuth.Client.t(), keyword()) ::
  {:ok, [Ltix.GradeService.Result.t()]} | {:error, Exception.t()}

Fetch results for a line item.

GETs {line_item}/results. Follows all rel="next" pagination links and returns a list of %Result{} structs.

Options

  • :endpoint (struct of type Ltix.LaunchClaims.AGSEndpoint) - Override the endpoint stored on the client.

  • :line_item (String.t/0 | struct of type Ltix.GradeService.LineItem) - Line item URL or struct. Defaults to the endpoint's line_item.

  • :user_id (String.t/0) - Filter results to a single user.

  • :per_page (integer/0) - Page size hint.

  • :max_results (integer/0 | :infinity) - Safety limit for eager fetch. Returns a CollectionTooLarge error if exceeded. Set to :infinity to disable, or use stream_results/2 for large courses. The default value is 10000.

list_results!(client, opts \\ [])

@spec list_results!(Ltix.OAuth.Client.t(), keyword()) :: [
  Ltix.GradeService.Result.t()
]

Same as list_results/2 but raises on error.

post_score(client, score, opts \\ [])

@spec post_score(Ltix.OAuth.Client.t(), Ltix.GradeService.Score.t(), keyword()) ::
  :ok | {:error, Exception.t()}

Post a score for a user.

The score is POSTed to {line_item}/scores. When no :line_item option is given, uses the endpoint's line_item URL (coupled flow).

Options

post_score!(client, score, opts \\ [])

@spec post_score!(Ltix.OAuth.Client.t(), Ltix.GradeService.Score.t(), keyword()) ::
  :ok

Same as post_score/3 but raises on error.

stream_line_items(client, opts \\ [])

@spec stream_line_items(Ltix.OAuth.Client.t(), keyword()) ::
  {:ok, Enumerable.t()} | {:error, Exception.t()}

Fetch line items as a lazy stream.

Returns {:ok, stream} where each element is a %LineItem{}. Use this for large gradebooks where you want to process line items incrementally or stop early. list_line_items/2 returns the whole list. Later page failures and parsing errors raise during enumeration.

Options

stream_line_items!(client, opts \\ [])

@spec stream_line_items!(Ltix.OAuth.Client.t(), keyword()) :: Enumerable.t()

Same as stream_line_items/2 but raises on error.

stream_results(client, opts \\ [])

@spec stream_results(Ltix.OAuth.Client.t(), keyword()) ::
  {:ok, Enumerable.t()} | {:error, Exception.t()}

Fetch results for a line item as a lazy stream.

Returns {:ok, stream} where each element is a %Result{}. Use this for large courses where you want to process results incrementally or stop early. list_results/2 returns the whole list. Later page failures and parsing errors raise during enumeration.

Options

stream_results!(client, opts \\ [])

@spec stream_results!(Ltix.OAuth.Client.t(), keyword()) :: Enumerable.t()

Same as stream_results/2 but raises on error.

update_line_item(client, item)

@spec update_line_item(Ltix.OAuth.Client.t(), Ltix.GradeService.LineItem.t()) ::
  {:ok, Ltix.GradeService.LineItem.t()} | {:error, Exception.t()}

Update a line item.

PUTs the full line item to its id URL. Callers should GET first to avoid overwriting fields they did not intend to change.

update_line_item!(client, item)

Same as update_line_item/2 but raises on error.