Skip to content
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

Recording anonymous users and sending notifications #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defmodule PhoenixChat.Mixfile do
applications: [
:comeonin,
:cowboy,
:faker,
:gettext,
:logger,
:phoenix,
Expand All @@ -45,6 +46,7 @@ defmodule PhoenixChat.Mixfile do
{:comeonin, "~> 2.3"},
{:corsica, "~> 0.4"},
{:cowboy, "~> 1.0"},
{:faker, "~> 0.7"},
{:gettext, "~> 0.11"},
{:guardian, "~> 0.10"},
{:phoenix, "~> 1.2.0"},
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"db_connection": {:hex, :db_connection, "1.0.0-rc.5", "1d9ab6e01387bdf2de7a16c56866971f7c2f75aea7c69cae2a0346e4b537ae0d", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: true]}, {:sbroker, "~> 1.0.0-beta.3", [hex: :sbroker, optional: true]}]},
"decimal": {:hex, :decimal, "1.1.2", "79a769d4657b2d537b51ef3c02d29ab7141d2b486b516c109642d453ee08e00c", [:mix], []},
"ecto": {:hex, :ecto, "2.0.5", "7f4c79ac41ffba1a4c032b69d7045489f0069c256de606523c65d9f8188e502d", [:mix], [{:db_connection, "~> 1.0-rc.4", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.1.2 or ~> 1.2", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.7.7", [hex: :mariaex, optional: true]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.12.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0-beta", [hex: :sbroker, optional: true]}]},
"faker": {:hex, :faker, "0.7.0", "2c42deeac7be717173c78c77fb3edc749fb5d5e460e33d01fe592ae99acc2f0d", [:mix], []},
"fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []},
"gettext": {:hex, :gettext, "0.11.0", "80c1dd42d270482418fa158ec5ba073d2980e3718bacad86f3d4ad71d5667679", [:mix], []},
"guardian": {:hex, :guardian, "0.12.0", "ab1f0a1ab0cd8f4f9c8cca6e28d61136ca682684cf0f82e55a50e8061be7575a", [:mix], [{:jose, "~> 1.6", [hex: :jose, optional: false]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}, {:poison, ">= 1.3.0", [hex: :poison, optional: false]}, {:uuid, ">=1.1.1", [hex: :uuid, optional: false]}]},
Expand Down
18 changes: 18 additions & 0 deletions priv/repo/migrations/20160915111446_create_anonymous_users.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule PhoenixChat.Repo.Migrations.CreateAnonymousUsers do
use Ecto.Migration

def change do
# We want to use a `uuid` as primary key so we need to set `primary_key: false`.
create table(:anonymous_users, primary_key: false) do
# We add the `:id` column manually with a type of `uuid` and set
# it as `primary_key`.
add :id, :uuid, primary_key: true
add :name, :string
add :avatar, :string
add :public_key, :string
add :last_viewed_by_admin_at, :datetime

timestamps
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule PhoenixChat.Repo.Migrations.MessageBelongsToAnonymousUser do
use Ecto.Migration

def up do
alter table(:messages) do
# We need to set `type` as `uuid` so it does not default to `integer`.
add :anonymous_user_id, references(:anonymous_users, on_delete: :nilify_all, type: :uuid)
remove :from
end
end

def down do
alter table(:messages) do
remove :anonymous_user_id
add :from, :string
end
end
end
65 changes: 65 additions & 0 deletions web/models/anonymous_user.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
defmodule PhoenixChat.AnonymousUser do
use PhoenixChat.Web, :model

alias PhoenixChat.Message

# Since we provide the `id` for our AnonymousUser record, we will need to set
# the primary key to not autogenerate it.
@primary_key {:id, :binary_id, autogenerate: false}
# We need to set `@foreign_key_type` below since it defaults to `:integer`.
# We are using a UUID as `id` so we need to set type as `:binary_id`.
@foreign_key_type :binary_id

schema "anonymous_users" do
field :name
field :avatar
field :public_key
field :last_viewed_by_admin_at, PhoenixChat.DateTime
has_many :messages, Message

timestamps
end

def changeset(model, params \\ :empty) do
model
|> cast(params, ~w(public_key id), ~w())
|> put_avatar
|> put_name
end

def last_viewed_changeset(model) do
params = %{last_viewed_by_admin_at: System.system_time(:milliseconds)}
model
|> cast(params, ~w(last_viewed_by_admin_at), [])
end

@doc """
This query returns all users and the respective last messages they
have sent.
Once the query is run, the return value is a tuple of two elements:
`{user, message}`
"""
def by_public_key(public_key, limit \\ 20) do
from u in __MODULE__,
join: m in Message, on: m.anonymous_user_id == u.id,
where: u.public_key == ^public_key,
limit: ^limit,
distinct: u.id,
order_by: [desc: m.inserted_at],
select: {u, m}
end

# Set a fake name for our anonymous user every time we create one
defp put_name(changeset) do
name = (Faker.Color.fancy_name <> " " <> Faker.Company.buzzword()) |> String.downcase
changeset
|> put_change(:name, name)
end

# Set a fake avatar for our anonymous user every time we create one
defp put_avatar(changeset) do
changeset
|> put_change(:avatar, Faker.Avatar.image_url(25, 25))
end
end
13 changes: 9 additions & 4 deletions web/models/message.ex
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
defmodule PhoenixChat.Message do
use PhoenixChat.Web, :model

alias PhoenixChat.{DateTime, User, AnonymousUser}

schema "messages" do
field :body, :string
field :timestamp, PhoenixChat.DateTime
field :timestamp, DateTime
field :room, :string
field :from, :string
belongs_to :user, PhoenixChat.User

belongs_to :user, User
# Note that we set `:type` below. This is so Ecto is aware the type of the
# foreign_key is not an `:integer` but a `:binary_id`.
belongs_to :user, AnonymousUser, type: :binary_id

timestamps
end

@required_fields ~w(body timestamp room)
@optional_fields ~w(user_id from)
@optional_fields ~w(anonymous_user_id user_id)

@doc """
Creates a changeset based on the `model` and `params`.
Expand Down