Ltix.LaunchClaims.Role (Ltix v0.1.0)

Copy Markdown View Source

A parsed LTI role with type, name, and optional sub-role.

Roles arrive in launch claims as URI strings. Use parse/1 to convert a single URI, or access them pre-parsed via context.claims.roles.

Checking Roles

Predicate helpers like instructor?/1 and learner?/1 match on the role name regardless of sub-role. This means instructor?/1 returns true for both a principal Instructor and an Instructor#TeachingAssistant:

Role.instructor?(launch.claims.roles)

To check for a specific sub-role, use teaching_assistant?/1 or has_role?/4:

Role.teaching_assistant?(roles)
Role.has_role?(roles, :context, :instructor, :teaching_assistant)

To check for only the principal role (excluding sub-roles), pass nil as the sub-role:

Role.has_role?(roles, :context, :instructor, nil)

Role Types

  • :context — course-level roles (Instructor, Learner, etc.)
  • :institution — institution-level roles (Faculty, Student, etc.)
  • :system — system-level roles (Administrator, SysAdmin, etc.)

Use the filter helpers to narrow by type:

Role.context_roles(roles)
Role.institution_roles(roles)

Examples

iex> Ltix.LaunchClaims.Role.parse("http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor")
{:ok, %Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: nil, uri: "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor"}}

iex> Ltix.LaunchClaims.Role.parse("Instructor")
{:ok, %Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: nil, uri: "Instructor"}}

iex> Ltix.LaunchClaims.Role.parse("http://example.com/unknown")
:error

Summary

Functions

Check if any role is a context Administrator, including sub-roles.

Check if any role is a context ContentDeveloper, including sub-roles.

Filter to only context roles.

Build a role from a well-known atom.

Check if any role matches the given type, name, and optional sub-role.

Filter to only institution roles.

Check if any role is a context Instructor, including sub-roles like TeachingAssistant.

Check if any role is a context Learner, including sub-roles like GuestLearner.

Check if any role is a context Mentor, including sub-roles.

Parse a single role URI into a %Role{} struct.

Parse a list of role URIs, separating recognized from unrecognized.

Filter to only system roles.

Check if any role is an Instructor#TeachingAssistant sub-role.

Convert a %Role{} struct to its URI string.

Types

t()

@type t() :: %Ltix.LaunchClaims.Role{
  name: atom(),
  sub_role: atom() | nil,
  type: :context | :institution | :system,
  uri: String.t()
}

t_without_uri()

@type t_without_uri() :: %Ltix.LaunchClaims.Role{
  name: atom(),
  sub_role: atom() | nil,
  type: :context | :institution | :system,
  uri: nil
}

Functions

administrator?(roles)

@spec administrator?([t()]) :: boolean()

Check if any role is a context Administrator, including sub-roles.

content_developer?(roles)

@spec content_developer?([t()]) :: boolean()

Check if any role is a context ContentDeveloper, including sub-roles.

context_roles(roles)

@spec context_roles([t()]) :: [t()]

Filter to only context roles.

from_atom(atom)

@spec from_atom(atom()) :: t()

Build a role from a well-known atom.

Supports common context roles, one sub-role, and a handful of institution and system roles. Raises ArgumentError for unknown atoms.

Context roles

iex> Ltix.LaunchClaims.Role.from_atom(:instructor)
%Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: nil, uri: "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor"}

iex> Ltix.LaunchClaims.Role.from_atom(:learner)
%Ltix.LaunchClaims.Role{type: :context, name: :learner, sub_role: nil, uri: "http://purl.imsglobal.org/vocab/lis/v2/membership#Learner"}

Sub-roles

iex> Ltix.LaunchClaims.Role.from_atom(:teaching_assistant)
%Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: :teaching_assistant, uri: "http://purl.imsglobal.org/vocab/lis/v2/membership/Instructor#TeachingAssistant"}

Institution roles

iex> Ltix.LaunchClaims.Role.from_atom(:faculty)
%Ltix.LaunchClaims.Role{type: :institution, name: :faculty, sub_role: nil, uri: "http://purl.imsglobal.org/vocab/lis/v2/institution/person#Faculty"}

System roles

iex> Ltix.LaunchClaims.Role.from_atom(:test_user)
%Ltix.LaunchClaims.Role{type: :system, name: :test_user, sub_role: nil, uri: "http://purl.imsglobal.org/vocab/lti/system/person#TestUser"}

has_role?(roles, type, name, sub_role \\ nil)

@spec has_role?([t()], :context | :institution | :system, atom(), atom() | nil) ::
  boolean()

Check if any role matches the given type, name, and optional sub-role.

Examples

iex> {:ok, role} = Ltix.LaunchClaims.Role.parse("http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor")
iex> Ltix.LaunchClaims.Role.has_role?([role], :context, :instructor)
true

institution_roles(roles)

@spec institution_roles([t()]) :: [t()]

Filter to only institution roles.

instructor?(roles)

@spec instructor?([t()]) :: boolean()

Check if any role is a context Instructor, including sub-roles like TeachingAssistant.

To check for only the principal Instructor role (excluding sub-roles), use has_role?(roles, :context, :instructor, nil).

learner?(roles)

@spec learner?([t()]) :: boolean()

Check if any role is a context Learner, including sub-roles like GuestLearner.

To check for only the principal Learner role (excluding sub-roles), use has_role?(roles, :context, :learner, nil).

mentor?(roles)

@spec mentor?([t()]) :: boolean()

Check if any role is a context Mentor, including sub-roles.

parse(uri, opts \\ [])

@spec parse(
  String.t(),
  keyword()
) :: {:ok, t()} | :error

Parse a single role URI into a %Role{} struct.

Tries registered parsers by URI prefix, then falls back to short context role names. The LIS vocabulary parser is registered by default.

Returns {:ok, %Role{}} for recognized roles, :error for unknown URIs.

Options

  • :parsers — map of URI prefix to parser module or function (defaults to application config, with LIS as a fallback)

Examples

iex> Ltix.LaunchClaims.Role.parse("http://purl.imsglobal.org/vocab/lis/v2/membership#Learner")
{:ok, %Ltix.LaunchClaims.Role{type: :context, name: :learner, sub_role: nil, uri: "http://purl.imsglobal.org/vocab/lis/v2/membership#Learner"}}

iex> Ltix.LaunchClaims.Role.parse("http://purl.imsglobal.org/vocab/lis/v2/membership/Instructor#TeachingAssistant")
{:ok, %Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: :teaching_assistant, uri: "http://purl.imsglobal.org/vocab/lis/v2/membership/Instructor#TeachingAssistant"}}

parse_all(uris, opts \\ [])

@spec parse_all(
  [String.t()],
  keyword()
) :: {[t()], [String.t()]}

Parse a list of role URIs, separating recognized from unrecognized.

Returns {parsed_roles, unrecognized_uris} where order is preserved.

Options

  • :parsers — map of URI prefix to parser module or function (defaults to application config, with LIS as a fallback)

Examples

iex> Ltix.LaunchClaims.Role.parse_all([])
{[], []}

system_roles(roles)

@spec system_roles([t()]) :: [t()]

Filter to only system roles.

teaching_assistant?(roles)

@spec teaching_assistant?([t()]) :: boolean()

Check if any role is an Instructor#TeachingAssistant sub-role.

to_uri(role)

@spec to_uri(t_without_uri()) :: {:ok, String.t()} | :error

Convert a %Role{} struct to its URI string.

Tries each registered parser's to_uri/1 callback until one succeeds. The LIS parser is tried by default.

Examples

iex> role = %Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: nil}
iex> Ltix.LaunchClaims.Role.to_uri(role)
{:ok, "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor"}

iex> role = %Ltix.LaunchClaims.Role{type: :context, name: :instructor, sub_role: :teaching_assistant}
iex> Ltix.LaunchClaims.Role.to_uri(role)
{:ok, "http://purl.imsglobal.org/vocab/lis/v2/membership/Instructor#TeachingAssistant"}