diff --git a/config/dev.exs b/config/dev.exs
index 258a646..4a5d86d 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -5,7 +5,7 @@ config :kmxgit, Kmxgit.Repo,
database: "kmxgit_dev",
hostname: "localhost",
show_sensitive_data_on_connection_error: true,
- pool_size: 10
+ pool_size: 2
# For development, we disable any cache and enable
# debugging and code reloading.
diff --git a/lib/kmxgit/organisation_manager.ex b/lib/kmxgit/organisation_manager.ex
index db11619..7d9d06a 100644
--- a/lib/kmxgit/organisation_manager.ex
+++ b/lib/kmxgit/organisation_manager.ex
@@ -4,19 +4,21 @@ defmodule Kmxgit.OrganisationManager do
alias Kmxgit.OrganisationManager.Organisation
alias Kmxgit.Repo
+ alias Kmxgit.UserManager.User
def list_organisations do
Organisation
|> Repo.all
end
- def change_organisation(organisation) do
+ def change_organisation(organisation \\ %Organisation{}) do
Organisation.changeset(organisation, %{})
end
- def create_organisation(attrs \\ %{}) do
+ def create_organisation(user = %User{id: _}, attrs \\ %{}) do
%Organisation{}
|> Organisation.changeset(attrs)
+ |> Ecto.Changeset.put_assoc(:users, [user])
|> Repo.insert()
end
diff --git a/lib/kmxgit/organisation_manager/organisation.ex b/lib/kmxgit/organisation_manager/organisation.ex
index 7a634e6..b13828a 100644
--- a/lib/kmxgit/organisation_manager/organisation.ex
+++ b/lib/kmxgit/organisation_manager/organisation.ex
@@ -3,10 +3,13 @@ defmodule Kmxgit.OrganisationManager.Organisation do
use Ecto.Schema
import Ecto.Changeset
+ alias Kmxgit.UserManager.User
+
schema "organisations" do
field :description, :string
field :name, :string
field :slug, :string, null: false
+ many_to_many :users, User, join_through: "users_organisations"
timestamps()
end
@@ -15,7 +18,7 @@ defmodule Kmxgit.OrganisationManager.Organisation do
organisation
|> cast(attrs, [:slug, :description, :name])
|> validate_required([:slug])
- |> validate_format(:slug, ~r/^[A-Za-z][-_+0-9A-Za-z]{1,64}$/)
+ |> validate_format(:slug, ~r/^[A-Za-z][-_+.0-9A-Za-z]{1,64}$/)
|> unique_constraint(:_lower_slug)
|> Markdown.validate_markdown(:description)
end
diff --git a/lib/kmxgit/organisation_manager/user_organisation.ex b/lib/kmxgit/organisation_manager/user_organisation.ex
new file mode 100644
index 0000000..3b74802
--- /dev/null
+++ b/lib/kmxgit/organisation_manager/user_organisation.ex
@@ -0,0 +1,17 @@
+defmodule Kmxgit.OrganisationManager.UserOrganisation do
+
+ use Ecto.Schema
+
+ alias Kmxgit.OrganisationManager.Organisation
+ alias Kmxgit.UserManager.User
+
+ schema "users_organisations" do
+ belongs_to :user, User
+ belongs_to :organisation, Organisation
+ belongs_to :invited_by, User, source: :invited_by
+ field :invited_at, :utc_datetime
+ field :invited_ip, :string
+ timestamps()
+ end
+
+end
diff --git a/lib/kmxgit/user_manager.ex b/lib/kmxgit/user_manager.ex
index 1348b30..9880c1c 100644
--- a/lib/kmxgit/user_manager.ex
+++ b/lib/kmxgit/user_manager.ex
@@ -37,14 +37,22 @@ defmodule Kmxgit.UserManager do
** (Ecto.NoResultsError)
"""
- def get_user!(id), do: Repo.get!(User, id)
+ def get_user!(id) do
+ Repo.one(from user in User,
+ where: [id: ^id],
+ preload: :organisations) || raise "user #{id} not found"
+ end
- def get_user(id), do: Repo.get(User, id)
+ def get_user(id) do
+ Repo.one from user in User,
+ where: [id: ^id],
+ preload: :organisations
+ end
def get_user_by_login(login) do
Repo.one from user in User,
where: [login: ^login],
- preload: [organisations: [:organisation]]
+ preload: :organisations
end
@doc """
diff --git a/lib/kmxgit/user_manager/user.ex b/lib/kmxgit/user_manager/user.ex
index 2f618d1..75148b3 100644
--- a/lib/kmxgit/user_manager/user.ex
+++ b/lib/kmxgit/user_manager/user.ex
@@ -13,8 +13,8 @@ defmodule Kmxgit.UserManager.User do
field :is_admin, :boolean, null: false
field :login, :string, unique: true
field :name, :string
- field :password, :string, virtual: true
- field :password_confirmation, :string, virtual: true
+ field :password, :string, virtual: true, redact: true
+ field :password_confirmation, :string, virtual: true, redact: true
field :ssh_keys, :string
many_to_many :organisations, Organisation, join_through: "users_organisations"
timestamps()
@@ -63,16 +63,16 @@ defmodule Kmxgit.UserManager.User do
passwords_do_not_match(changeset)
end
+ defp check_password_confirmation(changeset) do
+ changeset
+ end
+
defp passwords_do_not_match(changeset) do
Ecto.Changeset.add_error(changeset,
:password_confirmation,
"Passwords do not match.")
end
- defp check_password_confirmation(changeset) do
- changeset
- end
-
defp put_password_hash(%Ecto.Changeset{valid?: true,
changes: %{password: password,
password_confirmation: password}}
diff --git a/lib/kmxgit/user_manager/user_organisation.ex b/lib/kmxgit/user_manager/user_organisation.ex
deleted file mode 100644
index c621200..0000000
--- a/lib/kmxgit/user_manager/user_organisation.ex
+++ /dev/null
@@ -1,19 +0,0 @@
-defmodule Kmxgit.UserManager.UserOrganisation do
- use Ecto.Schema
- import Ecto.Changeset
-
- alias Kmxgit.OrganisationManager.Organisation
- alias Kmxgit.UserManager.User
-
- schema "users_organisations" do
- belongs_to :organisation, Organisation
- belongs_to :user, User
- timestamps()
- end
-
- @doc false
- defp changeset(user_organisation, attrs) do
- user_organisation
- |> cast(attrs, [:organisation_id, :user_id])
- end
-end
diff --git a/lib/kmxgit_web/controllers/admin/organisation_controller.ex b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
index 4103509..e40fd1f 100644
--- a/lib/kmxgit_web/controllers/admin/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
@@ -2,7 +2,6 @@ defmodule KmxgitWeb.Admin.OrganisationController do
use KmxgitWeb, :controller
alias Kmxgit.OrganisationManager
- alias Kmxgit.OrganisationManager.Organisation
alias KmxgitWeb.ErrorView
def index(conn, _params) do
@@ -12,7 +11,7 @@ defmodule KmxgitWeb.Admin.OrganisationController do
end
def new(conn, _params) do
- changeset = OrganisationManager.change_organisation(%Organisation{})
+ changeset = OrganisationManager.change_organisation
conn
|> assign(:action, Routes.admin_organisation_path(conn, :create))
|> assign(:changeset, changeset)
@@ -25,10 +24,11 @@ defmodule KmxgitWeb.Admin.OrganisationController do
conn
|> redirect(to: Routes.organisation_path(conn, :show, organisation.slug))
{:error, changeset} ->
- IO.inspect(changeset)
- conn
- |> render("new.html", changeset: changeset,
- action: Routes.admin_organisation_path(conn, :create))
+ IO.inspect(changeset)
+ conn
+ |> assign(:action, Routes.admin_organisation_path(conn, :create))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
end
end
diff --git a/lib/kmxgit_web/controllers/organisation_controller.ex b/lib/kmxgit_web/controllers/organisation_controller.ex
index 0524b0b..1dc2dea 100644
--- a/lib/kmxgit_web/controllers/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/organisation_controller.ex
@@ -3,16 +3,45 @@ defmodule KmxgitWeb.OrganisationController do
alias Kmxgit.OrganisationManager
- def index(conn, _params) do
- organisations = OrganisationManager.list_organisations
+ def new(conn, _params) do
+ _ = conn.assigns.current_user
+ changeset = OrganisationManager.change_organisation
conn
- |> render("index.html", organisations: organisations)
+ |> assign(:action, Routes.organisation_path(conn, :create))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
end
- def show(conn, params) do
- organisation = OrganisationManager.get_organisation_by_slug(params["slug"])
+ def create(conn, params) do
+ current_user = conn.assigns.current_user
+ case OrganisationManager.create_organisation(current_user, params["organisation"]) do
+ {:ok, organisation} ->
+ conn
+ |> redirect(to: Routes.organisation_path(conn, :show, organisation.slug))
+ {:error, changeset} ->
+ conn
+ |> assign(:action, Routes.organisation_path(conn, :create))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
+ end
+ end
+
+ defp not_found(conn) do
conn
- |> assign(:current_organisation, organisation)
- |> render("show.html", organisation: organisation)
+ |> put_status(:not_found)
+ |> put_view(ErrorView)
+ |> render(:"404")
+ end
+
+ def show(conn, params) do
+ org = OrganisationManager.get_organisation_by_slug(params["slug"])
+ if org do
+ conn
+ |> assign(:current_org, org)
+ |> assign(:org, org)
+ |> render("show.html")
+ else
+ not_found(conn)
+ end
end
end
diff --git a/lib/kmxgit_web/controllers/page_controller.ex b/lib/kmxgit_web/controllers/page_controller.ex
index 73a6bde..bdd467f 100644
--- a/lib/kmxgit_web/controllers/page_controller.ex
+++ b/lib/kmxgit_web/controllers/page_controller.ex
@@ -1,7 +1,6 @@
defmodule KmxgitWeb.PageController do
use KmxgitWeb, :controller
- alias Kmxgit.OrganisationManager
alias Kmxgit.UserManager
alias Kmxgit.UserManager.{Guardian, User}
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index a1526f8..32f92e9 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -51,15 +51,18 @@ defmodule KmxgitWeb.Router do
scope "/", KmxgitWeb do
pipe_through [:browser, :auth, :ensure_auth]
- scope "/org" do
- get "/", OrganisationController, :index
- get "/:slug", OrganisationController, :show
+ scope "/_o" do
+ get "/_new", OrganisationController, :new
+ post "/", OrganisationController, :create
+ get "/:slug", OrganisationController, :show
+ get "/:slug/_edit", OrganisationController, :edit
+ put "/:slug", OrganisationController, :update
end
- scope "/u" do
- get "/:login", UserController, :show
- get "/:login/edit", UserController, :edit
- put "/:login", UserController, :update
+ scope "/_u" do
+ get "/:login", UserController, :show
+ get "/:login/_edit", UserController, :edit
+ put "/:login", UserController, :update
end
scope "/admin", Admin, as: "admin" do
diff --git a/lib/kmxgit_web/templates/layout/nav_connected.html.heex b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
index 8e1f0a2..dd004bc 100644
--- a/lib/kmxgit_web/templates/layout/nav_connected.html.heex
+++ b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
@@ -1,3 +1,8 @@
+<li class="nav-item">
+ <%= link gettext("New organisation"),
+ to: Routes.organisation_path(@conn, :new),
+ class: "nav-link" %>
+</li>
<%= if @conn.assigns[:current_organisation] do %>
<li class="nav-item">
<%= link @current_organisation.name,
diff --git a/lib/kmxgit_web/templates/organisation/form.html.heex b/lib/kmxgit_web/templates/organisation/form.html.heex
new file mode 100644
index 0000000..958588c
--- /dev/null
+++ b/lib/kmxgit_web/templates/organisation/form.html.heex
@@ -0,0 +1,25 @@
+<%= form_for @changeset, @action, fn f -> %>
+
+ <div class="mb-3">
+ <%= label f, :slug, class: "form-label" %>
+ <%= text_input f, :slug, class: "form-control" %>
+ <%= error_tag f, :slug %>
+ </div>
+
+ <div class="mb-3">
+ <%= label f, :name, class: "form-label" %>
+ <%= text_input f, :name, class: "form-control" %>
+ <%= error_tag f, :name %>
+ </div>
+
+ <div class="mb-3">
+ <%= label f, :description, class: "form-label" %>
+ <%= textarea f, :description, class: "form-control" %>
+ <%= error_tag f, :description %>
+ </div>
+
+ <div class="mb-3">
+ <%= submit gettext("Submit"), class: "btn btn-primary" %>
+ </div>
+
+<% end %>
diff --git a/lib/kmxgit_web/templates/organisation/new.html.heex b/lib/kmxgit_web/templates/organisation/new.html.heex
new file mode 100644
index 0000000..8ac1816
--- /dev/null
+++ b/lib/kmxgit_web/templates/organisation/new.html.heex
@@ -0,0 +1,4 @@
+<div class="container-fluid">
+ <h1>New organisation</h1>
+ <%= render "form.html", assigns %>
+</div>
diff --git a/lib/kmxgit_web/templates/organisation/show.html.heex b/lib/kmxgit_web/templates/organisation/show.html.heex
index 75adbea..7c5c123 100644
--- a/lib/kmxgit_web/templates/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/organisation/show.html.heex
@@ -1,9 +1,42 @@
<div class="container-fluid">
- <h1><%= @organisation.name %></h1>
+ <div class="row">
+ <div class="col col-12 col-sm-7">
+ <h1><%= @org.name || @org.slug %></h1>
+ </div>
+ <div class="col col-12 col-sm-4">
+ <%= link gettext("Edit"),
+ to: Routes.organisation_path(@conn, :edit, @org.slug),
+ class: "btn btn-primary" %>
+ </div>
- <%= @organisation.address %>
+ </div>
- <%= if @organisation.description do %>
- <%= raw Earmark.as_html!(@organisation.description) %>
- <% end %>
+ <div class="row">
+ <div class="col col-12 col-md-7">
+ <hr/>
+ <h2><%= gettext "Repositories" %></h2>
+ </div>
+ <div class="col col-12 col-md-4">
+ <hr/>
+ <h2><%= gettext "Properties" %></h2>
+ <table class="table admin-properties">
+ <tr>
+ <th><%= gettext "Slug" %></th>
+ <td><%= @org.slug %></td>
+ </tr>
+ <tr>
+ <th><%= gettext "Name" %></th>
+ <td><%= @org.name %></td>
+ </tr>
+ <tr>
+ <th><%= gettext "Description" %></th>
+ <td>
+ <%= if @org.description do %>
+ <%= raw Earmark.as_html!(@org.description) %>
+ <% end %>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
</div>
diff --git a/lib/kmxgit_web/templates/page/index.html.heex b/lib/kmxgit_web/templates/page/index.html.heex
index f844bd8..2dc0a39 100644
--- a/lib/kmxgit_web/templates/page/index.html.heex
+++ b/lib/kmxgit_web/templates/page/index.html.heex
@@ -1,41 +1,5 @@
-<section class="phx-hero">
- <h1><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h1>
- <p>Peace of mind from prototype to production</p>
-</section>
-
-<section class="row">
- <article class="column">
- <h2>Resources</h2>
- <ul>
- <li>
- <a href="https://hexdocs.pm/phoenix/overview.html">Guides & Docs</a>
- </li>
- <li>
- <a href="https://github.com/phoenixframework/phoenix">Source</a>
- </li>
- <li>
- <a href="https://github.com/phoenixframework/phoenix/blob/v1.6/CHANGELOG.md">v1.6 Changelog</a>
- </li>
- </ul>
- </article>
- <article class="column">
- <h2>Help</h2>
- <ul>
- <li>
- <a href="https://elixirforum.com/c/phoenix-forum">Forum</a>
- </li>
- <li>
- <a href="https://web.libera.chat/#elixir">#elixir on Libera Chat (IRC)</a>
- </li>
- <li>
- <a href="https://twitter.com/elixirphoenix">Twitter @elixirphoenix</a>
- </li>
- <li>
- <a href="https://elixir-slackin.herokuapp.com/">Elixir on Slack</a>
- </li>
- <li>
- <a href="https://discord.gg/elixir">Elixir on Discord</a>
- </li>
- </ul>
- </article>
-</section>
+<div class="container-fluid">
+ <code>
+ "Hello, world !"
+ </code>
+</div>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 5cb4ac8..b46fb16 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -42,7 +42,9 @@
<tr>
<th><%= gettext "Organisations" %></th>
<td>
-
+ <%= for org <- @user.organisations do %>
+ <%= link(org.name || org.slug, to: Routes.organisation_path(@conn, :show, org.slug), class: "org") %>
+ <% end %>
</td>
</tr>
<tr>
diff --git a/lib/kmxgit_web/views/layout_view.ex b/lib/kmxgit_web/views/layout_view.ex
index 9bf5d5d..ab057fe 100644
--- a/lib/kmxgit_web/views/layout_view.ex
+++ b/lib/kmxgit_web/views/layout_view.ex
@@ -1,8 +1,6 @@
defmodule KmxgitWeb.LayoutView do
use KmxgitWeb, :view
- alias Kmxgit.UserManager.User
-
def flash_json(conn) do
{:ok, result} = Jason.encode(get_flash(conn))
%{"data-flash": result}
diff --git a/lib/kmxgit_web/views/user_view.ex b/lib/kmxgit_web/views/user_view.ex
index bc6de7d..2f4632e 100644
--- a/lib/kmxgit_web/views/user_view.ex
+++ b/lib/kmxgit_web/views/user_view.ex
@@ -1,5 +1,3 @@
defmodule KmxgitWeb.UserView do
use KmxgitWeb, :view
-
- alias Kmxgit.UserManager.User
end
diff --git a/priv/repo/migrations/20211118084129_create_users_organisations.exs b/priv/repo/migrations/20211118084129_create_users_organisations.exs
new file mode 100644
index 0000000..e1d75d5
--- /dev/null
+++ b/priv/repo/migrations/20211118084129_create_users_organisations.exs
@@ -0,0 +1,10 @@
+defmodule Kmxgit.Repo.Migrations.CreateUsersOrganisations do
+ use Ecto.Migration
+
+ def change do
+ create table(:users_organisations, foreign_key: false) do
+ add :user_id, references(:users)
+ add :organisation_id, references(:organisations)
+ end
+ end
+end