Packages

Gleam library for interacting with Automatic Certificate Management Environment (ACME) servers like Let's Encrypt

Retired package: Release invalid

Current section

Files

Jump to
acumen src acumen@update_account.erl
Raw

src/acumen@update_account.erl

-module(acumen@update_account).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/acumen/update_account.gleam").
-export([agree_to_terms/1, build/3, contacts/2, deactivate/1, request/0, response/1]).
-export_type([request_builder/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Update an existing ACME account.\n"
"\n"
" After registration, you can update your account by posting to the account\n"
" URL. Per RFC 8555, you can update:\n"
" - `contact`: Contact URLs for the account\n"
" - `termsOfServiceAgreed`: Agreement to terms of service\n"
" - `status`: Set to \"deactivated\" to deactivate the account (Section 7.3.6)\n"
"\n"
" The server ignores updates to `orders` and unrecognized fields.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import acumen\n"
" import acumen/update_account\n"
"\n"
" // Update contact information\n"
" let update = update_account.request()\n"
" |> update_account.contacts([\"mailto:new-admin@example.com\"])\n"
"\n"
" // Or deactivate the account\n"
" let deactivate = update_account.request()\n"
" |> update_account.deactivate\n"
"\n"
" let assert Ok(#(resp, ctx)) = acumen.execute(\n"
" ctx,\n"
" build: update_account.build(update, _, registered_key),\n"
" send: httpc.send,\n"
" )\n"
"\n"
" let assert Ok(account) = update_account.response(resp)\n"
" ```\n"
).
-opaque request_builder() :: {request_builder,
gleam@option:option(list(binary())),
gleam@option:option(boolean()),
boolean()}.
-file("src/acumen/update_account.gleam", 59).
?DOC(
" Indicates agreement to the ACME server's terms of service.\n"
"\n"
" The ToS URL is available in `directory.meta.terms_of_service`.\n"
).
-spec agree_to_terms(request_builder()) -> request_builder().
agree_to_terms(Builder) ->
{request_builder,
erlang:element(2, Builder),
{some, true},
erlang:element(4, Builder)}.
-file("src/acumen/update_account.gleam", 85).
-spec build_payload(request_builder()) -> gleam@json:json().
build_payload(Builder) ->
Fields = [],
Fields@1 = case erlang:element(2, Builder) of
{some, Contacts} ->
[{<<"contact"/utf8>>,
gleam@json:array(Contacts, fun gleam@json:string/1)} |
Fields];
none ->
Fields
end,
Fields@2 = case erlang:element(3, Builder) of
{some, Agreed} ->
[{<<"termsOfServiceAgreed"/utf8>>, gleam@json:bool(Agreed)} |
Fields@1];
none ->
Fields@1
end,
Fields@3 = case erlang:element(4, Builder) of
true ->
[{<<"status"/utf8>>, gleam@json:string(<<"deactivated"/utf8>>)} |
Fields@2];
false ->
Fields@2
end,
gleam@json:object(Fields@3).
-file("src/acumen/update_account.gleam", 67).
?DOC(
" Builds the signed HTTP request for account update.\n"
"\n"
" Only includes fields that were explicitly set on the builder;\n"
" omitted fields are left unchanged on the server.\n"
).
-spec build(request_builder(), acumen:context(), acumen:registered_key()) -> {ok,
gleam@http@request:request(binary())} |
{error, acumen:acme_error()}.
build(Builder, Context, Key) ->
_pipe = build_payload(Builder),
_pipe@1 = gleam@json:to_string(_pipe),
_pipe@2 = acumen@internal@jws:sign_with_kid(
erlang:element(2, Key),
erlang:element(3, Key),
_pipe@1,
erlang:element(3, Context),
erlang:element(3, Key)
),
_pipe@3 = gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {jws_error, Field@0} end
),
gleam@result:'try'(
_pipe@3,
fun(_capture) ->
acumen:build_post_request(erlang:element(3, Key), _capture)
end
).
-file("src/acumen/update_account.gleam", 116).
?DOC(
" Sets the new contact URLs for the account.\n"
"\n"
" Contact URLs are typically `mailto:` addresses where the CA can reach you\n"
" about certificate expiration, policy changes, or security issues.\n"
).
-spec contacts(request_builder(), list(binary())) -> request_builder().
contacts(Builder, Contacts) ->
{request_builder,
{some, Contacts},
erlang:element(3, Builder),
erlang:element(4, Builder)}.
-file("src/acumen/update_account.gleam", 127).
?DOC(
" Marks the account for deactivation.\n"
"\n"
" Once deactivated, the account cannot be used for any further operations.\n"
" This action is permanent.\n"
).
-spec deactivate(request_builder()) -> request_builder().
deactivate(Builder) ->
{request_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
true}.
-file("src/acumen/update_account.gleam", 139).
?DOC(
" Creates a new account update request builder with no changes set.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let update = update_account.request()\n"
" |> update_account.contacts([\"mailto:new@example.com\"])\n"
" ```\n"
).
-spec request() -> request_builder().
request() ->
{request_builder, none, none, false}.
-file("src/acumen/update_account.gleam", 151).
?DOC(
" Parses the account update response.\n"
"\n"
" Returns the full account state after the update, including any\n"
" fields that were not modified.\n"
).
-spec response(gleam@http@response:response(binary())) -> {ok,
acumen@account:account()} |
{error, acumen:acme_error()}.
response(Resp) ->
case erlang:element(2, Resp) of
200 ->
_pipe = gleam@json:parse(
erlang:element(4, Resp),
acumen@account:decoder()
),
gleam@result:map_error(
_pipe,
fun(Error) ->
{json_parse_error,
acumen@internal@utils:json_parse_error_message(
<<"account"/utf8>>,
Error
)}
end
);
_ ->
{error,
{invalid_response,
acumen@internal@utils:unexpected_status_message(
erlang:element(2, Resp)
)}}
end.