Skip to content

Commit

Permalink
rebase master
Browse files Browse the repository at this point in the history
  • Loading branch information
smpallen99 committed Apr 14, 2018
2 parents 52433a6 + b58cea6 commit 67c0912
Show file tree
Hide file tree
Showing 27 changed files with 236 additions and 32 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# InfinityOne Changelog

## 1.0.0.beta13 (2018-04-xx)

### Enhancements

* [UCX-3907] Support only one logged in device. Logout other devices automatically

### Bug Fixes

* [UCX-3898] Can't unmute user from User details flex panel


## 1.0.0.beta12 (2018-04-09)

### Enhancements

### Bug Fixes

* [UCX-3896] Message replacement patterns with OneChat.refresh_users_status exception
* [UCX-3897] Fix Error when deleting user on system with only one admin.
* [UCX-3900] Should not be able to mute a user in DM channel

## 1.0.0.beta11 (2018-04-05)

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion assets/js/one_chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,5 @@ import * as cc from "./chat_channel"
window.page_params = {
default_language: "en",
default_language_name: "English",
ucxchat: ucxchat,
ucxchat: window.ucxchat || {},
};
58 changes: 58 additions & 0 deletions lib/infinity_one/plug/single_login.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
defmodule InfinityOne.Plug.SingleLogin do
@moduledoc """
Plug to allow only one login per user.
Checks to see if another device is logged in for the user. If it finds other
logins, it logs them out.
"""
@behaviour Plug

import Plug.Conn

alias InfinityOne.OnePubSub
alias Coherence.CredentialStore.Server

require Logger

@session_key Application.get_env(:coherence, :session_key, "session_auth")

def init(opts) do
%{
store: Keyword.get(opts, :store, Coherence.CredentialStore.Session),
assigns_key: Keyword.get(opts, :assigns_key, :current_user),
login_key: Keyword.get(opts, :login_cookie, Coherence.Config.login_cookie),
}
end

def call(conn, opts) do
do_call(conn, opts, Process.whereis(Server))
end

defp do_call(conn, _opts, nil) do
conn
end

defp do_call(conn, opts, pid) do
user = conn.assigns.current_user
logins =
pid
|> :sys.get_state()
|> Map.get(:store)
|> Enum.filter(& elem(&1, 1) == user.id)

if length(logins) == 1 do
conn
else
key = get_session(conn, @session_key)
if is_nil(key), do: raise("Cannot find the session")

logins
|> Enum.reject(& elem(&1, 0) == key)
|> Enum.reduce(conn, fn {creds, _}, acc ->
opts.store.delete_credentials(creds)
OnePubSub.broadcast("user:" <> user.id, "logout", %{creds: creds})
acc
end)
end
end
end
31 changes: 31 additions & 0 deletions lib/infinity_one/release_tasks.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ defmodule InfinityOne.ReleaseTasks do
alias InfinityOne.Repo
alias InfinityOne.Accounts
alias OneChat.Channel
alias OneChat.Settings.Layout
alias OneChat.Direct

require Logger

Expand Down Expand Up @@ -176,6 +178,35 @@ defmodule InfinityOne.ReleaseTasks do
end
end)
end
end

@doc """
Reset the admin layout content_home_body setting back to its default.
Run this command after upgrading a system to get the default content page which
includes the link to download the desktop clients.
"""
def reset_content_home_body do
default = Layout.schema().__struct__
Layout.update(Layout.get, %{content_home_body: default.content_home_body})
end

@doc """
Run database migration functions, if required.
Run this command after upgrading system to execute database migration functions.
"""
def migrate_dm_friends do
if Enum.any?(Direct.list(), & is_nil(&1.friend_id)) do
IO.puts "Migration required! Running now"
result = Direct.migrate_db()
if result != [] do
IO.puts "Some errors were found. Please check the output below!"
end
result
else
IO.puts "Migration not needed!"
end
end

end
1 change: 1 addition & 0 deletions lib/infinity_one_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defmodule InfinityOneWeb.Router do
plug(:put_secure_browser_headers)
plug(InfinityOne.Plugs.Setup)
plug(Coherence.Authentication.Session, protected: true)
plug(InfinityOne.Plug.SingleLogin)
end

pipeline :api do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule InfinityOne.Mixfile do
def project do
[
app: :infinity_one,
version: "1.0.0-beta11",
version: "1.0.0-beta13",
elixir: "~> 1.5",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ defmodule OneAdminWeb.AdminChannel do
async_js socket, ~s/$('.-autocomplete-container.rooms').removeClass('hidden')/
end

def admin_new_pattern(socket, sender) do
def admin_new_pattern(socket, _sender) do
last_id_string = Rebel.Core.exec_js!(socket, ~s/$('.input-line.message-pattern').last().attr('data-id')/)
index =
case is_binary(last_id_string) && Integer.parse(last_id_string) do
Expand Down
1 change: 1 addition & 0 deletions plugins/one_backup_restore/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use Mix.Config

config :unbrella, :plugins, one_backup_restore: [
module: OneBackupRestore,
application: OneBackupRestore.Application,
]

import_config "#{Mix.env}.exs"
21 changes: 21 additions & 0 deletions plugins/one_backup_restore/lib/one_backup_restore/application.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule OneBackupRestore.Application do
@moduledoc """
Backup and Restore Application module.
Creates the backup path if it does not already exist.
"""

alias OneBackupRestore.Utils
require Logger

def start(_, _) do
case File.mkdir_p Utils.backup_path() do
:ok ->
:ok
{:error, error} ->
Logger.error("Could not create backup path #{Utils.backup_path()} - error: #{inspect error}")
:error
end
end

end
3 changes: 2 additions & 1 deletion plugins/one_chat/lib/one_chat.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ defmodule OneChat do
end

def refresh_users_status(username) when is_binary(username) do
if user_id = Accounts.user_id_by_username(username) do
with false <- is_nil(username),
user_id when not is_nil(user_id) <- Accounts.user_id_by_username(username) do
OnePubSub.broadcast "user:all", "status:refresh-user", %{username: username, user_id: user_id}
end
end
Expand Down
6 changes: 5 additions & 1 deletion plugins/one_chat/lib/one_chat/accounts/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,17 @@ defmodule OneChat.Accounts do
Accounts.count_user_roles(role) == 1
end

def user_is_admin?(user) do
Accounts.has_role?(user, "admin")
end

def delete_user(%{} = user) do
changeset = Accounts.change_user(user)

cond do
ids = user_last_owner_of_any_rooms(user) ->
{:error, add_error(changeset, :roles, ~g(Can't delete last owner), room_ids: ids)}
last_admin?() ->
user_is_admin?(user) and last_admin?() ->
{:error, add_error(changeset, :roles, ~g(Can't delete last admin))}
true ->
Accounts.delete_user(user)
Expand Down
6 changes: 4 additions & 2 deletions plugins/one_chat/lib/one_chat/message_replacement_patterns.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ defmodule OneChat.MessageReplacementPatterns do

defp compile_patterns do
try do
{res, _} = Code.eval_string OneSettings.message_replacement_patterns()
res
case Code.eval_string OneSettings.message_replacement_patterns() do
{nil, _} -> []
{res, _} -> res
end
rescue
_ -> []
end
Expand Down
8 changes: 7 additions & 1 deletion plugins/one_chat/lib/one_chat/models/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,16 @@ defmodule OneChat.Channel do
end
end

def direct?(channel) do
def direct?(%@schema{} = channel) do
channel.type == 2
end

def direct?(channel_id) when is_binary(channel_id) do
channel_id
|> get()
|> direct?()
end

def subscription_status(%{subscriptions: subs} = _channel, user_id) when is_list(subs) do
Enum.reduce subs, {false, false}, fn
%{user_id: ^user_id, hidden: hidden}, _acc -> {true, hidden}
Expand Down
14 changes: 8 additions & 6 deletions plugins/one_chat/lib/one_chat/models/direct.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ defmodule OneChat.Direct do

def migrate_db() do
__MODULE__.list()
|> Enum.reduce([], fn direct, acc ->
user = InfinityOne.Accounts.get_by_username(direct.users)
case __MODULE__.update(direct, %{friend_id: user.id}) do
{:ok, _} -> acc
{:error, changeset} -> [changeset | acc]
end
|> Enum.reduce([], fn
%{friend_id: nil} = direct, acc ->
friend = InfinityOne.Accounts.get_by_username(direct.users)
case __MODULE__.update(direct, %{friend_id: friend.id}) do
{:ok, _} -> acc
{:error, changeset} -> [changeset | acc]
end
_, acc -> acc
end)
end

Expand Down
30 changes: 30 additions & 0 deletions plugins/one_chat/lib/one_chat/models/mute.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
defmodule OneChat.Mute do
@moduledoc """
Track mute status for user and channel.
When created, the associated user is muted in the given channel. Delete
the record to unmute them.
"""
use OneModel, schema: OneChat.Schema.Mute
use InfinityOneWeb.Gettext

alias OneChat.Channel

@doc """
Checks if the user is muted in the given channel.
Returns true if the user is muted, false otherwise.
"""
def user_muted?(channel_id, user_id) do
!!get_by(channel_id: channel_id, user_id: user_id)
end

@doc """
A prepare changes hook to check that we are not trying to mute in a direct channel.
"""
def prepare_check_channel(%{action: :insert} = changeset) do
if Channel.direct?(changeset.changes.channel_id) do
Ecto.Changeset.add_error(changeset, :channel_id,
~g(can't be muted in a direct message channel))
else
changeset
end
end

def prepare_check_channel(changeset) do
changeset
end

end
6 changes: 5 additions & 1 deletion plugins/one_chat/lib/one_chat/models/schema/mute.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ defmodule OneChat.Schema.Mute do
struct
|> cast(params, @fields)
|> validate_required(@fields)
|> unique_constraint(:user_id, name: :muted_user_id_channel_id_index)
|> unique_constraint(:user_id,
name: :muted_user_id_channel_id_index,
message: "is already muted"
)
|> prepare_changes(&OneChat.Mute.prepare_check_channel/1)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule OneChatWeb.RoomChannel.Channel do

alias OneChat.{Message, Subscription, Settings, Mute, TypingAgent}
alias InfinityOne.{Accounts, OnePubSub, Permissions}
alias OneChatWeb.UserChannel
alias OneChatWeb.{UserChannel, SharedView}

require OneChat.ChatConstants, as: CC

Expand Down Expand Up @@ -78,9 +78,12 @@ defmodule OneChatWeb.RoomChannel.Channel do
current_user = Accounts.preload_schema current_user, [:roles, user_roles: :role]
if Permissions.has_permission? current_user, "mute-user", channel_id do
case Mute.create(%{user_id: user.id, channel_id: channel_id}) do
{:error, _cs} ->
message = ~g"User" <> " `@" <> user.username <> "` " <> ~g"already muted."
{:error, message}
{:error, changeset} ->
error =
SharedView.format_errors(changeset, formatter: fn list, _ ->
list |> Enum.map(fn {_, b} -> [b] end) |> Enum.join("\n")
end)
{:error, gettext("User @%{name} ", name: user.username) <> error}
{:ok, _} ->
notify_user_muted(channel_id, user, current_user)
{:ok, ~g"muted"}
Expand Down
19 changes: 17 additions & 2 deletions plugins/one_chat/lib/one_chat_web/channels/user_channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ defmodule OneChatWeb.UserChannel do
:delete_subscription
subscribe_callback "user:" <> user_id, "room:update",
:room_update
subscribe_callback "user:" <> user_id, "logout", :logout
subscribe_callback "user:" <> user_id, "webrtc:offer", :webrtc_offer
subscribe_callback "user:" <> user_id, "webrtc:answer", {WebrtcChannel, :webrtc_answer}
subscribe_callback "user:" <> user_id, "webrtc:leave", {WebrtcChannel, :webrtc_leave}
Expand Down Expand Up @@ -1432,6 +1433,19 @@ defmodule OneChatWeb.UserChannel do
push socket, "update:alerts", %{}
end

def logout(_event, payload, socket) do
key = Rebel.Core.exec_js!(socket, ~s/window.ucxchat.key/)
if key == payload.creds do
Client.toastr(socket, :warning,
~g(Logging you out. Someone logged into your account from another device.))
spawn fn ->
Process.sleep(3_000)
Rebel.Core.async_js(socket, ~s(window.location.href="/logout"))
end
end
socket
end

def room_update(_event, payload, socket) do
trace "room_update", payload

Expand Down Expand Up @@ -1787,8 +1801,9 @@ defmodule OneChatWeb.UserChannel do
defdelegateadmin :admin_add_user_role
defdelegateadmin :admin_user_role_remove
defdelegateadmin :admin_click_user_role_member
defdelegateadmin :admin_user_role_search_rooms
defdelegateadmin :admin_user_role_search_pages
defdelegateadmin :admin_user_role_search_channel
# defdelegateadmin :admin_user_role_search_rooms
# defdelegateadmin :admin_user_role_search_pages
defdelegateadmin :admin_click_scoped_room
defdelegateadmin :admin_autocomplete_mouseenter
defdelegateadmin :admin_reset_setting_click
Expand Down
Loading

0 comments on commit 67c0912

Please sign in to comment.