Lightning.Credentials (Lightning v2.13.3)

View Source

The Credentials context.

Summary

Functions

Returns an %Ecto.Changeset{} for tracking credential changes.

Confirms and executes a credential transfer.

Creates a new credential.

Returns an empty changeset structure for credential transfers with an email field.

Creates a changeset for transferring credentials, validating the provided email.

Deletes a credential.

Gets a single credential.

Creates a credential schema from credential json schema.

Checks if a given Credential has any associated Step activity.

Initiates a credential transfer from the owner to the receiver.

Retrieves all credentials based on the given context, either a Project or a User.

Returns all credentials owned by a specific user that are also being used in a specific project.

Refreshes an OAuth token if it has expired, or returns the credential unchanged.

Perform, when called with %{"type" => "purge_deleted"} will find credentials that are ready for permanent deletion, set their bodies to null, and try to purge them.

Revokes a pending credential transfer.

Schedules a given credential for deletion.

Updates an existing credential.

Validates a credential transfer request.

Types

transfer_error()

@type transfer_error() :: :token_error | :not_found | :not_owner

Functions

basic_auth_for(credential)

@spec basic_auth_for(Lightning.Credentials.Credential.t() | nil) :: [String.t()]

cancel_scheduled_deletion(credential_id)

change_credential(credential, attrs \\ %{})

Returns an %Ecto.Changeset{} for tracking credential changes.

Examples

iex> change_credential(credential)
%Ecto.Changeset{data: %Credential{}}

confirm_transfer(credential_id, receiver_id, owner_id, token)

@spec confirm_transfer(String.t(), String.t(), String.t(), String.t()) ::
  {:ok, Lightning.Credentials.Credential.t()}
  | {:error, transfer_error() | Ecto.Changeset.t()}

Confirms and executes a credential transfer.

This function:

  • Verifies the transfer token to ensure the request is valid.
  • Transfers the credential from the owner to the receiver.
  • Records the transfer in the audit log.
  • Deletes all related credential transfer tokens.
  • Notifies both parties about the transfer.

Parameters

  • credential_id: The ID of the Credential being transferred.
  • receiver_id: The ID of the User receiving the credential.
  • owner_id: The ID of the User currently owning the credential.
  • token: The transfer token for verification.

Returns

  • {:ok, credential} on successful transfer.
  • {:error, reason} if the transfer fails.

Errors

  • {:error, :not_found} if the credential or receiver does not exist.
  • {:error, :token_error} if the token is invalid.
  • {:error, :not_owner} if the token does not match the credential owner.
  • {:error, changeset} if there is a validation or update issue.

Example

case confirm_transfer(credential_id, receiver_id, owner_id, token) do
  {:ok, credential} -> IO.puts("Transfer successful")
  {:error, :not_found} -> IO.puts("Error: Credential or receiver not found")
  {:error, :token_error} -> IO.puts("Error: Invalid transfer token")
  {:error, reason} -> IO.inspect(reason, label: "Transfer failed")
end

create_credential(attrs \\ %{})

@spec create_credential(map()) ::
  {:ok, Lightning.Credentials.Credential.t()} | {:error, any()}

Creates a new credential.

For regular credentials, this simply inserts the changeset. For OAuth credentials, this creates a new OAuth token with the provided oauth_token data and associates it with the credential in a 1:1 relationship.

Parameters

  • attrs - Map of attributes for the credential including:
    • user_id - User ID
    • schema - Schema type ("oauth" for OAuth credentials)
    • oauth_client_id - OAuth client ID (for OAuth credentials)
    • body - Credential configuration data
    • oauth_token - OAuth token data (for OAuth credentials)
    • expected_scopes - List of expected scopes (for OAuth credentials)

Returns

  • {:ok, credential} - Successfully created credential
  • {:error, error} - Error with creation process

credential_transfer_changeset()

@spec credential_transfer_changeset() :: Ecto.Changeset.t()

Returns an empty changeset structure for credential transfers with an email field.

Returns

An Ecto.Changeset struct with an empty data map and an email field.

Example

iex> credential_transfer_changeset()
#Ecto.Changeset<...>

credential_transfer_changeset(email)

@spec credential_transfer_changeset(String.t()) :: Ecto.Changeset.t()

Creates a changeset for transferring credentials, validating the provided email.

Parameters

  • email: The email address to be included in the changeset.

Returns

An Ecto.Changeset containing the email field.

Example

iex> credential_transfer_changeset("user@example.com")
#Ecto.Changeset<...>

delete_credential(credential)

Deletes a credential.

Examples

iex> delete_credential(credential)
{:ok, %Credential{}}

iex> delete_credential(credential)
{:error, %Ecto.Changeset{}}

get_credential(id)

get_credential!(id)

Gets a single credential.

Raises Ecto.NoResultsError if the Credential does not exist.

Examples

iex> get_credential!(123)
%Credential{}

iex> get_credential!(456)
** (Ecto.NoResultsError)

get_credential_by_project_credential(project_credential_id)

get_credential_for_update!(id)

get_schema(schema_name)

@spec get_schema(String.t()) :: Lightning.Credentials.Schema.t()

Creates a credential schema from credential json schema.

has_activity_in_projects?(credential)

Checks if a given Credential has any associated Step activity.

Parameters

  • _credential: A Credential struct. Only the id field is used by the function.

Returns

  • true if there's at least one Step associated with the given Credential.
  • false otherwise.

Examples

iex> has_activity_in_projects?(%Credential{id: some_id})
true

iex> has_activity_in_projects?(%Credential{id: another_id})
false

Notes

This function leverages the association between Step and Credential to determine if any steps exist for a given credential. It's a fast check that does not load any records into memory, but simply checks for their existence.

initiate_credential_transfer(owner, receiver, credential)

@spec initiate_credential_transfer(
  Lightning.Accounts.User.t(),
  Lightning.Accounts.User.t(),
  Lightning.Credentials.Credential.t()
) :: :ok | {:error, transfer_error() | Ecto.Changeset.t()}

Initiates a credential transfer from the owner to the receiver.

This function:

  • Marks the credential as pending for transfer.
  • Generates an email token for the credential transfer.
  • Sends a transfer confirmation email to the receiver.

Parameters

  • owner: The User who currently owns the credential.
  • receiver: The User who will receive the credential.
  • credential: The Credential to be transferred.

Returns

  • :ok if the transfer process is successfully initiated.
  • {:error, reason} if any validation or transaction step fails.

Example

case initiate_credential_transfer(owner, receiver, credential) do
  :ok -> IO.puts("Transfer initiated successfully")
  {:error, error} -> IO.inspect(error, label: "Transfer failed")
end

list_credentials(project)

Retrieves all credentials based on the given context, either a Project or a User.

Parameters

  • context: The Project or User struct to retrieve credentials for.

Returns

  • A list of credentials associated with the given Project or created by the given User.

Examples

When given a Project:

iex> list_credentials(%Project{id: 1})
[%Credential{project_id: 1}, %Credential{project_id: 1}]

When given a User:

iex> list_credentials(%User{id: 123})
[%Credential{user_id: 123}, %Credential{user_id: 123}]

list_user_credentials_in_project(user, project)

@spec list_user_credentials_in_project(
  Lightning.Accounts.User.t(),
  Lightning.Projects.Project.t()
) :: [
  Lightning.Credentials.Credential.t()
]

Returns all credentials owned by a specific user that are also being used in a specific project.

Parameters

  • user: The User struct whose credentials we want to find.
  • project: The Project struct to check for credential usage.

Returns

  • A list of Credential structs that are owned by the user and used in the project.

Examples

iex> list_user_credentials_in_project(%User{id: 123}, %Project{id: 456})
[%Credential{user_id: 123, ...}, %Credential{user_id: 123, ...}]

maybe_refresh_token(credential)

Refreshes an OAuth token if it has expired, or returns the credential unchanged.

This function checks the freshness of a credential's associated OAuth token and refreshes it if necessary. For non-OAuth credentials, it simply returns the credential unchanged.

Refresh Logic

The function handles several cases:

  1. Non-OAuth credentials: Returns the credential unchanged
  2. OAuth credential with missing token: Returns the credential unchanged
  3. OAuth credential with missing client: Returns the credential unchanged
  4. OAuth credential with fresh token: Returns the credential unchanged
  5. OAuth credential with expired token: Attempts to refresh the token

Parameters

  • credential: The Credential struct to check and potentially refresh

Returns

  • {:ok, credential}: If the credential was fresh or successfully refreshed
  • {:error, error}: If refreshing the token failed

Examples

iex> maybe_refresh_token(non_oauth_credential)

iex> maybe_refresh_token(fresh_oauth_credential)

iex> maybe_refresh_token(expired_oauth_credential)

perform(job)

Perform, when called with %{"type" => "purge_deleted"} will find credentials that are ready for permanent deletion, set their bodies to null, and try to purge them.

revoke_transfer(credential_id, owner)

Revokes a pending credential transfer.

This function:

  • Ensures the credential exists.
  • Checks that the owner is the one who initiated the transfer.
  • Confirms that the credential is still in a pending state.
  • Resets the transfer status and deletes related credential transfer tokens.

Parameters

  • credential_id: The ID of the Credential being revoked.
  • owner: The User who owns the credential and is revoking the transfer.

Returns

  • {:ok, credential} if the transfer is successfully revoked.
  • {:error, :not_found} if the credential does not exist.
  • {:error, :not_owner} if the user does not own the credential.
  • {:error, :not_pending} if the transfer is not in a pending state.
  • {:error, changeset} if there is a validation or update issue.

Example

case revoke_transfer(credential_id, owner) do
  {:ok, credential} -> IO.puts("Transfer revoked for credential")
  {:error, :not_found} -> IO.puts("Error: Credential not found")
  {:error, :not_owner} -> IO.puts("Error: You do not own this credential")
  {:error, :not_pending} -> IO.puts("Error: Transfer is not pending")
  {:error, reason} -> IO.inspect(reason, label: "Revoke failed")
end

schedule_credential_deletion(credential)

Schedules a given credential for deletion.

The deletion date is determined based on the :purge_deleted_after_days configuration in the application environment. If this configuration is absent, the credential is scheduled for immediate deletion.

The function will also perform necessary side effects such as:

  • Removing associations of the credential.
  • Notifying the owner of the credential about the scheduled deletion.

Parameters

  • credential: A Credential struct that is to be scheduled for deletion.

Returns

  • {:ok, credential}: Returns an :ok tuple with the updated credential struct if the update was successful.
  • {:error, changeset}: Returns an :error tuple with the changeset if the update failed.

Examples

iex> schedule_credential_deletion(%Credential{id: some_id})
{:ok, %Credential{}}

iex> schedule_credential_deletion(%Credential{})
{:error, %Ecto.Changeset{}}

sensitive_values_for(id)

@spec sensitive_values_for(Ecto.UUID.t() | Lightning.Credentials.Credential.t() | nil) ::
  [any()]

update_credential(credential, attrs)

@spec update_credential(Lightning.Credentials.Credential.t(), map()) ::
  {:ok, Lightning.Credentials.Credential.t()} | {:error, any()}

Updates an existing credential.

For regular credentials, this simply updates the changeset. For OAuth credentials, this updates the associated OAuth token with token data provided in the oauth_token parameter.

Parameters

  • credential - The credential to update
  • attrs - Map of attributes to update

Returns

  • {:ok, credential} - Successfully updated credential
  • {:error, error} - Error with update process

validate_credential_transfer(changeset, sender, credential)

Validates a credential transfer request.

This function ensures:

  • The email format is correct.
  • The email does not already exist in the system.
  • The credential is not transferred to the same user.
  • The recipient has access to the necessary projects.

If the changeset is valid, additional validation checks are applied.

Parameters

  • changeset: The Ecto.Changeset containing the credential transfer details.
  • current_user: The user attempting the credential transfer.
  • credential: The credential being transferred.

Returns

  • An updated Ecto.Changeset with validation errors if any issues are found.