Skip to content

Commit 7ca729e

Browse files
yashin5Yashin Santos
authored and
Yashin Santos
committed
Merge branch 'master' into feat/add_show_admin_endpoint
2 parents adaa2ea + 368427e commit 7ca729e

File tree

18 files changed

+136
-75
lines changed

18 files changed

+136
-75
lines changed

.github/workflows/main.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ jobs:
109109
uses: actions/cache@v2
110110
id: plt-cache
111111
with:
112-
path: _build/plts
112+
path: dializer/
113113
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-plts-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
114114

115115
- name: Generate PLT
116116
if: steps.plt-cache.outputs.cache-hit != 'true'
117117
run: |
118-
mkdir -p _build/plts
118+
mkdir -p dialyzer/
119119
mix dialyzer --plt
120120
121121
- name: Run dialyzer

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# The directory Mix downloads your dependencies sources to.
88
/deps/
99

10+
# The directory where the files will be saved on every build.
11+
/dialyzer/
12+
1013
# Where third-party dependencies like ExDoc output generated docs.
1114
/doc/
1215

README.md

+2-12
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,14 @@
22

33
**This is a work in progress and every contribution is welcome :)**
44

5-
**TODO: Add description**
6-
75
## Requirements
86

9-
- Elixir `1.11` using `OTP-23`;
7+
- Elixir `1.11`;
108
- Erlang `23.1`;
119
- Docker-compose (Just when running in dev enviroment);
1210

1311
## Running it locally
1412

15-
First you should install all requirement, we recommend you to use [asdf](https://github.com/asdf-vm/asdf).
16-
17-
If you are using `asdf` just run:
18-
19-
- `asdf plugin-add elixir`;
20-
- `asdf plugin-add erlang`;
21-
- `asdf install`;
22-
2313
In order to prepare the application run:
2414

2515
- `docker-compose up` to get your containers running;
@@ -47,7 +37,7 @@ ResourceManager.Repo.all(ResourceManager.Identities.Schemas.ClientApplication) |
4737

4838
Check out the [rest api guide](https://github.com/lcpojr/watcher_ex/blob/master/apps/rest_api/README.md) on the specific application `README.md`.
4939

50-
## Testing
40+
### Testing
5141

5242
Before you can run the tests you should setup the test dabatase by using `mix test_setup`. After that just call `mix test` or `mix coveralls` if you want to check code coverage.
5343

apps/authenticator/test/authenticator/sign_in/commands/client_credentials_test.exs

+4-4
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ defmodule Authenticator.SignIn.Commands.ClientCredentialsTest do
106106
test "succeeds using client_assertions and generates an access_token" do
107107
scopes = RF.insert_list!(:scope, 3)
108108
app = RF.insert!(:client_application, grant_flows: ["client_credentials"])
109-
public_key = RF.insert!(:public_key, client_application: app, value: get_priv_public_key())
109+
public_key = RF.insert!(:public_key, client_application: app, value: get_public_key())
110110

111-
signer = Joken.Signer.create("RS256", %{"pem" => get_priv_private_key()})
111+
signer = Joken.Signer.create("RS256", %{"pem" => get_private_key()})
112112

113113
client_assertion =
114114
ClientAssertion.generate_and_sign!(
@@ -144,9 +144,9 @@ defmodule Authenticator.SignIn.Commands.ClientCredentialsTest do
144144
test "succeeds using client_assertions and generates a refresh_token" do
145145
scopes = RF.insert_list!(:scope, 3)
146146
app = RF.insert!(:client_application, grant_flows: ["client_credentials", "refresh_token"])
147-
public_key = RF.insert!(:public_key, client_application: app, value: get_priv_public_key())
147+
public_key = RF.insert!(:public_key, client_application: app, value: get_public_key())
148148

149-
signer = Joken.Signer.create("RS256", %{"pem" => get_priv_private_key()})
149+
signer = Joken.Signer.create("RS256", %{"pem" => get_private_key()})
150150

151151
client_assertion =
152152
ClientAssertion.generate_and_sign!(

apps/authenticator/test/authenticator/sign_in/commands/resource_owner_test.exs

+4-4
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ defmodule Authenticator.SignIn.Commands.ResourceOwnerTest do
129129
scopes = RF.insert_list!(:scope, 3)
130130
user = RF.insert!(:user)
131131
app = RF.insert!(:client_application)
132-
public_key = RF.insert!(:public_key, client_application: app, value: get_priv_public_key())
132+
public_key = RF.insert!(:public_key, client_application: app, value: get_public_key())
133133
hash = RF.gen_hashed_password("MyPassw@rd234")
134134
password = RF.insert!(:password, user: user, password_hash: hash)
135135

136-
signer = Joken.Signer.create("RS256", %{"pem" => get_priv_private_key()})
136+
signer = Joken.Signer.create("RS256", %{"pem" => get_private_key()})
137137

138138
client_assertion =
139139
ClientAssertion.generate_and_sign!(
@@ -177,11 +177,11 @@ defmodule Authenticator.SignIn.Commands.ResourceOwnerTest do
177177
scopes = RF.insert_list!(:scope, 3)
178178
user = RF.insert!(:user)
179179
app = RF.insert!(:client_application, grant_flows: ["resource_owner", "refresh_token"])
180-
public_key = RF.insert!(:public_key, client_application: app, value: get_priv_public_key())
180+
public_key = RF.insert!(:public_key, client_application: app, value: get_public_key())
181181
hash = RF.gen_hashed_password("MyPassw@rd234")
182182
password = RF.insert!(:password, user: user, password_hash: hash)
183183

184-
signer = Joken.Signer.create("RS256", %{"pem" => get_priv_private_key()})
184+
signer = Joken.Signer.create("RS256", %{"pem" => get_private_key()})
185185

186186
client_assertion =
187187
ClientAssertion.generate_and_sign!(

apps/authenticator/test/support/factory.ex

+30-19
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ defmodule Authenticator.Factory do
66
alias Authenticator.Sessions.Tokens.{AccessToken, RefreshToken}
77
alias Authenticator.SignIn.Schemas.{ApplicationAttempt, UserAttempt}
88

9-
@doc false
9+
@doc "Builds a default struct from the requested model"
10+
@spec build(model :: atom()) :: struct()
1011
def build(:session) do
1112
jti = Ecto.UUID.generate()
1213

@@ -51,50 +52,60 @@ defmodule Authenticator.Factory do
5152
}
5253
end
5354

54-
@doc false
55+
@doc "Returns the a model struct with the given attributes"
56+
@spec build(factory_name :: atom(), attributes :: Keyword.t()) :: struct()
5557
def build(factory_name, attributes) when is_atom(factory_name) and is_list(attributes) do
5658
factory_name
5759
|> build()
5860
|> struct!(attributes)
5961
end
6062

61-
@doc false
63+
@doc "Inserts a model with the given attributes on database"
64+
@spec insert!(factory_name :: atom(), attributes :: Keyword.t()) :: struct()
6265
def insert!(factory_name, attributes \\ []) when is_atom(factory_name) do
6366
factory_name
6467
|> build(attributes)
6568
|> Repo.insert!()
6669
end
6770

68-
@doc false
71+
@doc "Inserts a list of the given model on database"
72+
@spec insert_list!(
73+
factory_name :: atom(),
74+
count :: integer(),
75+
attributes :: Keyword.t()
76+
) :: list(struct())
6977
def insert_list!(factory_name, count \\ 10, attributes \\ []) when is_atom(factory_name),
7078
do: Enum.map(0..count, fn _ -> insert!(factory_name, attributes) end)
7179

72-
@doc false
73-
def build_access_token(claims), do: AccessToken.generate_and_sign(claims)
80+
@doc "Returns an mocked access token using the given claims"
81+
@spec build_access_token(claims :: map()) :: {:ok, token :: String.t(), claims :: map()}
82+
def build_access_token(claims) when is_map(claims), do: AccessToken.generate_and_sign(claims)
7483

75-
@doc false
76-
def build_refresh_token(claims), do: RefreshToken.generate_and_sign(claims)
84+
@doc "Returns an mocked refresh token using the given claims"
85+
@spec build_refresh_token(claims :: map()) :: {:ok, token :: String.t(), claims :: map()}
86+
def build_refresh_token(claims) when is_map(claims), do: RefreshToken.generate_and_sign(claims)
7787

78-
@doc false
88+
@doc "Returns an default token expiration"
89+
@spec default_expiration() :: NaiveDateTime.t()
7990
def default_expiration do
8091
NaiveDateTime.utc_now()
8192
|> NaiveDateTime.truncate(:second)
8293
|> NaiveDateTime.add(60 * 60 * 24, :second)
8394
end
8495

85-
@doc false
86-
def get_priv_public_key do
87-
:authenticator
88-
|> :code.priv_dir()
89-
|> Path.join("/keys/authenticator_key.pub")
96+
@doc "Returns the mocked public key"
97+
@spec get_public_key() :: String.t()
98+
def get_public_key do
99+
File.cwd!()
100+
|> Path.join("/test/support/mocks/keys/public_key.pub")
90101
|> File.read!()
91102
end
92103

93-
@doc false
94-
def get_priv_private_key do
95-
:authenticator
96-
|> :code.priv_dir()
97-
|> Path.join("/keys/authenticator_key.pem")
104+
@doc "Returns the mocked private key"
105+
@spec get_private_key() :: String.t()
106+
def get_private_key do
107+
File.cwd!()
108+
|> Path.join("/test/support/mocks/keys/private_key.pem")
98109
|> File.read!()
99110
end
100111
end

apps/resource_manager/test/resource_manager/credentials/public_key_test.exs

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ defmodule ResourceManager.Credentials.PublicKeysTest do
1717

1818
params = %{
1919
client_application_id: client_application.id,
20-
value: get_priv_public_key()
20+
value: get_public_key()
2121
}
2222

2323
assert {:ok, %PublicKey{id: id} = public_key} = PublicKeys.create(params)
@@ -32,7 +32,7 @@ defmodule ResourceManager.Credentials.PublicKeysTest do
3232

3333
describe "#{PublicKeys}.update/2" do
3434
test "succeed if params are valid", ctx do
35-
value = get_priv_public_key()
35+
value = get_public_key()
3636

3737
assert {:ok, %PublicKey{id: id, value: ^value} = public_key} =
3838
PublicKeys.update(ctx.public_key, %{value: value})
@@ -47,7 +47,7 @@ defmodule ResourceManager.Credentials.PublicKeysTest do
4747

4848
test "raises if public_key does not exist" do
4949
assert_raise Ecto.NoPrimaryKeyValueError, fn ->
50-
PublicKeys.update(%PublicKey{}, %{value: get_priv_public_key()})
50+
PublicKeys.update(%PublicKey{}, %{value: get_public_key()})
5151
end
5252
end
5353
end

apps/resource_manager/test/resource_manager/identity/commands/create_identity_test.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule ResourceManager.Identities.Commands.CreateIdentityTest do
2626
input = %{
2727
name: "my-client-application",
2828
description: "App for tests",
29-
public_key: get_priv_public_key(),
29+
public_key: get_public_key(),
3030
scopes: ctx.scopes
3131
}
3232

apps/resource_manager/test/support/factory.ex

+38-20
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ defmodule ResourceManager.Factory do
88

99
@default_password "My-passw@rd123"
1010

11-
@doc false
11+
@doc "Builds a default struct from the requested model"
12+
@spec build(model :: atom()) :: struct()
1213
def build(:user) do
1314
%User{
1415
username: "my-test-username#{System.unique_integer()}",
@@ -37,7 +38,7 @@ defmodule ResourceManager.Factory do
3738

3839
def build(:public_key) do
3940
%PublicKey{
40-
value: get_priv_public_key()
41+
value: get_public_key()
4142
}
4243
end
4344

@@ -62,43 +63,60 @@ defmodule ResourceManager.Factory do
6263
}
6364
end
6465

65-
@doc false
66+
@doc "Returns the a model struct with the given attributes"
67+
@spec build(factory_name :: atom(), attributes :: Keyword.t()) :: struct()
6668
def build(factory_name, attributes) when is_atom(factory_name) and is_list(attributes) do
6769
factory_name
6870
|> build()
6971
|> struct!(attributes)
7072
end
7173

72-
@doc false
74+
@doc "Inserts a model with the given attributes on database"
75+
@spec insert!(factory_name :: atom(), attributes :: Keyword.t()) :: struct()
7376
def insert!(factory_name, attributes \\ []) when is_atom(factory_name) do
7477
factory_name
7578
|> build(attributes)
7679
|> Repo.insert!()
7780
end
7881

79-
@doc false
82+
@doc "Inserts a list of the given model on database"
83+
@spec insert_list!(
84+
factory_name :: atom(),
85+
count :: integer(),
86+
attributes :: Keyword.t()
87+
) :: list(struct())
8088
def insert_list!(factory_name, count \\ 10, attributes \\ []) when is_atom(factory_name),
8189
do: Enum.map(0..count, fn _ -> insert!(factory_name, attributes) end)
8290

83-
@doc false
91+
@doc "Returns the given password hashed using the selected algorithm"
92+
@spec gen_hashed_password(
93+
password :: String.t(),
94+
algorithm :: :argon2 | :bcrypt | :pbkdf2
95+
) :: String.t()
8496
def gen_hashed_password(password \\ @default_password, alg \\ :argon2)
85-
def gen_hashed_password(password, :argon2), do: Argon2.hash_pwd_salt(password)
86-
def gen_hashed_password(password, :bcrypt), do: Bcrypt.hash_pwd_salt(password)
87-
def gen_hashed_password(password, :pbkdf2), do: Pbkdf2.hash_pwd_salt(password)
88-
89-
@doc false
90-
def get_priv_public_key do
91-
:resource_manager
92-
|> :code.priv_dir()
93-
|> Path.join("/keys/resource_manager_key.pub")
97+
98+
def gen_hashed_password(password, :argon2) when is_binary(password),
99+
do: Argon2.hash_pwd_salt(password)
100+
101+
def gen_hashed_password(password, :bcrypt) when is_binary(password),
102+
do: Bcrypt.hash_pwd_salt(password)
103+
104+
def gen_hashed_password(password, :pbkdf2) when is_binary(password),
105+
do: Pbkdf2.hash_pwd_salt(password)
106+
107+
@doc "Returns the mocked public key"
108+
@spec get_public_key() :: String.t()
109+
def get_public_key do
110+
File.cwd!()
111+
|> Path.join("/test/support/mocks/keys/public_key.pub")
94112
|> File.read!()
95113
end
96114

97-
@doc false
98-
def get_priv_private_key do
99-
:resource_manager
100-
|> :code.priv_dir()
101-
|> Path.join("/keys/resource_manager_key.pem")
115+
@doc "Returns the mocked private key"
116+
@spec get_private_key() :: String.t()
117+
def get_private_key do
118+
File.cwd!()
119+
|> Path.join("/test/support/mocks/keys/private_key.pem")
102120
|> File.read!()
103121
end
104122
end

apps/rest_api/lib/controllers/admin/user.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ defmodule RestAPI.Controller.Admin.User do
2727
end
2828
end
2929

30-
def show(conn, %{"id" => username} = params) do
30+
def show(conn, %{"id" => _} = params) do
3131
params
32-
|> Map.put(:username, username)
32+
|> Map.put(:username, nil)
3333
|> ResourceManager.get_identity()
3434
|> case do
3535
{:ok, identity} when is_map(identity) ->

apps/rest_api/test/controllers/admin/user_test.exs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
defmodule RestAPI.Controllers.Admin.User do
2-
use RestAPI.ConnCase, async: true
2+
use RestAPI.ConnCase, async: false
33

44
alias ResourceManager.Identities.Commands.Inputs.CreateUser
55
alias RestAPI.Ports.{AuthenticatorMock, AuthorizerMock, ResourceManagerMock}
@@ -216,7 +216,7 @@ defmodule RestAPI.Controllers.Admin.User do
216216
} =
217217
conn
218218
|> put_req_header("authorization", "Bearer #{access_token}")
219-
|> get(@show_endpoint <> "username")
219+
|> get(@show_endpoint <> username)
220220
|> json_response(201)
221221
end
222222
end

apps/rest_api/test/support/conn_case.ex

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ defmodule RestAPI.ConnCase do
1717

1818
use ExUnit.CaseTemplate
1919

20+
alias Ecto.Adapters.SQL.Sandbox
21+
2022
using do
2123
quote do
2224
# Import conveniences for testing with connections
2325
import Plug.Conn
2426
import Phoenix.ConnTest
2527
import RestAPI.ConnCase
2628
import Mox
27-
import ResourceManager.Factory
29+
import RestAPI.{ConnCase, Factory}
2830

2931
alias RestAPI.Router.Helpers, as: Routes
3032

@@ -33,7 +35,13 @@ defmodule RestAPI.ConnCase do
3335
end
3436
end
3537

36-
setup _tags do
38+
setup tags do
39+
:ok = Sandbox.checkout(ResourceManager.Repo)
40+
41+
unless tags[:async] do
42+
Sandbox.mode(ResourceManager.Repo, {:shared, self()})
43+
end
44+
3745
{:ok, conn: Phoenix.ConnTest.build_conn()}
3846
end
3947
end

0 commit comments

Comments
 (0)