Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions lib/aura/model/hex_user.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule Aura.Model.HexUser do
@moduledoc false

import Aura.Model.Common

defstruct [
:username,
:email,
:inserted_at,
:updated_at,
:url
]

def build(m) when is_map(m) do
m
|> prepare()
|> then(&struct(Aura.Model.HexUser, &1))
end
end
24 changes: 14 additions & 10 deletions lib/aura/packages.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ defmodule Aura.Packages do
stream_paginate("/packages", opts)
end

def list_package_owners(name) do
with {:ok, %{body: body}} <- Requester.get("/packages/#{name}/owners") do
def list_package_owners(name, opts \\ []) do
with {:ok, %{body: body}} <- Requester.get("/packages/#{name}/owners", opts) do
{:ok, Enum.map(body, &HexPackageOwner.build/1)}
end
end

def get_package(name) do
with {:ok, %{body: body}} <- Requester.get("/packages/#{name}") do
def get_package(name, opts \\ []) do
with {:ok, %{body: body}} <- Requester.get("/packages/#{name}", opts) do
{:ok, HexPackage.build(body)}
end
end
Expand All @@ -25,21 +25,23 @@ defmodule Aura.Packages do
qparams =
Keyword.merge([page: 1], opts)

opts = Keyword.delete(opts, :page)

start_fun = fn -> max(1, qparams[:page]) end
end_fun = fn _ -> :ok end

continue_fun = &paginate_with_page(&1, path, qparams)
continue_fun = &paginate_with_page(&1, path, qparams, opts)

Stream.resource(start_fun, continue_fun, end_fun)
end

defp paginate_with_page(page, _path, _qparams) when page < 1 do
defp paginate_with_page(page, _path, _qparams, _opts) when page < 1 do
{:halt, page}
end

defp paginate_with_page(page, path, qparams) when page >= 1 do
defp paginate_with_page(page, path, qparams, opts) when page >= 1 do
path
|> get_package_page(page, qparams)
|> get_package_page(page, qparams, opts)
|> case do
{:ok, package_page} ->
packages = Enum.map(package_page, &HexPackage.build/1)
Expand All @@ -51,10 +53,12 @@ defmodule Aura.Packages do
end
end

defp get_package_page(path, page, qparams) do
defp get_package_page(path, page, qparams, opts) do
qparams = Keyword.put(qparams, :page, page)

with {:ok, %{body: body}} <- Aura.Requester.get(path, qparams: qparams) do
opts = Keyword.put(opts, :qparams, qparams)

with {:ok, %{body: body}} <- Aura.Requester.get(path, opts) do
{:ok, body}
end
end
Expand Down
52 changes: 52 additions & 0 deletions lib/aura/users.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
defmodule Aura.Users do
@moduledoc false

alias Aura.Model.HexUser
alias Aura.Requester

require Logger

def create_user(username, password, email, opts \\ [])
when is_bitstring(username) and is_bitstring(password) and is_bitstring(email) do
if !opts[:repo_url] do
Logger.warning(
"By using create_user, you are agreeing to Hex's terms of service. See: https://hex.pm/policies/termsofservice"
)
end

opts = Keyword.merge([json: %{username: username, password: password, email: email}], opts)

# See: https://github.com/hexpm/specifications/issues/41
"/users"
|> Requester.post(opts)
|> case do
{:ok, %{body: body}} ->
try do
{:ok, HexUser.build(body)}
rescue
_ -> {:ok, :got_good_status}
end

err ->
err
end
end

def get_user(username_or_email, opts \\ []) when is_bitstring(username_or_email) do
with {:ok, %{body: body}} <- Requester.get("/users/#{username_or_email}", opts) do
{:ok, HexUser.build(body)}
end
end

def get_current_user(opts \\ []) do
with {:ok, %{body: body}} <- Requester.get("/users/me", opts) do
{:ok, HexUser.build(body)}
end
end

def reset_user_password(username_or_email, opts \\ []) do
with {:ok, _} <- Requester.post("/users/#{username_or_email}/reset", opts) do
:ok
end
end
end
2 changes: 1 addition & 1 deletion lib/aura/util/requester.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ defmodule Aura.Requester do
respect_limits(headers)
resp

{:ok, %Req.Response{status: 204, body: _body, headers: headers}} = resp ->
{:ok, %Req.Response{status: status, body: _body, headers: headers}} = resp when status >= 200 and status < 300 ->
respect_limits(headers)
resp

Expand Down
16 changes: 16 additions & 0 deletions test/aura/model/hex_user_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule Aura.Model.HexUserTest do
use ExUnit.Case

import Aura.Factory

alias Aura.Model.HexUser

@moduletag :capture_log

doctest HexUser

test "build_many" do
list = build_list(100, :hex_user)
assert Enum.count(list) == 100
end
end
66 changes: 66 additions & 0 deletions test/aura/users_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
defmodule Aura.UsersTest do
use ExUnit.Case

alias Aura.Model.HexUser
alias Aura.Packages
alias Aura.Users

doctest Users
@moduletag :capture_log

test "get user" do
# use hex
packages = Enum.take(Packages.list_packages(), 5)
refute Enum.empty?(packages)

Enum.each(packages, fn package ->
{:ok, owners} = Packages.list_package_owners(package.name)
refute Enum.empty?(owners)

Enum.each(owners, fn owner ->
assert {:ok, user} = Users.get_user(owner.username)
assert user.username
assert user.inserted_at
assert user.updated_at
assert user.url
end)
end)
end

test "create user" do
# use another repo
mock_repo = TestHelper.get_mock_repo()
Application.put_env(:aura, :repo_url, mock_repo)
username = Faker.Internet.user_name()
email = Faker.Internet.email()
password = Faker.Internet.slug()

# See: https://github.com/hexpm/specifications/issues/41
assert {:ok, _} = Users.create_user(username, email, password, raw: true)
Application.delete_env(:aura, :repo_url)
end

test "get current user" do
mock_repo = TestHelper.get_mock_repo()
api_key = TestHelper.get_mock_api_key()
Application.put_env(:aura, :api_key, api_key)
Application.put_env(:aura, :repo_url, mock_repo)

{:ok, %HexUser{}} = Users.get_current_user()

Application.delete_env(:aura, :repo_url)
Application.delete_env(:aura, :api_key)
end

test "reset user password" do
mock_repo = TestHelper.get_mock_repo()
api_key = TestHelper.get_mock_api_key()
Application.put_env(:aura, :api_key, api_key)
Application.put_env(:aura, :repo_url, mock_repo)

assert :ok = Users.reset_user_password("ericmj")

Application.delete_env(:aura, :repo_url)
Application.delete_env(:aura, :api_key)
end
end
21 changes: 21 additions & 0 deletions test/support/factories/hex_user_factory.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule Aura.Factory.HexUserFactory do
@moduledoc false

defmacro __using__(_opts) do
quote do
def hex_user_factory(attrs) do
inserted_at = Faker.DateTime.backward(40)

%Aura.Model.HexUser{
username: Faker.Internet.user_name(),
email: Faker.Internet.email(),
url: Faker.Internet.url(),
inserted_at: inserted_at,
updated_at: Faker.DateTime.between(inserted_at, DateTime.now!("Etc/UTC"))
}
|> merge_attributes(attrs)
|> evaluate_lazy_attributes()
end
end
end
end
1 change: 1 addition & 0 deletions test/support/factory.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ defmodule Aura.Factory do
use Aura.Factory.HexPackageOwnerFactory
use Aura.Factory.HexReleaseFactory
use Aura.Factory.HexAPIKeyFactory
use Aura.Factory.HexUserFactory
end
Loading