diff --git a/priv/repo/migrations/20170224233516_add_owner_to_organization.exs b/priv/repo/migrations/20170224233516_add_owner_to_organization.exs new file mode 100644 index 000000000..70f55afcd --- /dev/null +++ b/priv/repo/migrations/20170224233516_add_owner_to_organization.exs @@ -0,0 +1,9 @@ +defmodule CodeCorps.Repo.Migrations.AddOwnerToOrganization do + use Ecto.Migration + + def change do + alter table(:organizations) do + add :owner_id, references(:users, on_delete: :nothing) + end + end +end diff --git a/priv/repo/structure.sql b/priv/repo/structure.sql index 3c8d5c9e6..2c35baafc 100644 --- a/priv/repo/structure.sql +++ b/priv/repo/structure.sql @@ -197,7 +197,8 @@ CREATE TABLE organizations ( updated_at timestamp without time zone NOT NULL, approved boolean DEFAULT false, cloudinary_public_id character varying(255), - default_color character varying(255) + default_color character varying(255), + owner_id integer ); @@ -2179,6 +2180,14 @@ ALTER TABLE ONLY organization_memberships ADD CONSTRAINT organization_memberships_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id); +-- +-- Name: organizations_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY organizations + ADD CONSTRAINT organizations_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id); + + -- -- Name: previews_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -2519,5 +2528,5 @@ ALTER TABLE ONLY user_tasks -- PostgreSQL database dump complete -- -INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201014901), (20170201025454), (20170201035458), (20170201183258), (20170220032224); +INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201014901), (20170201025454), (20170201035458), (20170201183258), (20170220032224), (20170224233516); diff --git a/test/controllers/organization_controller_test.exs b/test/controllers/organization_controller_test.exs index 3981648ae..0237e7a1d 100644 --- a/test/controllers/organization_controller_test.exs +++ b/test/controllers/organization_controller_test.exs @@ -44,8 +44,9 @@ defmodule CodeCorps.OrganizationControllerTest do describe "create" do @tag authenticated: :admin - test "creates and renders resource when data is valid", %{conn: conn} do - assert conn |> request_create(@valid_attrs) |> json_response(201) + test "creates and renders resource when data is valid", %{conn: conn, current_user: user} do + attrs = Map.merge(@valid_attrs, %{owner: user}) + assert conn |> request_create(attrs) |> json_response(201) end @tag authenticated: :admin diff --git a/test/models/organization_test.exs b/test/models/organization_test.exs index 36c1ad3d9..5f5bee22e 100644 --- a/test/models/organization_test.exs +++ b/test/models/organization_test.exs @@ -3,27 +3,43 @@ defmodule CodeCorps.OrganizationTest do alias CodeCorps.Organization - @valid_attrs %{description: "Building a better future.", name: "Code Corps"} - @invalid_attrs %{} - test "changeset with valid attributes" do - changeset = Organization.changeset(%Organization{}, @valid_attrs) - assert changeset.valid? - end + describe "changeset" do + @valid_attrs %{description: "Building a better future.", name: "Code Corps"} + @invalid_attrs %{} + test "with valid attributes" do + changeset = Organization.changeset(%Organization{}, @valid_attrs) + assert changeset.valid? + end - test "changeset with invalid attributes" do - changeset = Organization.changeset(%Organization{}, @invalid_attrs) - refute changeset.valid? + test "with invalid attributes" do + changeset = Organization.changeset(%Organization{}, @invalid_attrs) + refute changeset.valid? + end end - test "create changeset with valid attributes" do - changeset = Organization.create_changeset(%Organization{}, @valid_attrs) - assert changeset.valid? - assert changeset.changes.slug == "code-corps" - end + describe "create_changeset" do + @valid_attrs %{owner_id: 1, description: "Building a better future.", name: "Code Corps"} + @invalid_attrs %{} + + test "with valid attributes" do + changeset = Organization.create_changeset(%Organization{}, @valid_attrs) + assert changeset.valid? + assert changeset.changes.slug == "code-corps" + end + + test "with invalid attributes" do + changeset = Organization.create_changeset(%Organization{}, @invalid_attrs) + refute changeset.valid? + end + + test "ensures owner (user) actuallys exist" do + changeset = Organization.create_changeset(%Organization{}, @valid_attrs) + + {result, changeset} = changeset |> Repo.insert - test "create changeset with invalid attributes" do - changeset = Organization.create_changeset(%Organization{}, @invalid_attrs) - refute changeset.valid? + assert result == :error + changeset |> assert_error_message(:owner, "does not exist") + end end end diff --git a/test/support/factories.ex b/test/support/factories.ex index e8eafe260..cd14f1399 100644 --- a/test/support/factories.ex +++ b/test/support/factories.ex @@ -32,6 +32,7 @@ defmodule CodeCorps.Factories do def organization_factory do %CodeCorps.Organization{ name: sequence(:username, &"Organization #{&1}"), + owner: build(:user), slug: sequence(:slug, &"organization-#{&1}"), description: sequence(:email, &"Description of organization #{&1}"), } diff --git a/test/views/organization_view_test.exs b/test/views/organization_view_test.exs index c23b40005..3537d5cbd 100644 --- a/test/views/organization_view_test.exs +++ b/test/views/organization_view_test.exs @@ -2,9 +2,9 @@ defmodule CodeCorps.OrganizationViewTest do use CodeCorps.ViewCase test "renders all attributes and relationships properly" do - organization = insert(:organization, default_color: "blue") - project = insert(:project, organization: organization) user = insert(:user) + organization = insert(:organization, owner: user, default_color: "blue") + project = insert(:project, organization: organization) organization_membership = insert(:organization_membership, member: user, organization: organization) slugged_route = insert(:slugged_route, organization: organization) stripe_connect_account = insert(:stripe_connect_account, organization: organization) @@ -27,6 +27,9 @@ defmodule CodeCorps.OrganizationViewTest do }, "id" => organization.id |> Integer.to_string, "relationships" => %{ + "owner" => %{ + "data" => %{"id" => user.id |> Integer.to_string, "type" => "user"} + }, "organization-memberships" => %{ "data" => [ %{"id" => organization_membership.id |> Integer.to_string, "type" => "organization-membership"} diff --git a/web/models/organization.ex b/web/models/organization.ex index 43c495452..687d812a6 100644 --- a/web/models/organization.ex +++ b/web/models/organization.ex @@ -21,6 +21,8 @@ defmodule CodeCorps.Organization do field :slug, :string field :approved, :boolean + belongs_to :owner, CodeCorps.User + has_one :slugged_route, CodeCorps.SluggedRoute has_one :stripe_connect_account, CodeCorps.StripeConnectAccount @@ -47,8 +49,10 @@ defmodule CodeCorps.Organization do def create_changeset(struct, params) do struct |> changeset(params) + |> cast(params, [:owner_id]) |> generate_slug(:name, :slug) - |> validate_required([:slug, :description]) + |> validate_required([:description, :owner_id, :slug]) + |> assoc_constraint(:owner) |> validate_slug(:slug) |> put_slugged_route() |> generate_icon_color(:default_color) diff --git a/web/views/organization_view.ex b/web/views/organization_view.ex index 9dcb109f6..25b0c0942 100644 --- a/web/views/organization_view.ex +++ b/web/views/organization_view.ex @@ -1,6 +1,6 @@ defmodule CodeCorps.OrganizationView do alias CodeCorps.Cloudex.CloudinaryUrl - use CodeCorps.PreloadHelpers, default_preloads: [:slugged_route, :stripe_connect_account, :organization_memberships, :projects] + use CodeCorps.PreloadHelpers, default_preloads: [:owner, :organization_memberships, :projects, :slugged_route, :stripe_connect_account] use CodeCorps.Web, :view use JaSerializer.PhoenixView @@ -9,6 +9,7 @@ defmodule CodeCorps.OrganizationView do :icon_large_url, :name, :slug, :inserted_at, :updated_at ] + has_one :owner, serializer: CodeCorps.UserView has_one :slugged_route, serializer: CodeCorps.SluggedRouteView has_one :stripe_connect_account, serializer: CodeCorps.StripeConnectAccountView