1.4 KiB · text 5af55d9
defmodule GitGud.Accounts.PersonalAccessToken do
@moduledoc """
A user-scoped API token (`ggp_…`) for the REST API. Only the SHA-256
`token_hash` is stored; the plaintext is shown once at creation.
`scopes` is a subset of the extensible vocabulary in `scopes/0`. The
API authorizes each request against the required scope, so new scopes
can be added here over time without changing existing tokens. Today:
* `repo` — create / manage repositories
"""
use Ecto.Schema
import Ecto.Changeset
alias GitGud.Accounts.User
# Extend this list to add scopes; tokens are validated against it.
@scopes ~w(repo)
schema "personal_access_tokens" do
field :name, :string
field :token_hash, :binary, redact: true
field :scopes, {:array, :string}, default: []
field :last_used_at, :utc_datetime
belongs_to :user, User
timestamps(type: :utc_datetime)
end
@doc false
def changeset(token, attrs) do
token
|> cast(attrs, [:name, :token_hash, :scopes, :user_id])
|> validate_required([:name, :token_hash, :user_id])
|> validate_length(:name, min: 1, max: 100)
|> validate_subset(:scopes, @scopes)
|> validate_length(:scopes, min: 1)
|> unique_constraint(:name, name: :personal_access_tokens_user_id_name_index)
|> unique_constraint(:token_hash)
end
@doc "The set of scopes a token may carry."
def scopes, do: @scopes
end