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

[WIP] [POC] Unified push notification #339

Open
wants to merge 11 commits into
base: main
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
7 changes: 7 additions & 0 deletions .vscode/thunder-tests/thunderCollection.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@
"headers": [],
"tests": []
}
},
{
"_id": "218855f8-9f59-41fb-8da4-163a31e28110",
"name": "devices",
"containerId": "a94213ca-8f76-4321-98c8-c7963d59efb9",
"created": "2023-01-03T15:17:08.973Z",
"sortNum": 110000
}
],
"settings": {
Expand Down
4 changes: 4 additions & 0 deletions .vscode/thunder-tests/thunderEnvironment.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
{
"name": "app_name",
"value": "Lenra Test 3"
},
{
"name": "device_id",
"value": "randomdeviceid42"
}
]
}
Expand Down
19 changes: 19 additions & 0 deletions .vscode/thunder-tests/thunderclient.json
Original file line number Diff line number Diff line change
Expand Up @@ -425,5 +425,24 @@
"headers": [],
"params": [],
"tests": []
},
{
"_id": "adb60f75-7c6c-4417-a5c6-c6f4c442ef41",
"colId": "786cd85e-2a59-44b6-a835-45cd23e28b73",
"containerId": "218855f8-9f59-41fb-8da4-163a31e28110",
"name": "notify_provider",
"url": "{{endpoint}}/api/devices/{{device_id}}/notify_provider",
"method": "PUT",
"sortNum": 310000,
"created": "2023-01-03T15:17:29.268Z",
"modified": "2023-01-03T15:20:36.492Z",
"headers": [],
"params": [],
"body": {
"type": "json",
"raw": "{\n \"endpoint\": \"http://localhost:4000/up/upDgrbsMX3yh7K?up=1\",\n \"system\": \"unified_push\"\n}",
"form": []
},
"tests": []
}
]
3 changes: 3 additions & 0 deletions apps/lenra/lib/lenra/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ defmodule Lenra.Accounts.User do

alias Lenra.Legal.{CGU, UserAcceptCGUVersion}

alias Lenra.Notifications.NotifyProvider

@type t :: %__MODULE__{}

@email_regex ~r/[^@]+@[^\.]+\..+/
Expand All @@ -46,6 +48,7 @@ defmodule Lenra.Accounts.User do
has_many(:builds, Build, foreign_key: :creator_id)
has_many(:environments, Environment, foreign_key: :creator_id)
has_many(:deployments, Deployment, foreign_key: :publisher_id)
has_many(:notif_providers, NotifyProvider)
many_to_many(:environments_accesses, Environment, join_through: UserEnvironmentAccess)
many_to_many(:cgus, CGU, join_through: UserAcceptCGUVersion)
timestamps()
Expand Down
37 changes: 21 additions & 16 deletions apps/lenra/lib/lenra/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,27 @@ defmodule Lenra.Application do
# Start the Event Queue
{EventQueue, &Lenra.LoadWorker.load/0},
# Start the HTTP Client
Supervisor.child_spec(
{Finch,
name: FaasHttp,
pools: %{
Application.fetch_env!(:lenra, :faas_url) => [size: 32, count: 8]
}},
id: :finch_faas_http
),
Supervisor.child_spec(
{Finch,
name: GitlabHttp,
pools: %{
Application.fetch_env!(:lenra, :gitlab_api_url) => [size: 10, count: 3]
}},
id: :finch_gitlab_http
),
{
Finch,
name: FaasHttp,
pools: %{
Application.fetch_env!(:lenra, :faas_url) => [size: 32, count: 8]
}
},
{
Finch,
name: GitlabHttp,
pools: %{
Application.fetch_env!(:lenra, :gitlab_api_url) => [size: 10, count: 3]
}
},
{
Finch,
name: UnifiedPushHttp,
pools: %{
"http://localhost:8001" => [size: 10, count: 3]
}
},
{Cluster.Supervisor, [Application.get_env(:libcluster, :topologies), [name: Lenra.ClusterSupervisor]]}
]

Expand Down
49 changes: 49 additions & 0 deletions apps/lenra/lib/lenra/notifications.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule Lenra.Notifications do
alias Lenra.NotifyWorker
alias Lenra.Repo
alias Lenra.Notifications.{NotifyProvider}
alias ApplicationRunner.Notifications.Notif
import Ecto.Query, only: [from: 2]

def set_notify_provider(params) do
params
|> NotifyProvider.new()
|> Repo.insert(
on_conflict: :replace_all,
conflict_target: [:device_id]
)
end

defp get_providers(user_ids) do
from(np in NotifyProvider, where: np.user_id in ^user_ids)
|> Repo.all()
end

def notify(%Notif{} = notif) do
get_providers(notif.to_uids)
|> Enum.map(fn %NotifyProvider{} = provider ->
NotifyWorker.add_push_notif(provider, notif)
end)
end

def send_up_notification(%NotifyProvider{} = provider, %Notif{} = notif) do
string_params_body = construct_string_body(notif)

Finch.build(:post, provider.endpoint, [], string_params_body)
|> Finch.request(UnifiedPushHttp)
end

defp construct_string_body(%Notif{} = body) do
[:message, :title, :tags, :priority, :attach, :actions, :click, :at]
|> Enum.reduce("", fn elem, url_params ->
case Map.get(body, elem) do
nil ->
url_params

res ->
key = Atom.to_string(elem)
"#{url_params}&#{key}=#{res}"
end
end)
end
end
36 changes: 36 additions & 0 deletions apps/lenra/lib/lenra/notifications/notify_provider.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule Lenra.Notifications.NotifyProvider do
use Lenra.Schema
import Ecto.Changeset

alias Lenra.Notifications.NotifyProvider
alias Lenra.Accounts.User

@derive {Jason.Encoder,
only: [
:device_id,
:endpoint,
:system,
:user_id
]}

schema "notify_provider" do
field(:device_id, :string)
field(:endpoint, :string)
field(:system, Ecto.Enum, values: [:unified_push, :fcm, :apns, :ws])
belongs_to(:user, User)

timestamps()
end

def changeset(dev_code, params \\ %{}) do
dev_code
|> cast(params, [:device_id, :user_id, :endpoint, :system])
|> validate_required([:device_id, :user_id, :endpoint, :system])
|> unique_constraint([:device_id])
|> foreign_key_constraint(:user_id)
end

def new(params) do
changeset(%NotifyProvider{}, params)
end
end
3 changes: 2 additions & 1 deletion apps/lenra/lib/lenra/workers/load_workers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ defmodule Lenra.LoadWorker do
@moduledoc """
function to load worker in eventQueue
"""
alias Lenra.EmailWorker
alias Lenra.{EmailWorker, NotifyWorker}

def load do
EventQueue.add_worker(EmailWorker, :email_verification)
EventQueue.add_worker(EmailWorker, :email_password_lost)
EventQueue.add_worker(EmailWorker, :email_invitation)
EventQueue.add_worker(NotifyWorker, :unified_push)
end
end
21 changes: 21 additions & 0 deletions apps/lenra/lib/lenra/workers/notify_worker.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule Lenra.NotifyWorker do
@moduledoc """
Worker to use for send email
"""
alias Lenra.Notifications
require Logger

def add_push_notif(provider, notif) do
EventQueue.add_event(:push_notif, [provider, notif])
end

def push_notif(provider, notif) do
case provider.system do
:unified_push ->
Notifications.send_up_notification(provider, notif)

_ ->
raise "Not implemented"
end
end
end
20 changes: 11 additions & 9 deletions apps/lenra/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,28 @@ defmodule Lenra.MixProject do
[
{:phoenix_pubsub, "~> 2.0"},
{:telemetry, "~> 0.4.3", override: true},
{:ecto_sql, "~> 3.4"},
{:ecto_sql, "~> 3.9.2"},
{:bamboo, "~> 2.2.0"},
{:bamboo_smtp, "~> 4.2.2"},
{:postgrex, "~> 0.15.8"},
{:postgrex, "~> 0.16.0"},
{:jason, "~> 1.2"},
{:json_diff, "~> 0.1.0"},
{:guardian, "~> 2.1.1"},
{:guardian, "~> 2.3.1"},
{:guardian_db, "~> 2.0"},
{:argon2_elixir, "~> 2.0"},
{:sentry, "~> 8.0"},
{:bypass, "~> 2.0", only: :test},
{:event_queue, git: "https://github.com/lenra-io/event-queue.git", tag: "v1.0.0"},
{:earmark, "~> 1.4.20", only: [:dev, :test], runtime: false},
{:libcluster, "~> 3.3"},
{:application_runner,
git: "https://github.com/lenra-io/application-runner.git",
ref: "v1.0.0-beta.102",
submodules: true},
{:lenra_common, git: "https://github.com/lenra-io/lenra-common.git", tag: "v2.4.0"}

{
:application_runner,
# git: "https://github.com/lenra-io/application-runner.git",
# tag: "v1.0.0-beta.102",
# submodules: true
path: "../../../application-runner"
},
{:lenra_common, git: "https://github.com/lenra-io/lenra-common.git", tag: "v2.5.0"}
]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
defmodule Lenra.Repo.Migrations.AddNotificationTable do
use Ecto.Migration

def change do
create table(:notify_provider) do
add(:user_id, references(:users), null: false)
add(:device_id, :string, null: false)
add(:endpoint, :string, null: false)
add(:system, :string, null: false)
timestamps()
end

create(unique_index(:notify_provider, [:device_id]))
end
end
8 changes: 8 additions & 0 deletions apps/lenra_web/lib/lenra_web/app_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule LenraWeb.AppAdapter do
alias Lenra.{Apps, Repo}
alias Lenra.Apps.{App, Environment, MainEnv}
alias Lenra.Errors.BusinessError
alias ApplicationRunner.Notifications.Notif

@impl ApplicationRunner.Adapter
def allow(user_id, app_name) do
Expand Down Expand Up @@ -69,6 +70,13 @@ defmodule LenraWeb.AppAdapter do
end
end

@impl ApplicationRunner.Adapter
def send_notification(%Notif{} = notif) do
Lenra.Notifications.notify(notif)

:ok
end

defmodule Policy do
@moduledoc """
This policy defines the rules to join an application.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule LenraWeb.NotificationController do
use ApplicationRunner.NotificationsController, adapter: LenraWeb.AppAdapter

use LenraWeb.Policy,
module: LenraWeb.NotificationController.Policy

import Plug.Conn

require Logger

alias Lenra.Notifications
alias LenraWeb.Guardian.Plug

def put_provider(conn, params) do
with :ok <- allow(conn),
user <- Plug.current_resource(conn),
{:ok, provider} <- params |> Map.put("user_id", user.id) |> Notifications.set_notify_provider() do
reply(conn, provider)
end
end
end

defmodule LenraWeb.NotificationController.Policy do
@impl Bouncer.Policy
def authorize(:put_provider, _user, _data), do: true

# credo:disable-for-next-line Credo.Check.Readability.StrictModuleLayout
use LenraWeb.Policy.Default
end
4 changes: 4 additions & 0 deletions apps/lenra_web/lib/lenra_web/controllers/user_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ defmodule LenraWeb.UserController do

alias Lenra.Errors.BusinessError

require Logger

def register(conn, params) do
Logger.debug(inspect(params))

with {:ok, %{inserted_user: user}} <- Accounts.register_user(params) do
conn
|> TokenHelper.assign_access_and_refresh_token(user)
Expand Down
4 changes: 3 additions & 1 deletion apps/lenra_web/lib/lenra_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule LenraWeb.Router do

require ApplicationRunner.Router

ApplicationRunner.Router.app_routes()
ApplicationRunner.Router.app_routes(notification_controller: LenraWeb.NotificationController)

pipeline :api do
plug(:accepts, ["json"])
Expand Down Expand Up @@ -82,6 +82,8 @@ defmodule LenraWeb.Router do

get("/webhooks", WebhooksController, :index)
post("/webhooks", WebhooksController, :api_create)

put("/devices/:device_id/notify_provider", NotificationController, :put_provider)
end

scope "/api", LenraWeb do
Expand Down
5 changes: 3 additions & 2 deletions apps/lenra_web/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ defmodule LenraWeb.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:phoenix, "~> 1.5.9"},
{:phoenix, "~> 1.6.15"},
{:telemetry, "~> 0.4.3", override: true},
{:phoenix_live_dashboard, "~> 0.4"},
{:telemetry_metrics, "~> 0.4"},
Expand All @@ -42,9 +42,10 @@ defmodule LenraWeb.MixProject do
{:phoenix_ecto, "~> 4.1"},
{:sentry, "~> 8.0"},
{:lenra, in_umbrella: true},
# {:ntfy_proxy, in_umbrella: true},
{:cors_plug, "~> 3.0", only: :dev, runtime: false},
{:bouncer, git: "https://github.com/lenra-io/bouncer.git", tag: "v1.0.0"},
{:lenra_common, git: "https://github.com/lenra-io/lenra-common.git", tag: "v2.4.0"}
{:lenra_common, git: "https://github.com/lenra-io/lenra-common.git", tag: "v2.5.0"},
]
end
end
4 changes: 4 additions & 0 deletions apps/ntfy_proxy/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[
import_deps: [:phoenix],
inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"]
]
Loading