/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading.Tasks;
using ASC.Api.Core;
using ASC.Api.CRM;
using ASC.Api.Utils;
using ASC.Common.Web;
using ASC.Core.Notify.Signalr;
using ASC.Core.Tenants;
using ASC.CRM.ApiModels;
using ASC.CRM.Core;
using ASC.CRM.Core.Dao;
using ASC.CRM.Core.Entities;
using ASC.CRM.Core.Enums;
using ASC.CRM.Resources;
using ASC.Data.Storage;
using ASC.VoipService;
using ASC.VoipService.Dao;
using ASC.VoipService.Twilio;
using ASC.Web.Api.Routing;
using ASC.Web.CRM.Classes;
using ASC.Web.Studio.Utility;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using SecurityContext = ASC.Core.SecurityContext;
namespace ASC.CRM.Api
{
public class VoIPController : BaseApiController
{
private readonly SignalrServiceClient _signalrServiceClient;
private readonly ApiContext _apiContext;
private readonly VoipEngine _voipEngine;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly CommonLinkUtility _commonLinkUtility;
private readonly StorageFactory _storageFactory;
private readonly ContactPhotoManager _contactPhotoManager;
private readonly Global _global;
public VoIPController(CrmSecurity crmSecurity,
DaoFactory daoFactory,
Global global,
ContactPhotoManager contactPhotoManager,
StorageFactory storageFactory,
CommonLinkUtility commonLinkUtility,
SecurityContext securityContext,
TenantUtil tenantUtil,
VoipEngine voipEngine,
ApiContext apiContext,
SignalrServiceClient signalrServiceClient,
IMapper mapper)
: base(daoFactory, crmSecurity, mapper)
{
_global = global;
_contactPhotoManager = contactPhotoManager;
_storageFactory = storageFactory;
_commonLinkUtility = commonLinkUtility;
_securityContext = securityContext;
_tenantUtil = tenantUtil;
_voipEngine = voipEngine;
_apiContext = apiContext;
_signalrServiceClient = signalrServiceClient;
}
///
///
///
///
/// Voip
///
///
///
[Read(@"voip/numbers/available")]
public IEnumerable GetAvailablePhoneNumbers(PhoneNumberType numberType, string isoCountryCode)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
if (string.IsNullOrEmpty(isoCountryCode)) throw new ArgumentException();
return _daoFactory.GetVoipDao().GetProvider().GetAvailablePhoneNumbers(numberType, isoCountryCode);
}
///
///
///
///
/// Voip
///
///
[Read(@"voip/numbers/unlinked")]
public IEnumerable GetUnlinkedPhoneNumbers()
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var listPhones = _daoFactory.GetVoipDao().GetProvider().GetExistingPhoneNumbers();
var buyedPhones = _daoFactory.GetVoipDao().GetNumbers();
return listPhones.Where(r => buyedPhones.All(b => r.Id != b.Id)).ToList();
}
///
///
///
///
/// Voip
///
///
[Read(@"voip/numbers/existing")]
public IEnumerable GetExistingPhoneNumbers()
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
return _daoFactory.GetVoipDao().GetNumbers();
}
///
///
///
///
/// Voip
///
///
[Create(@"voip/numbers")]
public Task BuyNumberAsync([FromBody] string number)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
return InternalBuyNumberAsync(number);
}
private async Task InternalBuyNumberAsync(string number)
{
var newPhone = _daoFactory.GetVoipDao().GetProvider().BuyNumber(number);
_daoFactory.GetVoipDao().GetProvider().CreateQueue(newPhone);
await SetDefaultAudioAsync(newPhone);
_daoFactory.GetVoipDao().GetProvider().UpdateSettings(newPhone);
return _daoFactory.GetVoipDao().SaveOrUpdateNumber(newPhone);
}
///
///
///
///
/// Voip
///
///
[Create(@"voip/numbers/link")]
public Task LinkNumberAsync([FromBody] string id)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
return InternalLinkNumberAsync(id);
}
private async Task InternalLinkNumberAsync([FromBody] string id)
{
var newPhone = _daoFactory.GetVoipDao().GetProvider().GetPhone(id);
_daoFactory.GetVoipDao().GetProvider().CreateQueue(newPhone);
await SetDefaultAudioAsync(newPhone);
_daoFactory.GetVoipDao().GetProvider().UpdateSettings(newPhone);
return _daoFactory.GetVoipDao().SaveOrUpdateNumber(newPhone);
}
public async System.Threading.Tasks.Task SetDefaultAudioAsync(VoipPhone newPhone)
{
var storage = _storageFactory.GetStorage("", "crm");
const string path = "default/";
var files = await storage.ListFilesRelativeAsync("voip", path, "*.*", true)
.SelectAwait(async filePath => new
{
path = _commonLinkUtility.GetFullAbsolutePath((await storage.GetUriAsync("voip", Path.Combine(path, filePath))).ToString()),
audioType = (AudioType)Enum.Parse(typeof(AudioType), Directory.GetParent(filePath).Name, true)
}).ToListAsync();
var audio = files.Find(r => r.audioType == AudioType.Greeting);
newPhone.Settings.GreetingAudio = audio != null ? audio.path : "";
audio = files.Find(r => r.audioType == AudioType.HoldUp);
newPhone.Settings.HoldAudio = audio != null ? audio.path : "";
audio = files.Find(r => r.audioType == AudioType.VoiceMail);
newPhone.Settings.VoiceMail = audio != null ? audio.path : "";
audio = files.Find(r => r.audioType == AudioType.Queue);
newPhone.Settings.Queue.WaitUrl = audio != null ? audio.path : "";
}
///
///
///
///
/// Voip
///
///
[Delete(@"voip/numbers/{numberId:regex(\w+)}")]
public VoipPhone DeleteNumber(string numberId)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var phone = dao.GetNumber(numberId).NotFoundIfNull();
_daoFactory.GetVoipDao().GetProvider().DisablePhone(phone);
dao.DeleteNumber(numberId);
new SignalRHelper(phone.Number, _signalrServiceClient).Reload();
return phone;
}
///
///
///
///
/// Voip
///
///
[Read(@"voip/numbers/{numberId:regex(\w+)}")]
public VoipPhone GetNumber(string numberId)
{
return _daoFactory.GetVoipDao().GetNumber(numberId).NotFoundIfNull();
}
///
///
///
///
/// Voip
///
[Read(@"voip/numbers/current")]
public VoipPhone GetCurrentNumber()
{
return _daoFactory.GetVoipDao().GetCurrentNumber().NotFoundIfNull();
}
///
///
///
///
/// Voip
///
[Read(@"voip/token")]
public string GetToken()
{
return _daoFactory.GetVoipDao().GetProvider().GetToken(GetCurrentNumber().Caller);
}
///
///
///
///
/// Voip
///
///
[Update(@"voip/numbers/{numberId:regex(\w+)}/settings")]
public VoipPhone UpdateSettings(string numberId, string greeting, string holdUp, string wait, string voiceMail, WorkingHours workingHours, bool? allowOutgoingCalls, bool? record, string alias)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var number = dao.GetNumber(numberId).NotFoundIfNull();
number.Alias = Update.IfNotEmptyAndNotEquals(number.Alias, alias);
number.Settings.GreetingAudio = Update.IfNotEmptyAndNotEquals(number.Settings.GreetingAudio, greeting);
number.Settings.HoldAudio = Update.IfNotEmptyAndNotEquals(number.Settings.HoldAudio, holdUp);
number.Settings.VoiceMail = Update.IfNotEmptyAndNotEquals(number.Settings.VoiceMail, voiceMail);
number.Settings.WorkingHours = Update.IfNotEmptyAndNotEquals(number.Settings.WorkingHours, workingHours);
if (!string.IsNullOrEmpty(wait))
{
number.Settings.Queue.WaitUrl = wait;
}
if (allowOutgoingCalls.HasValue)
{
number.Settings.AllowOutgoingCalls = allowOutgoingCalls.Value;
if (!number.Settings.AllowOutgoingCalls)
{
number.Settings.Operators.ForEach(r => r.AllowOutgoingCalls = false);
}
}
if (record.HasValue)
{
number.Settings.Record = record.Value;
if (!number.Settings.Record)
{
number.Settings.Operators.ForEach(r => r.Record = false);
}
}
dao.SaveOrUpdateNumber(number);
return number;
}
///
///
///
///
/// Voip
///
///
[Update(@"voip/numbers/settings")]
public object UpdateSettings(Queue queue, bool pause)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var numbers = dao.GetNumbers();
if (queue != null)
{
foreach (var number in numbers)
{
if (number.Settings.Queue == null || string.IsNullOrEmpty(number.Settings.Queue.Id))
{
var phone = number as TwilioPhone;
if (phone != null)
{
queue = phone.CreateQueue(phone.Number, queue.Size, queue.WaitUrl, queue.WaitTime * 60);
}
queue.Name = number.Number;
number.Settings.Queue = queue;
}
else
{
var oldQueue = number.Settings.Queue;
oldQueue.Size = Update.IfNotEmptyAndNotEquals(oldQueue.Size, queue.Size);
oldQueue.WaitTime = Update.IfNotEmptyAndNotEquals(oldQueue.WaitTime, queue.WaitTime * 60);
oldQueue.WaitUrl = Update.IfNotEmptyAndNotEquals(oldQueue.WaitUrl, queue.WaitUrl);
}
number.Settings.Pause = pause;
dao.SaveOrUpdateNumber(number);
}
}
return new { queue, pause };
}
///
///
///
///
/// Voip
///
///
[Read(@"voip/numbers/settings")]
public Task