Compare commits

..

No commits in common. "8d0a45471370d3be5b3b352966874f7d696fe0e2" and "d61183c0a822aecd12574239a63d8f9061ed9178" have entirely different histories.

6 changed files with 6 additions and 791 deletions

View file

@ -1,8 +1,3 @@
1.1.2
* Fix creating a new Conversation with a new Customer.
* Fix the error shown when trying to create a Customer with no linked Mailbox.
1.1.1 1.1.1
* Fix the ability to start new Conversations. * Fix the ability to start new Conversations.

View file

@ -1,742 +0,0 @@
<?php
/*
SPDX-License-Identifier: AGPL-3.0-only
SPDX-FileCopyrightText: © 2024 Millions Missing FRANCE <info@millionsmissing.fr>
*/
namespace Modules\MMFRestrictedCustomers\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Attachment;
use App\Conversation;
use App\Events\ConversationStatusChanged;
use App\Events\ConversationUserChanged;
use App\Events\UserAddedNote;
use App\Events\UserCreatedConversation;
use App\Events\UserReplied;
use App\Mailbox;
use App\MailboxUser;
use App\Thread;
use Modules\MMFRestrictedCustomers\Entities\Customer;
use App\Http\Controllers\ConversationsController as BaseConversationsController;
class ConversationsController extends BaseConversationsController {
/**
* Conversations ajax controller.
*/
public function ajax(Request $request) {
// This override is only required for "send_reply" requests.
if ( $request->action != 'send_reply' )
return parent::ajax($request);
$response = [
'status' => 'error',
'msg' => '', // this is error message
];
$user = auth()->user();
$mailbox = Mailbox::findOrFail($request->mailbox_id);
if (!$response['msg'] && !$user->can('view', $mailbox)) {
$response['msg'] = __('Not enough permissions');
}
$conversation = null;
if (!$response['msg'] && !empty($request->conversation_id)) {
$conversation = Conversation::find($request->conversation_id);
if ($conversation && !$user->can('view', $conversation)) {
$response['msg'] = __('Not enough permissions');
}
}
$new = false;
if (empty($request->conversation_id)) {
$new = true;
}
$is_note = false;
if (!empty($request->is_note)) {
$is_note = true;
}
// Conversation type.
$type = Conversation::TYPE_EMAIL;
if (!empty($request->type)) {
$type = (int)$request->type;
} elseif ($conversation) {
$type = $conversation->type;
}
$is_phone = false;
if ($type == Conversation::TYPE_PHONE) {
$is_phone = true;
}
$is_custom = false;
if ($type == Conversation::TYPE_CUSTOM) {
$is_custom = true;
}
$is_create = false;
if (!empty($request->is_create)) {
//if ($new || ($from_draft && $conversation->threads_count == 1)) {
$is_create = $request->is_create;
}
$is_forward = false;
if (!empty($request->subtype) && (int)$request->subtype == Thread::SUBTYPE_FORWARD) {
$is_forward = true;
}
$is_multiple = false;
if (!empty($request->multiple_conversations)) {
$is_multiple = true;
}
// If reply is being created from draft, there is already thread created
$thread = null;
$from_draft = false;
if (( ! $is_note || $is_phone || $is_custom ) && ! $response['msg'] && ! empty($request->thread_id)) {
$thread = Thread::find($request->thread_id);
if ($thread && (!$conversation || $thread->conversation_id != $conversation->id)) {
$response['msg'] = __('Incorrect thread');
} else {
$from_draft = true;
}
}
if (!$response['msg']) {
if ($thread && $from_draft && $thread->state == Thread::STATE_PUBLISHED) {
$response['msg'] = __('Message has been already sent. Please discard this draft.');
}
}
// Validate form
if (!$response['msg']) {
if ($new) {
if ($type == Conversation::TYPE_EMAIL) {
$validator = Validator::make($request->all(), [
'to' => 'required|array',
'subject' => 'required|string|max:998',
'body' => 'required|string',
'cc' => 'nullable|array',
'bcc' => 'nullable|array',
]);
} elseif ($type === Conversation::TYPE_PHONE) {
// Phone conversation.
$validator = Validator::make($request->all(), [
'name' => 'required|string',
'subject' => 'required|string|max:998',
'body' => 'required|string',
'phone' => 'nullable|string',
'to_email' => 'nullable|string',
]);
} elseif ($type === Conversation::TYPE_CUSTOM) {
$validation_rules = \Eventy::filter('conversation.custom.validation_rules', [
'body' => 'required|string',
'cc' => 'nullable|array',
'bcc' => 'nullable|array',
], $request);
$validator = Validator::make($request->all(), $validation_rules);
}
} else {
$validator = Validator::make($request->all(), [
'body' => 'required|string',
'cc' => 'nullable|array',
'bcc' => 'nullable|array',
]);
}
if ($validator->fails()) {
foreach ($validator->errors()->getMessages()as $errors) {
foreach ($errors as $field => $message) {
$response['msg'] .= $message.' ';
}
}
}
}
$body = $request->body;
// Replace base64 images with attachment URLs in case text
// was copy and pasted into the editor.
// https://github.com/freescout-helpdesk/freescout/issues/3057
$body = Thread::replaceBase64ImagesWithAttachments($body);
// List of emails.
$to_array = [];
if ($is_forward) {
$to_array = Conversation::sanitizeEmails($request->to_email);
} else {
$to_array = Conversation::sanitizeEmails($request->to);
}
// Check To
if (! $response['msg'] && $new && ! $is_phone && ! $is_custom) {
if (!$to_array) {
$response['msg'] .= __('Incorrect recipients');
}
}
// Check max. message size.
if (!$response['msg']) {
$max_message_size = (int)config('app.max_message_size');
if ($max_message_size) {
// Todo: take into account conversation history.
$message_size = mb_strlen($body, '8bit');
// Calculate attachments size.
$attachments_ids = array_merge($request->attachments ?? [], $request->embeds ?? []);
$attachments_ids = $this->decodeAttachmentsIds($attachments_ids);
if (count($attachments_ids)) {
$attachments_to_check = Attachment::select('size')->whereIn('id', $attachments_ids)->get();
foreach ($attachments_to_check as $attachment) {
$message_size += (int)$attachment->size;
}
}
if ($message_size > $max_message_size*1024*1024) {
$response['msg'] = __('Message is too large — :info. Please shorten your message or remove some attachments.', ['info' => __('Max. Message Size').': '.$max_message_size.' MB']);
}
}
}
if (!$response['msg']) {
// Get attachments info
// Delete removed attachments.
$attachments_info = $this->processReplyAttachments($request);
// Determine redirect.
// Must be done before updating current conversation's status or assignee.
// Redirect URL for new no saved yet conversation is determined below.
if (!$new) {
$response['redirect_url'] = $this->getRedirectUrl($request, $conversation, $user);
}
// Conversation
$now = date('Y-m-d H:i:s');
$status_changed = false;
$user_changed = false;
// Chat conversations in chat mode can not be undone.
$can_undo = true;
$request_status = (int)$request->status;
if ($new) {
// New conversation
$conversation = new Conversation();
$conversation->type = $type;
$conversation->subject = $request->subject;
$conversation->setPreview($body);
$conversation->mailbox_id = $request->mailbox_id;
$conversation->created_by_user_id = auth()->user()->id;
$conversation->source_via = Conversation::PERSON_USER;
$conversation->source_type = Conversation::SOURCE_TYPE_WEB;
} else {
// Reply or note
if ($request_status && $request_status != (int)$conversation->status) {
$status_changed = true;
}
if (!empty($request->subject)) {
$conversation->subject = $request->subject;
}
// When switching from regular message to phone and message sent
// without saving a draft type need to be saved here.
// Or vise versa.
if (($conversation->type == Conversation::TYPE_EMAIL && $type == Conversation::TYPE_PHONE)
|| ($conversation->type == Conversation::TYPE_PHONE && $type == Conversation::TYPE_EMAIL)
) {
$conversation->type = $type;
}
// Allow to convert phone conversations into email conversations.
if ($conversation->isPhone() && !$is_note && $conversation->customer
&& $customer_email = $conversation->customer->getMainEmail()
) {
$conversation->type = Conversation::TYPE_EMAIL;
$conversation->customer_email = $customer_email;
$is_phone = false;
}
}
if ($attachments_info['has_attachments']) {
$conversation->has_attachments = true;
}
// Customer can be empty in existing conversation if this is a draft.
$customer_email = '';
$customer = null;
if ($is_phone && $is_create) {
// Phone.
$phone_customer_data = $this->processPhoneCustomer($request);
$customer_email = $phone_customer_data['customer_email'];
$customer = $phone_customer_data['customer'];
if (! $conversation->customer_id) {
$conversation->customer_id = $customer->id;
}
} elseif ($is_custom) {
// No customer for custom conversations.
} else {
// Email or reply to a phone conversation.
if (!empty($to_array)) {
$customer_email = $to_array[0];
} elseif (!$conversation->customer_email
&& ($conversation->isEmail() || $conversation->isPhone())
&& $conversation->customer_id
&& $conversation->customer
) {
// When replying to a phone conversation, we need to
// set 'customer_email' for the conversation.
$customer_email = $conversation->customer->getMainEmail();
}
if (!$conversation->customer_id) {
// The new Customer must be linked to a specific Mailbox.
$data = [];
$data['mailbox_id'] = $conversation->mailbox_id;
$customer = Customer::create($customer_email, $data);
$conversation->customer_id = $customer->id;
} else {
$customer = $conversation->customer;
}
}
if ($customer_email && !$is_note && !$is_forward) {
$conversation->customer_email = $customer_email;
}
$prev_status = $conversation->status;
$conversation->status = $request_status ?: $conversation->status;
if (($prev_status != $conversation->status || $is_create)
&& $conversation->status == Conversation::STATUS_CLOSED
) {
$conversation->closed_by_user_id = $user->id;
$conversation->closed_at = date('Y-m-d H:i:s');
}
// We need to set state, as it may have been a draft.
$prev_state = $conversation->state;
$conversation->state = Conversation::STATE_PUBLISHED;
// Set assignee
$prev_user_id = $conversation->user_id;
if ((int) $request->user_id != -1) {
// Check if user has access to the current mailbox
if ((int) $conversation->user_id != (int) $request->user_id && $mailbox->userHasAccess($request->user_id)) {
$conversation->user_id = $request->user_id;
$user_changed = true;
}
} else {
$conversation->user_id = null;
}
// To is a single email string.
$to = '';
// List of emails.
$to_list = [];
if ($is_forward) {
if (empty($request->to_email[0])) {
$response['msg'] = __('Please specify a recipient.');
return \Response::json($response);
}
$to = $request->to_email[0];
} else {
if (!empty($request->to)) {
// When creating a new conversation, to is a list of emails.
if (is_array($request->to)) {
$to = $request->to[0];
} else {
$to = $request->to;
}
} else {
$to = $conversation->customer_email;
}
}
if (!$is_note && !$is_forward) {
// Save extra recipients to CC
if ($is_create && !$is_multiple && count($to_array) > 1) {
$conversation->setCc(array_merge(Conversation::sanitizeEmails($request->cc), $to_array));
} else {
if (!$is_multiple) {
$conversation->setCc(array_merge(Conversation::sanitizeEmails($request->cc), [$to]));
} else {
$conversation->setCc(Conversation::sanitizeEmails($request->cc));
}
}
$conversation->setBcc($request->bcc);
$conversation->last_reply_at = $now;
$conversation->last_reply_from = Conversation::PERSON_USER;
$conversation->user_updated_at = $now;
}
if ($conversation->isPhone() && $is_note) {
$conversation->last_reply_at = $now;
$conversation->last_reply_from = Conversation::PERSON_USER;
}
$conversation->updateFolder();
if ($from_draft) {
// Increment number of replies in conversation
$conversation->threads_count++;
// We need to set preview here as when conversation is created from draft,
// ThreadObserver::created() method is not called.
$conversation->setPreview($body);
}
$conversation->save();
// Redirect URL for new not saved yet conversation must be determined here.
if ($new) {
$response['redirect_url'] = $this->getRedirectUrl($request, $conversation, $user);
}
// Fire events
\Eventy::action('conversation.send_reply_save', $conversation, $request);
if (!$new) {
if ($status_changed) {
event(new ConversationStatusChanged($conversation));
\Eventy::action('conversation.status_changed', $conversation, $user, $changed_on_reply = true, $prev_status);
}
if ($user_changed) {
event(new ConversationUserChanged($conversation, $user));
\Eventy::action('conversation.user_changed', $conversation, $user, $prev_user_id);
}
}
if ($conversation->state != $prev_state) {
\Eventy::action('conversation.state_changed', $conversation, $user, $prev_state);
}
// Create thread
if (!$thread) {
$thread = new Thread();
$thread->conversation_id = $conversation->id;
if ($is_note || $is_forward) {
$thread->type = Thread::TYPE_NOTE;
} else {
$thread->type = Thread::TYPE_MESSAGE;
}
$thread->source_via = Thread::PERSON_USER;
$thread->source_type = Thread::SOURCE_TYPE_WEB;
} else {
if ($is_forward || $is_phone) {
$thread->type = Thread::TYPE_NOTE;
} else {
$thread->type = Thread::TYPE_MESSAGE;
}
$thread->created_at = $now;
}
if ($new) {
$thread->first = true;
}
$thread->user_id = $conversation->user_id;
$thread->status = $request_status ?? $conversation->status;
$thread->state = Thread::STATE_PUBLISHED;
if (!$is_custom) {
$thread->customer_id = $customer->id;
}
$thread->created_by_user_id = auth()->user()->id;
$thread->edited_by_user_id = null;
$thread->edited_at = null;
$thread->body = $body;
if ($is_create && !$is_multiple && count($to_array) > 1) {
$thread->setTo($to_array);
} else {
$thread->setTo($to);
}
// We save CC and BCC as is and filter emails when sending replies
$thread->setCc($request->cc);
$thread->setBcc($request->bcc);
if ($attachments_info['has_attachments'] && !$is_forward) {
$thread->has_attachments = true;
}
if (!empty($request->saved_reply_id)) {
$thread->saved_reply_id = $request->saved_reply_id;
}
$forwarded_conversations = [];
$forwarded_threads = [];
if ($is_forward) {
// Create forwarded conversations.
foreach ($to_array as $recipient_email) {
$forwarded_conversation = $conversation->replicate();
$forwarded_conversation->type = Conversation::TYPE_EMAIL;
$forwarded_conversation->setPreview($thread->body);
$forwarded_conversation->created_by_user_id = auth()->user()->id;
$forwarded_conversation->source_via = Conversation::PERSON_USER;
$forwarded_conversation->source_type = Conversation::SOURCE_TYPE_WEB;
$forwarded_conversation->threads_count = 0; // Counter will be incremented in ThreadObserver.
$forwarded_customer = Customer::create($recipient_email);
$forwarded_conversation->customer_id = $forwarded_customer->id;
// Reload customer object, otherwise it stores previous customer.
$forwarded_conversation->load('customer');
$forwarded_conversation->customer_email = $recipient_email;
$forwarded_conversation->subject = 'Fwd: '.$forwarded_conversation->subject;
//$forwarded_conversation->setCc(array_merge(Conversation::sanitizeEmails($request->cc), [$to]));
$forwarded_conversation->setCc(Conversation::sanitizeEmails($request->cc));
$forwarded_conversation->setBcc($request->bcc);
$forwarded_conversation->last_reply_at = $now;
$forwarded_conversation->last_reply_from = Conversation::PERSON_USER;
$forwarded_conversation->user_updated_at = $now;
if ($attachments_info['has_attachments']) {
$forwarded_conversation->has_attachments = true;
}
$forwarded_conversation->updateFolder();
$forwarded_conversation->save();
$forwarded_thread = $thread->replicate();
$forwarded_conversations[] = $forwarded_conversation;
$forwarded_threads[] = $forwarded_thread;
}
// Set forwarding meta data.
// todo: store array of numbers and IDs.
$thread->subtype = Thread::SUBTYPE_FORWARD;
$thread->setMeta(Thread::META_FORWARD_CHILD_CONVERSATION_NUMBER, $forwarded_conversation->number);
$thread->setMeta(Thread::META_FORWARD_CHILD_CONVERSATION_ID, $forwarded_conversation->id);
}
// Conversation history.
if (!empty($request->conv_history)) {
if ($request->conv_history != 'global') {
if ($is_forward && !empty($forwarded_threads)) {
foreach ($forwarded_threads as $forwarded_thread) {
$forwarded_thread->setMeta(Thread::META_CONVERSATION_HISTORY, $request->conv_history);
}
} else {
$thread->setMeta(Thread::META_CONVERSATION_HISTORY, $request->conv_history);
}
}
}
// From (mailbox alias).
if (!empty($request->from_alias)) {
$thread->from = $request->from_alias;
}
\Eventy::action('thread.before_save_from_request', $thread, $request);
$thread->save();
// Save forwarded thread.
if ($is_forward) {
foreach ($forwarded_conversations as $i => $forwarded_conversation) {
$forwarded_thread = $forwarded_threads[$i];
$forwarded_thread->conversation_id = $forwarded_conversation->id;
$forwarded_thread->type = Thread::TYPE_MESSAGE;
$forwarded_thread->subtype = null;
if ($attachments_info['has_attachments']) {
$forwarded_thread->has_attachments = true;
}
$forwarded_thread->setMeta(Thread::META_FORWARD_PARENT_CONVERSATION_NUMBER, $conversation->number);
$forwarded_thread->setMeta(Thread::META_FORWARD_PARENT_CONVERSATION_ID, $conversation->id);
$forwarded_thread->setMeta(Thread::META_FORWARD_PARENT_THREAD_ID, $thread->id);
\Eventy::action('send_reply.before_save_forwarded_thread', $forwarded_thread, $request);
$forwarded_thread->save();
}
}
// If thread has been created from draft, remove the draft
// if ($request->thread_id) {
// $draft_thread = Thread::find($request->thread_id);
// if ($draft_thread) {
// $draft_thread->delete();
// }
// }
if ($from_draft) {
// Remove conversation from drafts folder if needed
$conversation->maybeRemoveFromDrafts();
}
// Update folders counters
$conversation->mailbox->updateFoldersCounters();
$response['status'] = 'success';
// Set thread_id for uploaded attachments
if ($attachments_info['attachments']) {
if ($is_forward) {
// Copy attachments for each thread.
if (count($forwarded_threads) > 1) {
$attachments = Attachment::whereIn('id', $attachments_info['attachments'])->get();
}
foreach ($forwarded_threads as $i => $forwarded_thread) {
if ($i == 0) {
Attachment::whereIn('id', $attachments_info['attachments'])->update(['thread_id' => $forwarded_thread->id]);
} else {
foreach ($attachments as $attachment) {
$attachment->duplicate($forwarded_thread->id);
}
}
}
} else {
Attachment::whereIn('id', $attachments_info['attachments'])
->where('thread_id', null)
->update(['thread_id' => $thread->id]);
}
}
// Follow conversation if it's assigned to someone else.
if (!$is_create && !$new && !$is_forward && !$is_note
&& $conversation->user_id != $user->id
) {
$user->followConversation($conversation->id);
}
if ($conversation->isChat() && \Helper::isChatMode()) {
$can_undo = false;
}
// When user creates a new conversation it may be saved as draft first.
if ($is_create) {
// New conversation.
event(new UserCreatedConversation($conversation, $thread));
\Eventy::action('conversation.created_by_user_can_undo', $conversation, $thread);
// After Conversation::UNDO_TIMOUT period trigger final event.
\Helper::backgroundAction('conversation.created_by_user', [$conversation, $thread], now()->addSeconds($this->getUndoTimeout($can_undo)));
} elseif ($is_forward) {
// Forward.
// Notifications to users not sent.
event(new UserAddedNote($conversation, $thread));
foreach ($forwarded_conversations as $i => $forwarded_conversation) {
$forwarded_thread = $forwarded_threads[$i];
// To send email with forwarded conversation.
event(new UserReplied($forwarded_conversation, $forwarded_thread));
\Eventy::action('conversation.user_forwarded_can_undo', $conversation, $thread, $forwarded_conversation, $forwarded_thread);
// After Conversation::UNDO_TIMOUT period trigger final event.
\Helper::backgroundAction('conversation.user_forwarded', [$conversation, $thread, $forwarded_conversation, $forwarded_thread], now()->addSeconds(Conversation::UNDO_TIMOUT));
}
} elseif ($is_note) {
// Note.
event(new UserAddedNote($conversation, $thread));
\Eventy::action('conversation.note_added', $conversation, $thread);
} else {
// Reply.
event(new UserReplied($conversation, $thread));
\Eventy::action('conversation.user_replied_can_undo', $conversation, $thread);
// After Conversation::UNDO_TIMOUT period trigger final event.
\Helper::backgroundAction('conversation.user_replied', [$conversation, $thread], now()->addSeconds($this->getUndoTimeout($can_undo)));
}
// Send new conversation separately to each customer.
if ($is_create && count($to_array) > 1 && $is_multiple) {
$prev_customers_ids = [];
foreach ($to_array as $i => $customer_email) {
// Skip first email, as conversation has already been created for it.
if ($i == 0) {
continue;
}
// Get customer by email.
$customer_tmp = Customer::getByEmail($customer_email);
// Skip same customers.
if ($customer_tmp && in_array($customer_tmp->id, $prev_customers_ids)) {
continue;
}
if (!$customer_tmp) {
$customer_tmp = Customer::create($customer_email);
}
$prev_customers_ids[] = $customer_tmp->id;
// Copy conversation and thread.
$conversation_copy = $conversation->replicate();
$thread_copy = $thread->replicate();
// Save conversation.
$conversation_copy->threads_count = 0;
$conversation_copy->customer_id = $customer_tmp->id;
// Reload customer, otherwise all recipients will have the same name.
$conversation_copy->load('customer');
$conversation_copy->customer_email = $customer_email;
$conversation_copy->has_attachments = $conversation->has_attachments;
$conversation_copy->push();
$thread_copy->conversation_id = $conversation_copy->id;
$thread_copy->customer_id = $customer_tmp->id;
$thread_copy->has_attachments = $conversation->has_attachments;
$thread_copy->setTo($customer_email);
// Reload the conversation, otherwise Thread observer will be
// increasing threads_count for the first conversation.
$thread_copy->load('conversation');
$thread_copy->push();
// Copy attachments.
if (!empty($attachments_info['attachments'])) {
$attachments = Attachment::whereIn('id', $attachments_info['attachments'])->get();
foreach ($attachments as $attachment) {
$attachment->duplicate($thread_copy->id);
}
}
// Events.
// todo: allow to undo all emails
event(new UserCreatedConversation($conversation_copy, $thread_copy));
\Eventy::action('conversation.created_by_user_can_undo', $conversation_copy, $thread_copy);
// After Conversation::UNDO_TIMOUT period trigger final event.
\Helper::backgroundAction('conversation.created_by_user', [$conversation_copy, $thread_copy], now()->addSeconds($this->getUndoTimeout($can_undo)));
}
}
// Compose flash message.
$show_view_link = true;
if (!empty($request->after_send) && $request->after_send == MailboxUser::AFTER_SEND_STAY) {
$show_view_link = false;
}
$flash_vars = ['%tag_start%' => '<strong>', '%tag_end%' => '</strong>', '%view_start%' => '&nbsp;<a href="'.$conversation->url().'">', '%a_end%' => '</a>&nbsp;', '%undo_start%' => '&nbsp;<a href="'.route('conversations.undo', ['thread_id' => $thread->id]).'" class="text-danger">'];
if ($is_phone) {
$flash_type = 'warning';
if ($show_view_link) {
$flash_text = __(':%tag_start%Conversation created:%tag_end% :%view_start%View:%a_end% or :%undo_start%Undo:%a_end%', $flash_vars);
} else {
$flash_text = '<strong>'.__('Conversation created').'</strong>';
}
} elseif ($is_custom) {
$flash_type = 'warning';
$identifier = \Eventy::filter('conversation.custom.identifier', __('Custom conversation'), $request);
if ($show_view_link) {
$flash_text = __(':%tag_start%' . $identifier . ' added:%tag_end% :%view_start%View:%a_end%', $flash_vars);
} else {
$flash_text = '<strong>'.__('%identifier% added',['%identifier%'=>$identifier]).'</strong>';
}
} elseif ($is_note) {
$flash_type = 'warning';
if ($show_view_link) {
$flash_text = __(':%tag_start%Note added:%tag_end% :%view_start%View:%a_end%', $flash_vars);
} else {
$flash_text = '<strong>'.__('Note added').'</strong>';
}
} else {
$flash_type = 'success';
if ($show_view_link) {
$flash_text = __(':%tag_start%Email Sent:%tag_end% :%view_start%View:%a_end% or :%undo_start%Undo:%a_end%', $flash_vars);
} else {
$flash_text = __(':%tag_start%Email Sent:%tag_end% :%undo_start%Undo:%a_end%', $flash_vars);
}
}
if ($can_undo) {
\Session::flash('flash_'.$flash_type.'_floating', $flash_text);
}
}
if ($response['status'] == 'error' && empty($response['msg'])) {
$response['msg'] = 'Unknown error occurred';
}
return \Response::json($response);
}
}

View file

@ -70,13 +70,7 @@ class MMFRestrictedCustomersServiceProvider extends ServiceProvider {
if ( array_key_exists('mailbox_id', $data) ) { if ( array_key_exists('mailbox_id', $data) ) {
$customer->mailbox_id = $data['mailbox_id']; $customer->mailbox_id = $data['mailbox_id'];
} else { } else {
$customer_id = $customer->id; $customer = Customer::find($customer->id);
if ( $customer_id == null ) {
Log::error('The creation of a Customer with no link to a Mailbox is not allowed, and has been aborted.');
// TODO: Error out more gracefully.
abort(500, 'The creation of a Customer with no link to a Mailbox is not allowed, and has been aborted.');
}
$customer = Customer::find($customer_id);
if ( $customer == null ) { if ( $customer == null ) {
Log::error('Trying to use a Customer in another Mailbox than the one it is linked to is not allowed, and has been aborted.'); Log::error('Trying to use a Customer in another Mailbox than the one it is linked to is not allowed, and has been aborted.');
// TODO: Error out more gracefully. // TODO: Error out more gracefully.

View file

@ -33,11 +33,11 @@ So it is highly recommended to backup your customers database:
Download the [release tarball] and extract its content into `Modules/MMFRestrictedCustomers`. Download the [release tarball] and extract its content into `Modules/MMFRestrictedCustomers`.
[release tarball]: https://port.numenaute.org/MMF/freescout-restricted-customers/archive/1.1.2.tar.gz [release tarball]: https://port.numenaute.org/MMF/freescout-restricted-customers/archive/1.1.1.tar.gz
``` ```
wget https://port.numenaute.org/MMF/freescout-restricted-customers/archive/1.1.2.tar.gz -O freescout-restricted-customers-1.1.2.tar.gz wget https://port.numenaute.org/MMF/freescout-restricted-customers/archive/1.1.1.tar.gz -O freescout-restricted-customers-1.1.1.tar.gz
tar xf freescout-restricted-customers-1.1.2.tar.gz -C Modules tar xf freescout-restricted-customers-1.1.1.tar.gz -C Modules
mv Modules/freescout-restricted-customers Modules/MMFRestrictedCustomers mv Modules/freescout-restricted-customers Modules/MMFRestrictedCustomers
``` ```
@ -76,38 +76,6 @@ Route::get('/customers/ajax-search', ['uses' => '\Modules\MMFRestrictedCustomers
Route::post('/customers/ajax', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@ajax', 'laroute' => true])->name('customers.ajax'); Route::post('/customers/ajax', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\CustomersController@ajax', 'laroute' => true])->name('customers.ajax');
``` ```
This other section:
```php
// Conversations
Route::get('/conversation/{id}', ['uses' => 'ConversationsController@view', 'laroute' => true])->name('conversations.view');
Route::post('/conversation/ajax', ['uses' => 'ConversationsController@ajax', 'laroute' => true])->name('conversations.ajax');
Route::post('/conversation/upload', ['uses' => 'ConversationsController@upload', 'laroute' => true])->name('conversations.upload');
Route::get('/mailbox/{mailbox_id}/new-ticket', 'ConversationsController@create')->name('conversations.create');
Route::get('/mailbox/{mailbox_id}/clone-ticket/{from_thread_id}', 'ConversationsController@cloneConversation')->name('conversations.clone_conversation');
//Route::get('/conversation/draft/{id}', 'ConversationsController@draft')->name('conversations.draft');
Route::get('/conversation/ajax-html/{action}', ['uses' => 'ConversationsController@ajaxHtml', 'laroute' => true])->name('conversations.ajax_html');
Route::get('/search', 'ConversationsController@search')->name('conversations.search');
Route::get('/conversation/undo-reply/{thread_id}', 'ConversationsController@undoReply')->name('conversations.undo');
Route::get('/mailbox/{mailbox_id}/chats', 'ConversationsController@chats')->name('conversations.chats');
```
should be replaced with:
```php
// Conversations
Route::get('/conversation/{id}', ['uses' => 'ConversationsController@view', 'laroute' => true])->name('conversations.view');
Route::post('/conversation/ajax', ['uses' => '\Modules\MMFRestrictedCustomers\Http\Controllers\ConversationsController@ajax', 'laroute' => true])->name('conversations.ajax');
Route::post('/conversation/upload', ['uses' => 'ConversationsController@upload', 'laroute' => true])->name('conversations.upload');
Route::get('/mailbox/{mailbox_id}/new-ticket', 'ConversationsController@create')->name('conversations.create');
Route::get('/mailbox/{mailbox_id}/clone-ticket/{from_thread_id}', 'ConversationsController@cloneConversation')->name('conversations.clone_conversation');
//Route::get('/conversation/draft/{id}', 'ConversationsController@draft')->name('conversations.draft');
Route::get('/conversation/ajax-html/{action}', ['uses' => 'ConversationsController@ajaxHtml', 'laroute' => true])->name('conversations.ajax_html');
Route::get('/search', 'ConversationsController@search')->name('conversations.search');
Route::get('/conversation/undo-reply/{thread_id}', 'ConversationsController@undoReply')->name('conversations.undo');
Route::get('/mailbox/{mailbox_id}/chats', 'ConversationsController@chats')->name('conversations.chats');
```
### Edit the artisan commands ### Edit the artisan commands
Console commands set in other modules or in Freescout itself can not be automatically overridden. Console commands set in other modules or in Freescout itself can not be automatically overridden.

View file

@ -1,7 +1,7 @@
{ {
"name": "millions-missing-france/freescout-restricted-customers", "name": "millions-missing-france/freescout-restricted-customers",
"description": "Freescout restricted customers - Restrict access to Freescout customers to specific mailboxes", "description": "Freescout restricted customers - Restrict access to Freescout customers to specific mailboxes",
"version": "1.1.2", "version": "1.1.1",
"type": "library", "type": "library",
"license": ["AGPL-3.0-only"], "license": ["AGPL-3.0-only"],
"authors": [ "authors": [

View file

@ -2,7 +2,7 @@
"name": "MMFRestrictedCustomers", "name": "MMFRestrictedCustomers",
"alias": "mmfrestrictedcustomers", "alias": "mmfrestrictedcustomers",
"description": "Freescout restricted customers - Restrict access to Freescout customers to specific mailboxes", "description": "Freescout restricted customers - Restrict access to Freescout customers to specific mailboxes",
"version": "1.1.2", "version": "1.1.1",
"detailsUrl": "", "detailsUrl": "",
"author": "Millions Missing FRANCE", "author": "Millions Missing FRANCE",
"authorUrl": "info@millionsmissing.fr", "authorUrl": "info@millionsmissing.fr",