-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Guide on how to set up organization #11
Comments
I'll write some short instructions here to answer the above post. Create the organization and add a migration to add the organization reference: mix phx.gen.context Organizations Organization organizations name:string
mix ecto.gen.migration add_organization_to_users Update defmodule MyApp.Repo.Migrations.AddOrganizationToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add :organization_id, references("organizations", on_delete: :delete_all), null: false
end
end
end And update the user to restraint them to organizations: defmodule MyApp.Users.User do
# ...
alias MyApp.Organizations.Organization
schema "users" do
belongs_to :organization, Organization
pow_user_fields()
timestamp()
end
def changeset(user_or_changeset, attrs) do
user_or_changeset
|> pow_changeset(attrs)
|> pow_extension_changeset(attrs)
|> Ecto.Changeset.assoc_constraint(:organization)
end
def invite_changeset(user_or_changeset, invited_by, attrs) do
user_or_changeset
|> pow_invite_changeset(invited_by, attrs)
|> changeset_organization(invited_by)
end
defp changeset_organization(changeset, invited_by) do
Ecto.Changeset.change(changeset, organization_id: invited_by.organization_id)
end
# ...
end Update the organizations schema to require an initial user: defmodule MyApp.Organizations.Organization do
use Ecto.Schema
import Ecto.Changeset
alias MyApp.Users.User
schema "organizations" do
field :name, :string
has_many :users, User, on_delete: :delete_all
timestamps()
end
@doc false
def changeset(organization, attrs) do
organization
|> cast(attrs, [:name])
|> validate_required([:name])
end
defp changeset_users(changeset) do
case Ecto.get_meta(changeset.data, :state) do
:built -> cast_assoc(changeset, :users, required: true)
_any -> any
end
end
Set up a controller action to create the organization: defmodule MyAppWeb.RegistrationController do
use MyAppWeb, :controller
alias MyApp.{Organizations.Organization, Repo}
def new(conn, _params) do
changeset = Organization.changeset(%Organization{}, %{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"organization" => user_params}) do
%Organization{}
|> Organization.changeset(user_params)
|> Repo.insert()
|> case do
{:ok, organization} ->
conn
|> auth_user(organization.users)
|> put_flash(:info, "Welcome!")
|> redirect(to: Routes.page_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
defp auth_user(conn, [user]) do
config = Pow.Plug.fetch_config(conn)
Pow.Plug.get_plug(config).do_create(conn, user, config)
end
end The form could look like this: <%= form_for @changeset, Routes.organization_path(@conn, :create), fn f -> %>
<%= text_input f, :name %>
<%= inputs_for f, :users, [append: [%MyApp.Users.User{}]], fn f_user -> %>
<%= label f_user, :email, "email" %>
<%= email_input f_user, :email %>
<%= error_tag f_user, :email %>
<%= label f_user, :password, "password" %>
<%= password_input f_user, :password %>
<%= error_tag f_user, :password %>
<%= label f_user, :confirm_password, "confirm_password" %>
<%= password_input f_user, :confirm_password %>
<%= error_tag f_user, :confirm_password %>
<% end %>
<% end %> |
Thank you for the instructions. Thanks! |
I started implementing the proposed workflow along these steps:
I have an issue with registration view: The code is here any other comments are most welcome! Thank you for your help! |
Hmm, what kind of error do you get? Also, you can do the rest in in much less code by overriding the registration scope "/", MyAppWeb do
pipe_through [:browser]
resources "/registration", OrganizationController, singleton: true, only: [:new, :create]
end
scope "/" do
pipe_through :browser
pow_routes()
end defmodule MyAppWeb.OrganizationController do
use MyAppWeb, :controller
alias MyApp.{Organizations.Organization, Repo}
def new(conn, _params) do
changeset = Organization.changeset(%Organization{}, %{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"organization" => organization_params}) do
%Organization{}
|> Organization.changeset(user_params)
|> Repo.insert()
|> case do
{:ok, organization} ->
conn
|> auth_user(organization.users)
|> put_flash(:info, "Welcome!")
|> redirect(to: Routes.page_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
defp auth_user(conn, [user]) do
config = Pow.Plug.fetch_config(conn)
Pow.Plug.get_plug(config).do_create(conn, user, config)
end
end # organization new.html.eex
<%= form_for @changeset, Routes.organization_path(@conn, :create), fn f -> %>
<%= text_input f, :name %>
<%= inputs_for f, :users, [append: [%MyApp.Users.User{}]], fn f_user -> %>
<%= label f_user, :email, "email" %>
<%= email_input f_user, :email %>
<%= error_tag f_user, :email %>
<%= label f_user, :password, "password" %>
<%= password_input f_user, :password %>
<%= error_tag f_user, :password %>
<%= label f_user, :confirm_password, "confirm_password" %>
<%= password_input f_user, :confirm_password %>
<%= error_tag f_user, :confirm_password %>
<% end %>
<% end %> This way you don't need to override anything else in Pow, just the routes 😄 Also the organization constraint in the user changeset will prevent users from signing up through the regular Pow registration controller if you somehow inadvertently expose it, so it's safe. |
Thank you! The error I have is: It's originating from |
Oh, try use |
It works but only with a list of: [%User{}] instead of %User{} directly. Is it OK to solve this error like this? |
Yeah, it was my mistake. Updated the examples! |
This would be a good newbie guide, based on this post in the elixir forum:
This would be a very easy guide to write. It can go into PowInvitation, roles and/or user management within the organization, and maybe on how to limit organizations to a certain subdomain (so users in a certain organization can only sign in on that subdomain). Any ideas are welcome!
The text was updated successfully, but these errors were encountered: