- def create_token(%App{} = app, %User{} = user, scopes \\ nil) do
- scopes = scopes || app.scopes
- token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
- refresh_token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
-
- token = %Token{
- token: token,
- refresh_token: refresh_token,
- scopes: scopes,
- user_id: user.id,
- app_id: app.id,
- valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10)
- }
-
- Repo.insert(token)
+ defp put_token(changeset) do
+ changeset
+ |> change(%{token: Token.Utils.generate_token()})
+ |> validate_required([:token])
+ |> unique_constraint(:token)
+ end
+
+ defp put_refresh_token(changeset, attrs) do
+ refresh_token = Map.get(attrs, :refresh_token, Token.Utils.generate_token())
+
+ changeset
+ |> change(%{refresh_token: refresh_token})
+ |> validate_required([:refresh_token])
+ |> unique_constraint(:refresh_token)
+ end
+
+ defp put_valid_until(changeset, attrs) do
+ expires_in =
+ Map.get(attrs, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), expires_in()))
+
+ changeset
+ |> change(%{valid_until: expires_in})
+ |> validate_required([:valid_until])
+ end
+
+ @spec create_token(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Changeset.t()}
+ def create_token(%App{} = app, %User{} = user, attrs \\ %{}) do
+ %__MODULE__{user_id: user.id, app_id: app.id}
+ |> cast(%{scopes: attrs[:scopes] || app.scopes}, [:scopes])
+ |> validate_required([:scopes, :app_id])
+ |> put_valid_until(attrs)
+ |> put_token()
+ |> put_refresh_token(attrs)
+ |> Repo.insert()