Skip to content

Commit 20b9396

Browse files
authoredJul 28, 2020
Merge pull request #44 from papercups-io/revert-security-changes
Revert security changes
2 parents f43c866 + bec7838 commit 20b9396

File tree

6 files changed

+42
-69
lines changed

6 files changed

+42
-69
lines changed
 

‎assets/src/api.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ export type RegisterParams = LoginParams & {
2727
passwordConfirmation: string;
2828
};
2929

30-
export const getAccessToken = (): string | null => {
30+
const getAccessToken = (): string | null => {
3131
const tokens = getAuthTokens();
3232

3333
return (tokens && tokens.token) || null;
3434
};
3535

36-
export const getRefreshToken = (): string | null => {
36+
const getRefreshToken = (): string | null => {
3737
const tokens = getAuthTokens();
3838

3939
return (tokens && tokens.renew_token) || null;

‎assets/src/components/account/GettingStartedOverview.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ const ExamplePage = () => {
165165
subtitle={subtitle}
166166
primaryColor={color}
167167
accountId={accountId}
168-
baseUrl="https://app.papercups.io"
168+
baseUrl={'https://app.papercups.io'}
169169
defaultIsOpen
170170
/>
171171
</Box>

‎assets/src/components/conversations/ConversationsProvider.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class ConversationsProvider extends React.Component<Props, State> {
9797
channel: Channel | null = null;
9898

9999
async componentDidMount() {
100-
socket.connect({token: API.getAccessToken()});
100+
socket.connect();
101101

102102
const [currentUser, account, numTotalMessages] = await Promise.all([
103103
API.me(),
@@ -279,13 +279,19 @@ export class ConversationsProvider extends React.Component<Props, State> {
279279
conversationId: string,
280280
cb?: () => void
281281
) => {
282+
const {account, currentUser} = this.state;
283+
const {id: accountId} = account;
284+
const {id: userId} = currentUser;
285+
282286
if (!this.channel || !message || message.trim().length === 0) {
283287
return;
284288
}
285289

286290
this.channel.push('shout', {
287291
body: message,
292+
user_id: userId,
288293
conversation_id: conversationId,
294+
account_id: accountId,
289295
sender: 'agent', // TODO: remove?
290296
});
291297

‎lib/chat_api_web/channels/notification_channel.ex

+29-28
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,24 @@ defmodule ChatApiWeb.NotificationChannel do
55
alias ChatApi.{Messages, Conversations}
66

77
@impl true
8-
def join("notification:" <> account_id, %{"ids" => ids}, socket) do
9-
if authorized?(socket, account_id) do
10-
topics = for conversation_id <- ids, do: "conversation:#{conversation_id}"
11-
12-
{:ok,
13-
socket
14-
|> assign(:topics, [])
15-
|> put_new_topics(topics)}
8+
def join("notification:lobby", payload, socket) do
9+
if authorized?(payload) do
10+
{:ok, socket}
1611
else
17-
{:error, %{reason: "Unauthorized"}}
12+
{:error, %{reason: "unauthorized"}}
1813
end
1914
end
2015

16+
# TODO: secure this better!
17+
def join("notification:" <> _account_id, %{"ids" => ids}, socket) do
18+
topics = for conversation_id <- ids, do: "conversation:#{conversation_id}"
19+
20+
{:ok,
21+
socket
22+
|> assign(:topics, [])
23+
|> put_new_topics(topics)}
24+
end
25+
2126
# Channels can be used in a request/response fashion
2227
# by sending replies to requests from the client
2328
@impl true
@@ -46,22 +51,22 @@ defmodule ChatApiWeb.NotificationChannel do
4651
end
4752

4853
def handle_in("shout", payload, socket) do
49-
with %{current_user: current_user} <- socket.assigns,
50-
%{id: user_id, account_id: account_id} <- current_user do
51-
msg = Map.merge(payload, %{"user_id" => user_id, "account_id" => account_id})
52-
{:ok, message} = Messages.create_message(msg)
53-
message = Messages.get_message!(message.id)
54-
result = ChatApiWeb.MessageView.render("expanded.json", message: message)
54+
{:ok, message} = Messages.create_message(payload)
55+
message = Messages.get_message!(message.id)
56+
result = ChatApiWeb.MessageView.render("expanded.json", message: message)
57+
# TODO: write doc explaining difference between push, broadcast, etc.
58+
push(socket, "shout", result)
5559

56-
# TODO: write doc explaining difference between push, broadcast, etc.
57-
push(socket, "shout", result)
60+
case result do
61+
%{conversation_id: conversation_id} ->
62+
topic = "conversation:" <> conversation_id
5863

59-
%{conversation_id: conversation_id} = result
60-
topic = "conversation:" <> conversation_id
64+
ChatApiWeb.Endpoint.broadcast_from!(self(), topic, "shout", result)
6165

62-
ChatApiWeb.Endpoint.broadcast_from!(self(), topic, "shout", result)
66+
ChatApi.Slack.send_conversation_message_alert(conversation_id, message.body, type: "agent")
6367

64-
ChatApi.Slack.send_conversation_message_alert(conversation_id, message.body, type: "agent")
68+
_ ->
69+
nil
6570
end
6671

6772
{:noreply, socket}
@@ -93,12 +98,8 @@ defmodule ChatApiWeb.NotificationChannel do
9398
end)
9499
end
95100

96-
defp authorized?(socket, account_id) do
97-
with %{current_user: current_user} <- socket.assigns,
98-
%{account_id: acct} <- current_user do
99-
acct == account_id
100-
else
101-
_ -> false
102-
end
101+
# Add authorization logic here as required.
102+
defp authorized?(_payload) do
103+
true
103104
end
104105
end

‎lib/chat_api_web/channels/user_socket.ex

-20
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,6 @@ defmodule ChatApiWeb.UserSocket do
1818
# See `Phoenix.Token` documentation for examples in
1919
# performing token verification on connect.
2020
@impl true
21-
def connect(%{"token" => token}, socket, _connect_info) do
22-
case get_credentials(socket, token, otp_app: :chat_api) do
23-
nil -> :error
24-
user -> {:ok, assign(socket, :current_user, user)}
25-
end
26-
end
27-
2821
def connect(_params, socket, _connect_info) do
2922
{:ok, socket}
3023
end
@@ -41,17 +34,4 @@ defmodule ChatApiWeb.UserSocket do
4134
# Returning `nil` makes this socket anonymous.
4235
@impl true
4336
def id(_socket), do: nil
44-
45-
defp get_credentials(socket, signed_token, config) do
46-
conn = %Plug.Conn{secret_key_base: socket.endpoint.config(:secret_key_base)}
47-
store_config = [backend: Pow.Store.Backend.EtsCache]
48-
salt = Atom.to_string(ChatApiWeb.APIAuthPlug)
49-
50-
with {:ok, token} <- Pow.Plug.verify_token(conn, salt, signed_token, config),
51-
{user, _metadata} <- Pow.Store.CredentialsCache.get(store_config, token) do
52-
user
53-
else
54-
_any -> nil
55-
end
56-
end
5737
end

‎test/chat_api_web/channels/notification_channel_test.exs

+3-17
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
11
defmodule ChatApiWeb.NotificationChannelTest do
22
use ChatApiWeb.ChannelCase
33

4-
alias ChatApi.{Repo, Accounts, Conversations, Users.User}
5-
6-
@password "secret1234"
4+
alias ChatApi.{Accounts, Conversations}
75

86
setup do
97
{:ok, account} = Accounts.create_account(%{company_name: "Taro"})
108

11-
user =
12-
%User{}
13-
|> User.changeset(%{
14-
email: "test@example.com",
15-
password: @password,
16-
password_confirmation: @password,
17-
account_id: account.id
18-
})
19-
|> Repo.insert!()
20-
219
{:ok, conversation} =
2210
Conversations.create_conversation(%{account_id: account.id, status: "open"})
2311

2412
{:ok, _, socket} =
2513
ChatApiWeb.UserSocket
26-
|> socket("user_id", %{current_user: user})
27-
|> subscribe_and_join(ChatApiWeb.NotificationChannel, "notification:" <> account.id, %{
28-
"ids" => [conversation.id]
29-
})
14+
|> socket("user_id", %{some: :assign})
15+
|> subscribe_and_join(ChatApiWeb.NotificationChannel, "notification:lobby")
3016

3117
%{socket: socket, account: account, conversation: conversation}
3218
end

0 commit comments

Comments
 (0)