diff --git a/.gitignore b/.gitignore index 55f0bbe8..bb307b5b 100644 --- a/.gitignore +++ b/.gitignore @@ -70,7 +70,7 @@ paket-files/ # End of https://www.gitignore.io/api/aspnetcore node_modules -**/wwwroot/dist +#**/wwwroot/dist # nunit test results TestResult.xml @@ -85,3 +85,7 @@ bootstrap-datetimepicker-build.min.css colorpicker.css colorpicker.min.css *.log +CCMWeb/appsettings.Development.json + +logs +CCM.Web/appsettings.Development.json diff --git a/CCM.Core/Attributes/FilterPropertyAttribute.cs b/CCM.Core/Attributes/FilterPropertyAttribute.cs index 859d23eb..82aed7d4 100644 --- a/CCM.Core/Attributes/FilterPropertyAttribute.cs +++ b/CCM.Core/Attributes/FilterPropertyAttribute.cs @@ -28,6 +28,9 @@ namespace CCM.Core.Attributes { + /// + /// Used to collect possible discovery filter properties, use as '[FilterProperty(TableName = "Locations", ColumnName = "Name")]' + /// public class FilterPropertyAttribute : Attribute { public string TableName { get; set; } diff --git a/CCM.WebCommon/Authentication/Credentials.cs b/CCM.Core/Authentication/AuthenticationCredentials.cs similarity index 95% rename from CCM.WebCommon/Authentication/Credentials.cs rename to CCM.Core/Authentication/AuthenticationCredentials.cs index 7dcc431b..ea774e49 100644 --- a/CCM.WebCommon/Authentication/Credentials.cs +++ b/CCM.Core/Authentication/AuthenticationCredentials.cs @@ -24,9 +24,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace CCM.WebCommon.Authentication +namespace CCM.Core.Authentication { - public class Credentials + public class AuthenticationCredentials { public string Username { get; set; } public string Password { get; set; } diff --git a/CCM.WebCommon/Authentication/BasicAuthenticationAttributeBase.cs b/CCM.Core/Authentication/BasicAuthenticationAttributeBase.cs similarity index 50% rename from CCM.WebCommon/Authentication/BasicAuthenticationAttributeBase.cs rename to CCM.Core/Authentication/BasicAuthenticationAttributeBase.cs index 777d622a..04db9d65 100644 --- a/CCM.WebCommon/Authentication/BasicAuthenticationAttributeBase.cs +++ b/CCM.Core/Authentication/BasicAuthenticationAttributeBase.cs @@ -25,94 +25,80 @@ */ using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; +using System.Security.Claims; using System.Security.Principal; +using System.Text.Encodings.Web; using System.Threading; using System.Threading.Tasks; -using System.Web.Http.Filters; -using System.Web.Http.Results; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NLog; -namespace CCM.WebCommon.Authentication +namespace CCM.Core.Authentication { /// /// Based on code from /// http://www.asp.net/web-api/overview/security/authentication-filters /// > - public abstract class BasicAuthenticationAttributeBase : Attribute, IAuthenticationFilter + //public abstract class BasicAuthenticationAttributeBase : Attribute, IAuthenticationFilter + public abstract class BasicAuthenticationAttributeBase : AuthenticationHandler { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public bool AllowMultiple => false; + public BasicAuthenticationAttributeBase( + IOptionsMonitor options, + ILoggerFactory logger, + UrlEncoder encoder, + ISystemClock clock) + : base(options, logger, encoder, clock) + { + } - public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) + protected override async Task HandleAuthenticateAsync() { - HttpRequestMessage request = context.Request; - AuthenticationHeaderValue authorization = request.Headers.Authorization; + var authReqHeader = (string)Request.Headers["Authorization"]; - if (authorization == null) + if (!string.IsNullOrEmpty(authReqHeader)) { // No authentication was attempted (for this authentication method). // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error). - log.Debug("No authentication header in request for {0}", request.RequestUri); - return; + log.Debug("No authentication header in request for {0}", new Uri(Request.GetDisplayUrl()).ToString()); + return AuthenticateResult.Fail("Missing authorization header"); } - if (authorization.Scheme != AuthenticationSchemes.Basic.ToString()) + if (authReqHeader != null && !authReqHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase)) { // No authentication was attempted (for this authentication method). // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error). - log.Debug("Not a Basic authentication header in request for {0}", request.RequestUri); - return; + log.Debug("Not a Basic authentication header in request for {0}", new Uri(Request.GetDisplayUrl()).ToString()); + return AuthenticateResult.Fail("Not using basic authorization scheme"); } - if (string.IsNullOrEmpty(authorization.Parameter)) - { - // Authentication was attempted but failed. Set ErrorResult to indicate an error. - log.Debug("Missing authentication credentials in request for {0}", request.RequestUri); - context.ErrorResult = new AuthenticationFailureResult("Missing credentials", request, HttpStatusCode.BadRequest); - return; - } - - Credentials credentials = BasicAuthenticationHelper.ParseCredentials(authorization.Parameter); - if (credentials == null) + AuthenticationCredentials authenticationCredentials = BasicAuthenticationHelper.ParseCredentials(authReqHeader); + if (authenticationCredentials == null) { // Authentication was attempted but failed. Set ErrorResult to indicate an error. - log.Debug("No username and password in request for {0}", request.RequestUri); - context.ErrorResult = new AuthenticationFailureResult("Invalid credentials", request, HttpStatusCode.BadRequest); - return; + log.Debug("No username and password in request for {0}", new Uri(Request.GetDisplayUrl()).ToString()); + return AuthenticateResult.Fail("Missing or invalid credentials"); } - try - { - IPrincipal principal = await AuthenticateAsync(credentials.Username, credentials.Password, cancellationToken); - - if (principal == null) - { - // Authentication was attempted but failed. Set ErrorResult to indicate an error. - log.Debug("Invalid username ({0}) or password in request for {1}, Req From: {2}, Req Host: {3}", credentials.Username, request.RequestUri, request.Headers.From, request.Headers.Host); - context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request); - return; - } + // Setting up some claims + // TODO: See if things are actually still forwarded + var claims = new[] { + new Claim(ClaimTypes.Role, "Discovery endpoint verified"), + new Claim(ClaimTypes.NameIdentifier, authenticationCredentials.Username), + }; + var identity = new ClaimsIdentity(claims, Scheme.Name); + // Claims principal, an array of Claim Identities or Claims (Many authorities can say how you are) + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, Scheme.Name); - // Authentication succeeded. - context.Principal = principal; - } - catch (Exception ex) - { - log.Error(ex, $"Error in BasicAuthenticationAttribute on request to {request.RequestUri}"); - context.ErrorResult = new InternalServerErrorResult(request); - } + return AuthenticateResult.Success(ticket); } protected abstract Task AuthenticateAsync(string userName, string password, CancellationToken cancellationToken); - - public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) - { - return Task.FromResult(0); - } } } diff --git a/CCM.WebCommon/Authentication/BasicAuthenticationHelper.cs b/CCM.Core/Authentication/BasicAuthenticationHelper.cs similarity index 87% rename from CCM.WebCommon/Authentication/BasicAuthenticationHelper.cs rename to CCM.Core/Authentication/BasicAuthenticationHelper.cs index 2d34b7b9..8dd73c30 100644 --- a/CCM.WebCommon/Authentication/BasicAuthenticationHelper.cs +++ b/CCM.Core/Authentication/BasicAuthenticationHelper.cs @@ -25,22 +25,28 @@ */ using System; +using System.Diagnostics; using System.Text; -namespace CCM.WebCommon.Authentication +namespace CCM.Core.Authentication { public static class BasicAuthenticationHelper { - public static Credentials ParseCredentials(string authorizationString) + public static AuthenticationCredentials ParseCredentials(string authorizationString) { - byte[] credentialBytes; + if (String.IsNullOrEmpty(authorizationString)) + { + return null; + } + byte[] credentialBytes; try { credentialBytes = Convert.FromBase64String(authorizationString); } - catch (FormatException) + catch (Exception ex) { + Debug.WriteLine(ex); return null; } @@ -75,7 +81,7 @@ public static Credentials ParseCredentials(string authorizationString) return null; } - return new Credentials() { Username = credentials[0], Password = credentials[1] }; + return new AuthenticationCredentials() { Username = credentials[0], Password = credentials[1] }; } } } diff --git a/CCM.Core/CCM.Core.csproj b/CCM.Core/CCM.Core.csproj index e246d148..f6c198e7 100644 --- a/CCM.Core/CCM.Core.csproj +++ b/CCM.Core/CCM.Core.csproj @@ -1,291 +1,37 @@ - - - + + - Debug - AnyCPU - {2B04CC56-7DFE-40F0-BA17-21D8B93E0B75} - Library - Properties - CCM.Core - CCM.Core - v4.6.2 - 512 - ..\ - true - 3e12f533 - + netstandard2.1 + 8.0 - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\ReleaseRed\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\ReleaseUtv\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Production\ - - - - ..\packages\AutoMapper.6.2.2\lib\net45\AutoMapper.dll - - - ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll - - - ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll - - - ..\packages\LazyCache.0.7.1.44\lib\net45\LazyCache.dll - True - - - ..\packages\Microsoft.AspNet.Identity.Core.1.0.0\lib\net45\Microsoft.AspNet.Identity.Core.dll - True - - - ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - False - ..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll - - - ..\packages\NLog.4.5.3\lib\net45\NLog.dll - - - - - - - - - - - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.4\lib\net45\System.Net.Http.Formatting.dll - - - ..\packages\IPNetwork2.2.0.3\lib\net40\System.Net.IPNetwork.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - - - + - - - + + + + + + + + + + + + - + ResXFileCodeGenerator Resources.Designer.cs - - - - - \ No newline at end of file + + + + Resources.resx + True + True + + + + diff --git a/CCM.Core/Cache/CachedCallHistoryRepository.cs b/CCM.Core/Cache/CachedCallHistoryRepository.cs index db8097d0..b7ceda11 100644 --- a/CCM.Core/Cache/CachedCallHistoryRepository.cs +++ b/CCM.Core/Cache/CachedCallHistoryRepository.cs @@ -26,22 +26,29 @@ using System; using System.Collections.Generic; +using System.Linq; using CCM.Core.Entities; using CCM.Core.Entities.Specific; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; namespace CCM.Core.Cache { - public class CachedCallHistoryRepository : ICallHistoryRepository + public class CachedCallHistoryRepository : ICachedCallHistoryRepository { private readonly ICallHistoryRepository _internalRepository; private readonly IAppCache _lazyCache; + private readonly ISettingsManager _settingsManager; - public CachedCallHistoryRepository(IAppCache cache, ICallHistoryRepository internalRepository) + public CachedCallHistoryRepository( + IAppCache cache, + ICallHistoryRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = cache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public bool Save(CallHistory callHistory) @@ -58,44 +65,126 @@ public CallHistory GetById(Guid id) public CallHistory GetCallHistoryByCallId(Guid callId) { - return _internalRepository.GetCallHistoryByCallId(callId); + try + { + var history = _lazyCache.GetOrAddCallHistories(() => _internalRepository.GetOneMonthCallHistories(), _settingsManager.CacheTimeLiveData); + return history?.FirstOrDefault(c => c.CallId == callId); + } + catch (Exception) + { + return null; + } } - public IList GetOldCalls(int callCount, bool anonymize) + public IList GetOldCalls(int callCount = 0) { - return _lazyCache.GetOrAddCallHistory(() => _internalRepository.GetOldCalls(callCount, anonymize)); + var history = _lazyCache.GetOrAddOldCalls(() => _internalRepository.GetOneMonthOldCalls(), _settingsManager.CacheTimeLiveData); + return history.Take(callCount).ToList(); } - public IList GetOldCallsFiltered(string region, string codecType, string sipAddress, string searchString, bool anonymize, bool onlyPhoneCalls, int callCount) + public IList GetOldCallsFiltered(string region, string codecType, string sipAddress, string searchString, bool onlyPhoneCalls, int callCount, bool limitByMonth) { - return _internalRepository.GetOldCallsFiltered(region, codecType, sipAddress, searchString, anonymize, - onlyPhoneCalls, callCount); + var oldCalls = _lazyCache.GetOrAddOldCalls(() => _internalRepository.GetOneMonthOldCalls(), _settingsManager.CacheTimeLiveData).AsEnumerable(); + if (oldCalls == null) + { + return null; + } + + if (!string.IsNullOrEmpty(region)) + { + oldCalls = oldCalls.Where(ch => ch.FromRegionName == region || ch.ToRegionName == region); + } + + if (!string.IsNullOrEmpty(codecType)) + { + oldCalls = oldCalls.Where(ch => ch.FromCodecTypeName == codecType || ch.ToCodecTypeName == codecType); + } + + if (!string.IsNullOrEmpty(sipAddress)) + { + oldCalls = oldCalls.Where(ch => ch.FromSip.Contains(sipAddress) || ch.ToSip.Contains(sipAddress)); + } + + if (onlyPhoneCalls) + { + oldCalls = oldCalls.Where(ch => ch.IsPhoneCall); + } + + if (!string.IsNullOrEmpty(searchString)) + { + searchString = searchString.ToLower(); + oldCalls = oldCalls.Where(ch => + ch.FromDisplayName.ToLower().Contains(searchString) || + ch.ToDisplayName.ToLower().Contains(searchString) || + ch.FromSip.Contains(searchString) || + ch.ToSip.Contains(searchString) || + ch.FromLocationName.Contains(searchString) || + ch.ToLocationName.Contains(searchString) || + ch.FromLocationShortName.Contains(searchString) || + ch.ToLocationShortName.Contains(searchString) + ); + } + + if (limitByMonth) + { + var monthLimit = DateTime.Today.AddMonths(-1); + oldCalls = oldCalls.Where(ch => ch.Ended >= monthLimit); + } + + var calls = oldCalls.OrderByDescending(callHistory => callHistory.Ended).Take(callCount).ToList(); + return calls; } - public IList GetCallHistoriesByDate(DateTime startTime, DateTime endTime) + #region Statistics + private IReadOnlyList GetOneYearCallHistory() { - return _internalRepository.GetCallHistoriesByDate(startTime, endTime); + return _lazyCache.GetOrAddOneYearCallHistory(() => _internalRepository.GetOneYearCallHistory(), _settingsManager.CacheTimeLiveData); + } + + public IList GetCallHistoriesByDate(DateTime startDate, DateTime endDate) + { + if (startDate > DateTime.Now.AddYears(-1)) + { + return _internalRepository.GetCallHistoriesByDate(GetOneYearCallHistory(), startDate, endDate); + } + return _internalRepository.GetCallHistoriesByDate(startDate, endDate); } public IList GetCallHistoriesForRegion(DateTime startDate, DateTime endDate, Guid regionId) { + if (startDate > DateTime.Now.AddYears(-1)) + { + return _internalRepository.GetCallHistoriesForRegion(GetOneYearCallHistory(), startDate, endDate, regionId); + } return _internalRepository.GetCallHistoriesForRegion(startDate, endDate, regionId); } public IList GetCallHistoriesForRegisteredSip(DateTime startDate, DateTime endDate, string sipId) { + if (startDate > DateTime.Now.AddYears(-1)) + { + return _internalRepository.GetCallHistoriesForRegisteredSip(GetOneYearCallHistory(), startDate, endDate, sipId); + } return _internalRepository.GetCallHistoriesForRegisteredSip(startDate, endDate, sipId); } public IList GetCallHistoriesForCodecType(DateTime startDate, DateTime endDate, Guid codecTypeId) { + if (startDate > DateTime.Now.AddYears(-1)) + { + return _internalRepository.GetCallHistoriesForCodecType(GetOneYearCallHistory(), startDate, endDate, codecTypeId); + } return _internalRepository.GetCallHistoriesForCodecType(startDate, endDate, codecTypeId); } public IList GetCallHistoriesForLocation(DateTime startDate, DateTime endDate, Guid locationId) { + if (startDate > DateTime.Now.AddYears(-1)) + { + return _internalRepository.GetCallHistoriesForLocation(GetOneYearCallHistory(), startDate, endDate, locationId); + } return _internalRepository.GetCallHistoriesForLocation(startDate, endDate, locationId); } - + #endregion Statistics } } diff --git a/CCM.Core/Cache/CachedCallRepository.cs b/CCM.Core/Cache/CachedCallRepository.cs index 238ab609..3bb4aa1c 100644 --- a/CCM.Core/Cache/CachedCallRepository.cs +++ b/CCM.Core/Cache/CachedCallRepository.cs @@ -28,26 +28,36 @@ using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.Entities.Specific; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; namespace CCM.Core.Cache { - public class CachedCallRepository : ICallRepository + public class CachedCallRepository : ICachedCallRepository { private readonly ICallRepository _internalRepository; private readonly IAppCache _lazyCache; + private readonly ISettingsManager _settingsManager; - public CachedCallRepository(IAppCache cache, ICallRepository internalRepository) + public CachedCallRepository( + IAppCache cache, + ICallRepository internalRepository, + ISettingsManager settingsManager) { - // TODO: Use cache call on the other queries _lazyCache = cache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public IReadOnlyCollection GetOngoingCalls(bool anonymize) { - return _lazyCache.GetOrAddOngoingCalls(() => _internalRepository.GetOngoingCalls(anonymize)); + return _lazyCache.GetOrAddOngoingCalls(() => _internalRepository.GetOngoingCalls(anonymize), _settingsManager.CacheTimeLiveData); + } + + public OnGoingCall GetOngoingCallById(Guid callId) + { + return _internalRepository.GetOngoingCallById(callId); } public bool CallExists(string callId, string hashId, string hashEnt) @@ -81,6 +91,5 @@ public void CloseCall(Guid callId) _internalRepository.CloseCall(callId); _lazyCache.ClearOngoingCalls(); } - } } diff --git a/CCM.Core/Cache/CachedLocationRepository.cs b/CCM.Core/Cache/CachedLocationRepository.cs index 70e1831b..b874e726 100644 --- a/CCM.Core/Cache/CachedLocationRepository.cs +++ b/CCM.Core/Cache/CachedLocationRepository.cs @@ -28,20 +28,26 @@ using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.Entities.Specific; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; namespace CCM.Core.Cache { - public class CachedLocationRepository : ILocationRepository + public class CachedLocationRepository : ICachedLocationRepository { private readonly IAppCache _lazyCache; private readonly ILocationRepository _internalRepository; + private readonly ISettingsManager _settingsManager; - public CachedLocationRepository(IAppCache lazyCache, ILocationRepository internalRepository) + public CachedLocationRepository( + IAppCache lazyCache, + ILocationRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = lazyCache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public Location GetById(Guid id) @@ -73,12 +79,17 @@ public void Delete(Guid id) public List GetAllLocationNetworks() { - return _lazyCache.GetOrAddLocationNetworks(() => _internalRepository.GetAllLocationNetworks()); + return _lazyCache.GetOrAddLocationNetworks(() => _internalRepository.GetAllLocationNetworks(), _settingsManager.CacheTimeConfigData); } public Dictionary GetLocationsAndProfiles() { - return _lazyCache.GetOrAddLocationsAndProfiles(() => _internalRepository.GetLocationsAndProfiles()); + return _lazyCache.GetOrAddLocationsAndProfiles(() => _internalRepository.GetLocationsAndProfiles(), _settingsManager.CacheTimeConfigData); + } + + public List GetAllLocationInfo() + { + return _lazyCache.GetOrAddLocationsInfo(() => _internalRepository.GetAllLocationInfo(), _settingsManager.CacheTimeConfigData); } } } diff --git a/CCM.Core/Cache/CachedProfileGroupRepository.cs b/CCM.Core/Cache/CachedProfileGroupRepository.cs index a1b5f5b3..b0dd4ec7 100644 --- a/CCM.Core/Cache/CachedProfileGroupRepository.cs +++ b/CCM.Core/Cache/CachedProfileGroupRepository.cs @@ -27,20 +27,26 @@ using System; using System.Collections.Generic; using CCM.Core.Entities; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; namespace CCM.Core.Cache { - public class CachedProfileGroupRepository : IProfileGroupRepository + public class CachedProfileGroupRepository : ICachedProfileGroupRepository { private readonly IAppCache _lazyCache; private readonly IProfileGroupRepository _internalRepository; + private readonly ISettingsManager _settingsManager; - public CachedProfileGroupRepository(IAppCache lazyCache, IProfileGroupRepository internalRepository) + public CachedProfileGroupRepository( + IAppCache lazyCache, + IProfileGroupRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = lazyCache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public ProfileGroup GetById(Guid id) @@ -50,24 +56,23 @@ public ProfileGroup GetById(Guid id) public List GetAll() { - return _lazyCache.GetOrAddProfileGroups(() => _internalRepository.GetAll()); + return _lazyCache.GetOrAddProfileGroups(() => _internalRepository.GetAll(), _settingsManager.CacheTimeConfigData); } - public void Save(ProfileGroup location) + public List FindProfileGroups(string search) { - _internalRepository.Save(location); - _lazyCache.ClearProfileGroups(); + return _internalRepository.FindProfileGroups(search); } - public void Delete(Guid id) + public void Save(ProfileGroup profileGroup) { - _internalRepository.Delete(id); + _internalRepository.Save(profileGroup); _lazyCache.ClearProfileGroups(); } - public void SetProfileGroupSortWeight(IList> profileGroupTuples) + public void Delete(Guid id) { - _internalRepository.SetProfileGroupSortWeight(profileGroupTuples); + _internalRepository.Delete(id); _lazyCache.ClearProfileGroups(); } } diff --git a/CCM.Core/Cache/CachedProfileRepository.cs b/CCM.Core/Cache/CachedProfileRepository.cs index f06d00e1..8f2bb98c 100644 --- a/CCM.Core/Cache/CachedProfileRepository.cs +++ b/CCM.Core/Cache/CachedProfileRepository.cs @@ -28,33 +28,39 @@ using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.Entities.Specific; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; namespace CCM.Core.Cache { - public class CachedProfileRepository : IProfileRepository + public class CachedProfileRepository : ICachedProfileRepository { private readonly IAppCache _lazyCache; private readonly IProfileRepository _internalRepository; + private readonly ISettingsManager _settingsManager; - public CachedProfileRepository(IAppCache lazyCache, IProfileRepository internalRepository) + public CachedProfileRepository( + IAppCache lazyCache, + IProfileRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = lazyCache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } - public Profile GetById(Guid id) + public ProfileCodec GetById(Guid id) { return _internalRepository.GetById(id); } - public List GetAll() + public List GetAll() { return _internalRepository.GetAll(); } - public void Save(Profile profile) + public void Save(ProfileCodec profile) { _internalRepository.Save(profile); _lazyCache.ClearProfiles(); @@ -66,14 +72,14 @@ public void Delete(Guid id) _lazyCache.ClearProfiles(); } - public List FindProfiles(string searchString) + public List FindProfiles(string searchString) { return _internalRepository.FindProfiles(searchString); } public IList GetAllProfileNamesAndSdp() { - return _lazyCache.GetOrAddAllProfileNamesAndSdp(() => _internalRepository.GetAllProfileNamesAndSdp()); + return _lazyCache.GetOrAddAllProfileNamesAndSdp(() => _internalRepository.GetAllProfileNamesAndSdp(), _settingsManager.CacheTimeConfigData); } public IList GetAllProfileInfos() @@ -81,11 +87,9 @@ public IList GetAllProfileInfos() return _internalRepository.GetAllProfileInfos(); } - public void SetProfileSortIndex(IList> profileTuples) + public IReadOnlyCollection GetFullDetails() { - _internalRepository.SetProfileSortIndex(profileTuples); - _lazyCache.ClearProfiles(); + return _lazyCache.GetOrAddFullDetailProfiles(() => _internalRepository.GetFullDetails(), _settingsManager.CacheTimeConfigData); } - } } diff --git a/CCM.Core/Cache/CachedRegisteredSipRepository.cs b/CCM.Core/Cache/CachedRegisteredCodecRepository.cs similarity index 77% rename from CCM.Core/Cache/CachedRegisteredSipRepository.cs rename to CCM.Core/Cache/CachedRegisteredCodecRepository.cs index 20b96b04..5a3aa734 100644 --- a/CCM.Core/Cache/CachedRegisteredSipRepository.cs +++ b/CCM.Core/Cache/CachedRegisteredCodecRepository.cs @@ -26,48 +26,49 @@ using System; using System.Collections.Generic; +using System.Linq; using CCM.Core.Entities; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; using CCM.Core.SipEvent; +using CCM.Core.SipEvent.Models; namespace CCM.Core.Cache { - public class CachedRegisteredSipRepository : IRegisteredSipRepository + public class CachedRegisteredCodecRepository : ICachedRegisteredCodecRepository { - private readonly IRegisteredSipRepository _internalRepository; + private readonly IRegisteredCodecRepository _internalRepository; private readonly IAppCache _lazyCache; + private readonly ISettingsManager _settingsManager; - public CachedRegisteredSipRepository(IAppCache cache, IRegisteredSipRepository internalRepository) + public CachedRegisteredCodecRepository( + IAppCache cache, + IRegisteredCodecRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = cache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public IEnumerable GetRegisteredUserAgentsDiscovery() { - return _lazyCache.GetOrAddRegisteredUserAgentsDiscovery(() => _internalRepository.GetRegisteredUserAgentsDiscovery()); + return _lazyCache.GetOrAddRegisteredUserAgentsDiscovery(() => _internalRepository.GetRegisteredUserAgentsDiscovery(), _settingsManager.CacheTimeLiveData); } public IEnumerable GetRegisteredUserAgents() { - return _lazyCache.GetOrAddRegisteredUserAgents(() => _internalRepository.GetRegisteredUserAgents()); + return _lazyCache.GetOrAddRegisteredUserAgents(() => _internalRepository.GetRegisteredUserAgents(), _settingsManager.CacheTimeLiveData); } public SipEventHandlerResult UpdateRegisteredSip(UserAgentRegistration userAgentRegistration) { var result = _internalRepository.UpdateRegisteredSip(userAgentRegistration); - // When reregistration of codec already in cache, just update timestamp + // When reregistration of codec already in cache if (result.ChangeStatus == SipEventChangeStatus.NothingChanged && result.ChangedObjectId != Guid.Empty) { - // TODO: When GetRegisteredSips is gone, decide over this - //var regSip = GetRegisteredSips().FirstOrDefault(rs => rs.Id == result.ChangedObjectId); - //if (regSip != null) - //{ - // regSip.Updated = DateTime.UtcNow; - // return result; - //} return result; } @@ -90,8 +91,12 @@ public SipEventHandlerResult DeleteRegisteredSip(string sipAddress) public IEnumerable GetRegisteredUserAgentsCodecInformation() { - return _lazyCache.GetOrAddRegisteredUserAgentsCodecInformation(() => _internalRepository.GetRegisteredUserAgentsCodecInformation()); + return _lazyCache.GetOrAddRegisteredUserAgentsCodecInformation(() => _internalRepository.GetRegisteredUserAgentsCodecInformation(), _settingsManager.CacheTimeLiveData); } + public IEnumerable GetRegisteredCodecsUpdateTimes() + { + return _internalRepository.GetRegisteredCodecsUpdateTimes(); + } } } diff --git a/CCM.Core/Cache/CachedSettingsRepository.cs b/CCM.Core/Cache/CachedSettingsRepository.cs index 137d4702..d308bc09 100644 --- a/CCM.Core/Cache/CachedSettingsRepository.cs +++ b/CCM.Core/Cache/CachedSettingsRepository.cs @@ -31,7 +31,7 @@ namespace CCM.Core.Cache { - public class CachedSettingsRepository : ISettingsRepository + public class CachedSettingsRepository : ICachedSettingsRepository { private readonly ISettingsRepository _internalRepository; private readonly IAppCache _lazyCache; diff --git a/CCM.Core/Cache/CachedSipAccountRepository.cs b/CCM.Core/Cache/CachedSipAccountRepository.cs index bd23beb0..658c6756 100644 --- a/CCM.Core/Cache/CachedSipAccountRepository.cs +++ b/CCM.Core/Cache/CachedSipAccountRepository.cs @@ -26,22 +26,29 @@ using System; using System.Collections.Generic; +using System.Linq; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using LazyCache; using System.Threading.Tasks; +using CCM.Core.Interfaces.Managers; namespace CCM.Core.Cache { - public class CachedSipAccountRepository : ISipAccountRepository + public class CachedSipAccountRepository : ICachedSipAccountRepository { private readonly ISipAccountRepository _internalRepository; private readonly IAppCache _lazyCache; + private readonly ISettingsManager _settingsManager; - public CachedSipAccountRepository(IAppCache cache, ISipAccountRepository internalRepository) + public CachedSipAccountRepository( + IAppCache cache, + ISipAccountRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = cache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public SipAccount GetById(Guid id) @@ -56,17 +63,19 @@ public SipAccount GetByRegisteredSipId(Guid registeredSipId) public SipAccount GetByUserName(string userName) { + // TODO: XXXX Is already???? return _internalRepository.GetByUserName(userName); } - public List GetAllIncludingRelations() + public SipAccount GetSipAccountByUserName(string username) { - return _internalRepository.GetAllIncludingRelations(); + // TODO: XXXX Is already???? + return GetAll().FirstOrDefault(u => u.UserName.ToLower() == username); } public List GetAll() { - return _lazyCache.GetOrAddSipAccounts(() => _internalRepository.GetAll()); + return _lazyCache.GetOrAddSipAccounts(() => _internalRepository.GetAll(), _settingsManager.CacheTimeConfigData); } public List Find(string startsWith) @@ -74,6 +83,11 @@ public List Find(string startsWith) return _internalRepository.Find(startsWith); } + public void Save(SipAccount ccmUser) + { + _internalRepository.Save(ccmUser); + } + public void Create(SipAccount ccmUser) { _internalRepository.Create(ccmUser); @@ -92,6 +106,13 @@ public void UpdateComment(Guid id, string comment) // TODO: Maybe this needs to clear more things? like registeredUserAgents } + public void UpdateSipAccountQuick(Guid id, string presentationName, string externalReference) + { + _internalRepository.UpdateSipAccountQuick(id, presentationName, externalReference); + _lazyCache.ClearSipAccounts(); + // TODO: Maybe this needs to clear more things? like registeredUserAgents + } + public void UpdatePassword(Guid id, string password) { _internalRepository.UpdatePassword(id, password); @@ -108,6 +129,5 @@ public Task AuthenticateAsync(string username, string password) { return _internalRepository.AuthenticateAsync(username, password); } - } } diff --git a/CCM.Core/Cache/CachedUserAgentRepository.cs b/CCM.Core/Cache/CachedUserAgentRepository.cs index a88668ef..ea3083ef 100644 --- a/CCM.Core/Cache/CachedUserAgentRepository.cs +++ b/CCM.Core/Cache/CachedUserAgentRepository.cs @@ -27,20 +27,26 @@ using System; using System.Collections.Generic; using CCM.Core.Entities; +using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using LazyCache; namespace CCM.Core.Cache { - public class CachedUserAgentRepository : IUserAgentRepository + public class CachedUserAgentRepository : ICachedUserAgentRepository { private readonly IUserAgentRepository _internalRepository; private readonly IAppCache _lazyCache; + private readonly ISettingsManager _settingsManager; - public CachedUserAgentRepository(IAppCache cache, IUserAgentRepository internalRepository) + public CachedUserAgentRepository( + IAppCache cache, + IUserAgentRepository internalRepository, + ISettingsManager settingsManager) { _lazyCache = cache; _internalRepository = internalRepository; + _settingsManager = settingsManager; } public void Save(UserAgent userAgent) @@ -60,12 +66,12 @@ public UserAgent GetById(Guid id) public List GetAll() { - return _lazyCache.GetOrAddUserAgents(() => _internalRepository.GetAll()); + return _lazyCache.GetOrAddUserAgents(() => _internalRepository.GetAll(), _settingsManager.CacheTimeConfigData); } public Dictionary GetUserAgentsTypesAndProfiles() { - return _lazyCache.GetOrAddUserAgentsAndProfiles(() => _internalRepository.GetUserAgentsTypesAndProfiles()); + return _lazyCache.GetOrAddUserAgentsAndProfiles(() => _internalRepository.GetUserAgentsTypesAndProfiles(), _settingsManager.CacheTimeConfigData); } public List Find(string search) diff --git a/CCM.Core/Cache/LazyCacheExtensions.cs b/CCM.Core/Cache/LazyCacheExtensions.cs index 8b173b7f..f86be2b5 100644 --- a/CCM.Core/Cache/LazyCacheExtensions.cs +++ b/CCM.Core/Cache/LazyCacheExtensions.cs @@ -28,7 +28,6 @@ using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.Entities.Specific; -using CCM.Core.Helpers; using LazyCache; using NLog; @@ -36,41 +35,32 @@ namespace CCM.Core.Cache { public static class LazyCacheExtensions { - // Cache time in seconds - public static int CacheTimeLiveData = ApplicationSettings.CacheTimeLiveData; - - public static int CacheTimeFilter = ApplicationSettings.CacheTimeConfigData; - public static int CacheTimeProfiles = ApplicationSettings.CacheTimeConfigData; - public static int CacheTimeProfileGroups = ApplicationSettings.CacheTimeConfigData; - public static int CacheTimeLocations = ApplicationSettings.CacheTimeConfigData; - public static int CacheTimeUserAgents = ApplicationSettings.CacheTimeConfigData; - public static int CacheTimeUserAgentsAndProfiles = ApplicationSettings.CacheTimeConfigData; - public static int CacheTimeSipAccounts = ApplicationSettings.CacheTimeConfigData; - // Cache keys private const string RegisteredUserAgentsDiscoveryKey = "RegisteredUserAgentsDiscovery"; private const string RegisteredUserAgentsCodecInformationKey = "RegisteredUserAgentsCodecInformation"; private const string RegisteredUserAgentsKey = "RegisteredUserAgents"; private const string OngoingCallsKey = "OngoingCalls"; private const string CallHistoryKey = "CallHistory"; + private const string OldCallHistoryKey = "OldCallHistory"; + private const string OneYearCallHistoryKey = "OneYearCallHistory"; private const string SettingsKey = "Settings"; private const string LocationNetworksKey = "LocationNetworks"; private const string LocationsAndProfilesKey = "LocationsAndProfiles"; + private const string LocationsInfoKey = "LocationsInfoKey"; private const string AvailableFiltersKey = "AvailableFilters"; private const string AllProfileNamesAndSdpKey = "AllProfileNamesAndSdp"; private const string ProfileGroupsKey = "ProfileGroups"; + private const string FullDetailProfilesKey = "FullDetailProfilesKey"; private const string UserAgentsKey = "UserAgents"; private const string UserAgentsAndProfilesKey = "UserAgentsAndProfiles"; private const string SipAccountsKey = "SipAccounts"; private static readonly Logger log = LogManager.GetCurrentClassLogger(); - // TODO: Make some decisions on how we deal with replication changes that doesn't trigger a reload of cache if this instance was not the one saving changes. - #region SipAccounts - public static List GetOrAddSipAccounts(this IAppCache cache, Func> sipAccountsLoader) + public static List GetOrAddSipAccounts(this IAppCache cache, Func> sipAccountsLoader, int cacheTimeSipAccounts) { - return cache.GetOrAdd(SipAccountsKey, sipAccountsLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeSipAccounts)); + return cache.GetOrAdd(SipAccountsKey, sipAccountsLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeSipAccounts)); } public static void ClearSipAccounts(this IAppCache cache) @@ -81,19 +71,19 @@ public static void ClearSipAccounts(this IAppCache cache) #endregion #region RegisteredUserAgents - public static IEnumerable GetOrAddRegisteredUserAgents(this IAppCache cache, Func> registeredUserAgentsLoader) + public static IEnumerable GetOrAddRegisteredUserAgents(this IAppCache cache, Func> registeredUserAgentsLoader, int cacheTimeLiveData) { - return cache.GetOrAdd(RegisteredUserAgentsKey, registeredUserAgentsLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLiveData)); + return cache.GetOrAdd(RegisteredUserAgentsKey, registeredUserAgentsLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); } - public static IEnumerable GetOrAddRegisteredUserAgentsDiscovery(this IAppCache cache, Func> registeredUserAgentsDiscoveryLoader) + public static IEnumerable GetOrAddRegisteredUserAgentsDiscovery(this IAppCache cache, Func> registeredUserAgentsDiscoveryLoader, int cacheTimeLiveData) { - return cache.GetOrAdd(RegisteredUserAgentsDiscoveryKey, registeredUserAgentsDiscoveryLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLiveData)); + return cache.GetOrAdd(RegisteredUserAgentsDiscoveryKey, registeredUserAgentsDiscoveryLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); } - public static IEnumerable GetOrAddRegisteredUserAgentsCodecInformation(this IAppCache cache, Func> registeredUserAgentsCodecInformationLoader) + public static IEnumerable GetOrAddRegisteredUserAgentsCodecInformation(this IAppCache cache, Func> registeredUserAgentsCodecInformationLoader, int cacheTimeLiveData) { - return cache.GetOrAdd(RegisteredUserAgentsCodecInformationKey, registeredUserAgentsCodecInformationLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLiveData)); + return cache.GetOrAdd(RegisteredUserAgentsCodecInformationKey, registeredUserAgentsCodecInformationLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); } public static void ClearRegisteredUserAgents(this IAppCache cache) @@ -110,9 +100,9 @@ public static void ClearRegisteredUserAgents(this IAppCache cache) #endregion #region OngoingCalls - public static IReadOnlyCollection GetOrAddOngoingCalls(this IAppCache cache, Func> ongoingCallsLoader) + public static IReadOnlyCollection GetOrAddOngoingCalls(this IAppCache cache, Func> ongoingCallsLoader, int cacheTimeLiveData) { - return cache.GetOrAdd(OngoingCallsKey, ongoingCallsLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLiveData)); + return cache.GetOrAdd(OngoingCallsKey, ongoingCallsLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); } public static void ClearOngoingCalls(this IAppCache cache) @@ -123,15 +113,27 @@ public static void ClearOngoingCalls(this IAppCache cache) #endregion #region CallHistory - public static IList GetOrAddCallHistory(this IAppCache cache, Func> callHistoryLoader) + public static IReadOnlyCollection GetOrAddOldCalls(this IAppCache cache, Func> callHistoryLoader, int cacheTimeLiveData) + { + return cache.GetOrAdd(OldCallHistoryKey, callHistoryLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); + } + + public static IReadOnlyCollection GetOrAddCallHistories(this IAppCache cache, Func> callHistoryLoader, int cacheTimeLiveData) + { + return cache.GetOrAdd(CallHistoryKey, callHistoryLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); + } + + public static IReadOnlyList GetOrAddOneYearCallHistory(this IAppCache cache, Func> oneYearCallHistoryLoader, int cacheTimeLiveData) { - return cache.GetOrAdd(CallHistoryKey, callHistoryLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLiveData)); + return cache.GetOrAdd(OneYearCallHistoryKey, oneYearCallHistoryLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLiveData)); } public static void ClearCallHistory(this IAppCache cache) { log.Debug("Removing call history from cache"); cache.Remove(CallHistoryKey); + cache.Remove(OldCallHistoryKey); + cache.Remove(OneYearCallHistoryKey); } #endregion @@ -149,15 +151,20 @@ public static void ClearSettings(this IAppCache cache) #endregion #region LocationNetworks - public static List GetOrAddLocationNetworks(this IAppCache cache, Func> loader) + public static List GetOrAddLocationNetworks(this IAppCache cache, Func> loader, int cacheTimeLocations) { - var list = cache.GetOrAdd(LocationNetworksKey, loader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLocations)); + var list = cache.GetOrAdd(LocationNetworksKey, loader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLocations)); return list; } - public static Dictionary GetOrAddLocationsAndProfiles(this IAppCache cache, Func> loader) + public static Dictionary GetOrAddLocationsAndProfiles(this IAppCache cache, Func> loader, int cacheTimeLocations) { - return cache.GetOrAdd(LocationsAndProfilesKey, loader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeLocations)); + return cache.GetOrAdd(LocationsAndProfilesKey, loader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLocations)); + } + + public static List GetOrAddLocationsInfo(this IAppCache cache, Func> loader, int cacheTimeLocations) + { + return cache.GetOrAdd(LocationsInfoKey, loader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeLocations)); } public static void ClearLocationNetworks(this IAppCache cache) @@ -167,14 +174,17 @@ public static void ClearLocationNetworks(this IAppCache cache) log.Debug("Removing locations and profiles from cache"); cache.Remove(LocationsAndProfilesKey); + + log.Debug("Removing locations info from cache"); + cache.Remove(LocationsInfoKey); } #endregion #region AvailableFilters - public static IList GetAvailableFilters(this IAppCache cache, Func> loader) + public static IList GetAvailableFilters(this IAppCache cache, Func> loader, int cacheTimeFilter) { // TODO: Should not be called like this?! - var list = cache.GetOrAdd(AvailableFiltersKey, loader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeFilter)); + var list = cache.GetOrAdd(AvailableFiltersKey, loader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeFilter)); return list; } @@ -186,22 +196,30 @@ public static void ClearAvailableFilters(this IAppCache cache) #endregion #region Profiles - public static IList GetOrAddAllProfileNamesAndSdp(this IAppCache cache, Func> allProfileNamesAndSdpLoader) + public static IList GetOrAddAllProfileNamesAndSdp(this IAppCache cache, Func> allProfileNamesAndSdpLoader, int cacheTimeProfiles) { - return cache.GetOrAdd(AllProfileNamesAndSdpKey, allProfileNamesAndSdpLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeProfiles)); + return cache.GetOrAdd(AllProfileNamesAndSdpKey, allProfileNamesAndSdpLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeProfiles)); + } + + public static IReadOnlyCollection GetOrAddFullDetailProfiles(this IAppCache cache, Func> loader, int cacheTime) + { + return cache.GetOrAdd(FullDetailProfilesKey, loader, DateTimeOffset.UtcNow.AddSeconds(cacheTime)); } public static void ClearProfiles(this IAppCache cache) { log.Debug("Removing all profile names and sdp from cache"); cache.Remove(AllProfileNamesAndSdpKey); + + log.Debug("Clearing full detail profiles from cache"); + cache.Remove(FullDetailProfilesKey); } #endregion #region ProfileGroups - public static List GetOrAddProfileGroups(this IAppCache cache, Func> profileGroupsLoader) + public static List GetOrAddProfileGroups(this IAppCache cache, Func> profileGroupsLoader, int cacheTimeProfileGroups) { - return cache.GetOrAdd(ProfileGroupsKey, profileGroupsLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeProfileGroups)); + return cache.GetOrAdd(ProfileGroupsKey, profileGroupsLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeProfileGroups)); } public static void ClearProfileGroups(this IAppCache cache) @@ -212,14 +230,14 @@ public static void ClearProfileGroups(this IAppCache cache) #endregion #region UserAgent - public static List GetOrAddUserAgents(this IAppCache cache, Func> userAgentsLoader) + public static List GetOrAddUserAgents(this IAppCache cache, Func> userAgentsLoader, int cacheTimeUserAgents) { - return cache.GetOrAdd(UserAgentsKey, userAgentsLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeUserAgents)); + return cache.GetOrAdd(UserAgentsKey, userAgentsLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeUserAgents)); } - public static Dictionary GetOrAddUserAgentsAndProfiles(this IAppCache cache, Func> userAgentsAndProfilesLoader) + public static Dictionary GetOrAddUserAgentsAndProfiles(this IAppCache cache, Func> userAgentsAndProfilesLoader, int cacheTimeUserAgentsAndProfiles) { - return cache.GetOrAdd(UserAgentsAndProfilesKey, userAgentsAndProfilesLoader, DateTimeOffset.UtcNow.AddSeconds(CacheTimeUserAgentsAndProfiles)); + return cache.GetOrAdd(UserAgentsAndProfilesKey, userAgentsAndProfilesLoader, DateTimeOffset.UtcNow.AddSeconds(cacheTimeUserAgentsAndProfiles)); } public static void ClearUserAgents(this IAppCache cache) diff --git a/CCM.Core/Entities/Call.cs b/CCM.Core/Entities/Call.cs index 565c3900..e28f3b17 100644 --- a/CCM.Core/Entities/Call.cs +++ b/CCM.Core/Entities/Call.cs @@ -32,28 +32,28 @@ namespace CCM.Core.Entities { public class Call : CoreEntityBase { - public string CallId { get; set; } // Id from Kamailio - public string DlgHashId { get; set; } - public string DlgHashEnt { get; set; } - - public Guid FromId { get; set; } - public RegisteredSip From { get; set; } - public string FromSip { get; set; } - public string FromDisplayName { get; set; } - - public Guid ToId { get; set; } - public RegisteredSip To { get; set; } - public string ToSip { get; set; } - public string ToDisplayName { get; set; } - + public string CallId { get; set; } + public string DialogHashId { get; set; } + public string DialogHashEnt { get; set; } public DateTime Started { get; set; } public DateTime Updated { get; set; } - public SipCallState State { get; set; } public bool Closed { get; set; } - public bool IsPhoneCall { get; set; } // True if it's a phone call + public bool IsPhoneCall { get; set; } + public string SDP { get; set; } - public string ToTag { get; set; } // TODO: Doesn't seem to be in use - public string FromTag { get; set; } // TODO: Doesn't seem to be in use + public Guid? FromId { get; set; } + public CallRegisteredCodec From { get; set; } + public string FromSip { get; set; } + public string FromDisplayName { get; set; } + public string FromTag { get; set; } + public string FromCategory { get; set; } + + public Guid? ToId { get; set; } + public CallRegisteredCodec To { get; set; } + public string ToSip { get; set; } + public string ToDisplayName { get; set; } + public string ToTag { get; set; } + public string ToCategory { get; set; } } } diff --git a/CCM.Core/Entities/CallHistory.cs b/CCM.Core/Entities/CallHistory.cs index af20e942..f6f32158 100644 --- a/CCM.Core/Entities/CallHistory.cs +++ b/CCM.Core/Entities/CallHistory.cs @@ -24,22 +24,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; + namespace CCM.Core.Entities { - using System; - public class CallHistory { public Guid CallHistoryId { get; set; } public Guid CallId { get; set; } - public string SipCallId { get; set; } + public string DialogCallId { get; set; } public DateTime Started { get; set; } public DateTime Ended { get; set; } - public string DlgHashId { get; set; } - public string DlgHashEnt { get; set; } - public string ToTag { get; set; } - public string FromTag { get; set; } + public bool IsPhoneCall { get; set; } + public string DialogHashId { get; set; } + public string DialogHashEnt { get; set; } + public Guid FromId { get; set; } + public string FromTag { get; set; } public string FromSip { get; set; } public string FromUsername { get; set; } public string FromDisplayName { get; set; } @@ -48,15 +49,19 @@ public class CallHistory public string FromLocationName { get; set; } public string FromLocationComment { get; set; } public string FromLocationShortName { get; set; } + public string FromLocationCategory { get; set; } public Guid FromCodecTypeId { get; set; } public string FromCodecTypeName { get; set; } public string FromCodecTypeColor { get; set; } + public string FromCodecTypeCategory { get; set; } public Guid FromOwnerId { get; set; } public string FromOwnerName { get; set; } public Guid FromRegionId { get; set; } public string FromRegionName { get; set; } - public string FromUserAgentHead { get; set; } + public string FromUserAgentHeader { get; set; } + public Guid ToId { get; set; } + public string ToTag { get; set; } public string ToSip { get; set; } public string ToUsername { get; set; } public string ToDisplayName { get; set; } @@ -65,14 +70,15 @@ public class CallHistory public string ToLocationName { get; set; } public string ToLocationComment { get; set; } public string ToLocationShortName { get; set; } + public string ToLocationCategory { get; set; } public Guid ToCodecTypeId { get; set; } public string ToCodecTypeName { get; set; } public string ToCodecTypeColor { get; set; } + public string ToCodecTypeCategory { get; set; } public Guid ToOwnerId { get; set; } public string ToOwnerName { get; set; } public Guid ToRegionId { get; set; } public string ToRegionName { get; set; } - public string ToUserAgentHead { get; set; } - public bool IsPhoneCall { get; set; } + public string ToUserAgentHeader { get; set; } } } diff --git a/CCM.Web/Models/ApiExternal/CodecInfo.cs b/CCM.Core/Entities/CallRegisteredCodec.cs similarity index 80% rename from CCM.Web/Models/ApiExternal/CodecInfo.cs rename to CCM.Core/Entities/CallRegisteredCodec.cs index 41fad9ae..90ea403a 100644 --- a/CCM.Web/Models/ApiExternal/CodecInfo.cs +++ b/CCM.Core/Entities/CallRegisteredCodec.cs @@ -24,12 +24,17 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace CCM.Web.Models.ApiExternal +using CCM.Core.Entities.Base; + +namespace CCM.Core.Entities { - public class CodecInfo + public class CallRegisteredCodec : CoreEntityBase { - public string SipAddress { get; set; } + public string SIP { get; set; } + public string UserAgentHead { get; set; } + public string UserName { get; set; } public string DisplayName { get; set; } - public bool InCall { get; set; } + public string PresentationName { get; set; } + public CallRegisteredCodecSipAccount User { get; set; } } } diff --git a/CCM.Web/Models/Profile/GuidSortIndexTuple.cs b/CCM.Core/Entities/CallRegisteredCodecSipAccount.cs similarity index 90% rename from CCM.Web/Models/Profile/GuidSortIndexTuple.cs rename to CCM.Core/Entities/CallRegisteredCodecSipAccount.cs index 8dbe4a2f..f54e3654 100644 --- a/CCM.Web/Models/Profile/GuidSortIndexTuple.cs +++ b/CCM.Core/Entities/CallRegisteredCodecSipAccount.cs @@ -26,11 +26,12 @@ using System; -namespace CCM.Web.Models.Profile +namespace CCM.Core.Entities { - public class GuidSortIndexTuple + public class CallRegisteredCodecSipAccount { public Guid Id { get; set; } - public int SortIndex { get; set; } + public string UserName { get; set; } + public string DisplayName { get; set; } } -} +} \ No newline at end of file diff --git a/CCM.Web/Extensions/EnumDto.cs b/CCM.Core/Entities/Category.cs similarity index 79% rename from CCM.Web/Extensions/EnumDto.cs rename to CCM.Core/Entities/Category.cs index 0e362449..92bd9a9c 100644 --- a/CCM.Web/Extensions/EnumDto.cs +++ b/CCM.Core/Entities/Category.cs @@ -24,26 +24,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using CCM.Core.Helpers; +using System.Collections.Generic; +using CCM.Core.Entities.Base; +using CCM.Core.Interfaces; -namespace CCM.Web.Extensions +namespace CCM.Core.Entities { - public class EnumDto + public class Category : CoreEntityWithTimestamps, ISipFilter { - public int Value { get; set; } public string Name { get; set; } public string Description { get; set; } + public List Locations { get; set; } + public List UserAgents { get; set; } - public static EnumDto Create(Enum e) + public Category() { - return new EnumDto - { - Value = Convert.ToInt32(e), - Name = e.ToString(), - Description = e.DescriptionAsResource() - }; + Locations = new List(); + UserAgents = new List(); } - } } diff --git a/CCM.Core/Entities/CodecType.cs b/CCM.Core/Entities/CodecType.cs index 1d9100fa..e20f1040 100644 --- a/CCM.Core/Entities/CodecType.cs +++ b/CCM.Core/Entities/CodecType.cs @@ -34,7 +34,7 @@ public class CodecType : CoreEntityWithTimestamps, ISipFilter { public string Name { get; set; } public string Color { get; set; } - public List Users { get; set; } + public List Users { get; set; } // TODO: Mode out to specific class public CodecType() { diff --git a/CCM.Core/Entities/Discovery/UserAgentSearchParamsDto.cs b/CCM.Core/Entities/Discovery/UserAgentSearchParamsDto.cs index c67983e8..12435d4e 100644 --- a/CCM.Core/Entities/Discovery/UserAgentSearchParamsDto.cs +++ b/CCM.Core/Entities/Discovery/UserAgentSearchParamsDto.cs @@ -25,14 +25,19 @@ */ using System.Collections.Generic; +using Newtonsoft.Json; namespace CCM.Core.Entities.Discovery { public class UserAgentSearchParamsDto { + [JsonProperty("caller")] public string Caller { get; set; } + [JsonProperty("callee")] public string Callee { get; set; } + [JsonProperty("filters")] public IList> Filters { get; set; } + [JsonProperty("includeCodecsInCall")] public bool IncludeCodecsInCall { get; set; } } } diff --git a/CCM.Core/Entities/DocumentDb/CodecControlApi.cs b/CCM.Core/Entities/DocumentDb/CodecControlApi.cs deleted file mode 100644 index 76d3a686..00000000 --- a/CCM.Core/Entities/DocumentDb/CodecControlApi.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Runtime.Serialization; - -namespace CCM.Core.Entities.DocumentDb -{ - /// - /// Used for JSON Document Db Storage - /// - [DataContract] - public class CodecControlApi : DocumentDbObjectBase - { - [DataMember] public string Name { get; set; } - [DataMember] public string Description { get; set; } - [DataMember] public string DeviceSerial { get; set; } - } -} diff --git a/CCM.Core/Entities/Filter.cs b/CCM.Core/Entities/Filter.cs index b0088a6d..2c95efdb 100644 --- a/CCM.Core/Entities/Filter.cs +++ b/CCM.Core/Entities/Filter.cs @@ -31,8 +31,17 @@ namespace CCM.Core.Entities public class Filter : CoreEntityWithTimestamps { public string Name { get; set; } - public string ColumnName { get; set; } // Property/column name name in db - public string TableName { get; set; } // Type (table) in db - public string FilteringName { get; set; } // Property on cached registered sip object + /// + /// Property/column name name in db + /// + public string ColumnName { get; set; } + /// + /// Type (table) in db + /// + public string TableName { get; set; } + /// + /// Property on cached registered sip object + /// + public string FilteringName { get; set; } } } diff --git a/CCM.Core/Entities/Location.cs b/CCM.Core/Entities/Location.cs index 1b403b0a..dd3e3f62 100644 --- a/CCM.Core/Entities/Location.cs +++ b/CCM.Core/Entities/Location.cs @@ -36,7 +36,10 @@ public class Location : CoreEntityWithTimestamps, ISipFilter public string ShortName { get; set; } public string Comment { get; set; } - public string Net { get; set; } // First IP-address for the network. Together with CIDR it describes a net-span + /// + /// First IP-address for the network. Together with CIDR it describes a net-span + /// + public string Net { get; set; } public byte? Cidr { get; set; } public string Net_v6 { get; set; } @@ -46,6 +49,7 @@ public class Location : CoreEntityWithTimestamps, ISipFilter public City City { get; set; } public ProfileGroup ProfileGroup { get; set; } public Region Region { get; set; } + public Category Category { get; set; } public string ToIpV4String() { return !string.IsNullOrEmpty(Net) ? string.Format("{0} / {1}", Net, Cidr) : string.Empty; } public string ToIpV6String() { return !string.IsNullOrEmpty(Net_v6) ? string.Format("{0} / {1}", Net_v6, Cidr_v6) : string.Empty; } @@ -58,6 +62,5 @@ public byte[] ToIpV4SortString() } return ipAddress.GetAddressBytes(); } - } } diff --git a/CCM.Core/Entities/Profile.cs b/CCM.Core/Entities/ProfileCodec.cs similarity index 91% rename from CCM.Core/Entities/Profile.cs rename to CCM.Core/Entities/ProfileCodec.cs index 5e69df54..97957dc9 100644 --- a/CCM.Core/Entities/Profile.cs +++ b/CCM.Core/Entities/ProfileCodec.cs @@ -29,16 +29,17 @@ namespace CCM.Core.Entities { - public class Profile : CoreEntityWithTimestamps + public class ProfileCodec : CoreEntityWithTimestamps { public string Name { get; set; } public string Description { get; set; } + public string LongDescription { get; set; } public string Sdp { get; set; } public ICollection Groups { get; set; } public List UserAgents { get; set; } - public int SortIndex { get; set; } + public int OrderIndex { get; set; } - public Profile() + public ProfileCodec() { UserAgents = new List(); } diff --git a/CCM.Core/Entities/ProfileGroup.cs b/CCM.Core/Entities/ProfileGroup.cs index 9fe1cfc2..43bba10e 100644 --- a/CCM.Core/Entities/ProfileGroup.cs +++ b/CCM.Core/Entities/ProfileGroup.cs @@ -33,7 +33,7 @@ public class ProfileGroup: CoreEntityWithTimestamps { public ProfileGroup() { - Profiles = new List(); // TODO: This whole class needs some work.. Why this? + Profiles = new List(); // TODO: This whole class needs some work.. Why this? } public string Name { get; set; } @@ -41,6 +41,6 @@ public ProfileGroup() // Decides how valuable this group is compared to other groups public int? GroupSortWeight { get; set; } - public List Profiles { get; set; } + public List Profiles { get; set; } } } diff --git a/CCM.Core/Entities/RegisteredSip.cs b/CCM.Core/Entities/RegisteredSip.cs deleted file mode 100644 index 92bbc63f..00000000 --- a/CCM.Core/Entities/RegisteredSip.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using CCM.Core.Entities.Base; - -namespace CCM.Core.Entities -{ - public class RegisteredSip : CoreEntityBase - { - // Properties from codec message - public string SIP { get; set; } - public string UserAgentHead { get; set; } // User-agent string that the codec is reporting. TODO: Try to rename this? - public string Username { get; set; } - public string DisplayName { get; set; } - public string Registrar { get; set; } - public string IP { get; set; } - public int Port { get; set; } - public int Expires { get; set; } - public long ServerTimeStamp { get; set; } - - // Properties set on server - public DateTime Updated { get; set; } - public Location Location { get; set; } - public SipAccount User { get; set; } - } -} diff --git a/CCM.Core/Entities/RegisteredUserAgent.cs b/CCM.Core/Entities/RegisteredUserAgent.cs index af83811b..4fdbaddf 100644 --- a/CCM.Core/Entities/RegisteredUserAgent.cs +++ b/CCM.Core/Entities/RegisteredUserAgent.cs @@ -36,26 +36,32 @@ public RegisteredUserAgent( string displayName, string location, string locationShortName, + string locationCategory, string image, string codecTypeName, string codecTypeColor, - string username, + string codecTypeCategory, + string userExternalReference, string userDisplayName, string userComment, - string regionName) + string regionName, + string codecApi) { SipUri = sipUri; Id = id; DisplayName = displayName; Location = location; LocationShortName = locationShortName; + LocationCategory = locationCategory; Image = image; CodecTypeName = codecTypeName; CodecTypeColor = codecTypeColor; - Username = username; + CodecTypeCategory = codecTypeCategory; + UserExternalReference = userExternalReference; UserDisplayName = userDisplayName; UserComment = userComment; RegionName = regionName; + CodecApi = codecApi; } public string SipUri { get; } @@ -63,10 +69,13 @@ public RegisteredUserAgent( public string DisplayName { get; } public string Location { get; } public string LocationShortName { get; } + public string LocationCategory { get; } public string Image { get; } public string CodecTypeName { get; } public string CodecTypeColor { get; } - public string Username { get; } + public string CodecTypeCategory { get; } + public string CodecApi { get; } + public string UserExternalReference { get; } public string UserDisplayName { get; } public string UserComment { get; } public string RegionName { get; } diff --git a/CCM.Core/Entities/RegisteredUserAgentAndProfilesDiscovery.cs b/CCM.Core/Entities/RegisteredUserAgentAndProfilesDiscovery.cs index 2879519b..08f55c00 100644 --- a/CCM.Core/Entities/RegisteredUserAgentAndProfilesDiscovery.cs +++ b/CCM.Core/Entities/RegisteredUserAgentAndProfilesDiscovery.cs @@ -40,7 +40,6 @@ public RegisteredUserAgentAndProfilesDiscovery( Guid id, string sipUri, string displayName, - string username, string ipAddress, string userAgentHeader, string userAgentName, @@ -62,7 +61,6 @@ public RegisteredUserAgentAndProfilesDiscovery( Id = id; SipUri = sipUri; DisplayName = displayName; - Username = username; IpAddress = ipAddress; UserAgentHeader = userAgentHeader; UserAgentName = userAgentName; @@ -87,32 +85,24 @@ public RegisteredUserAgentAndProfilesDiscovery( public Guid Id { get; } public string SipUri { get; } public string DisplayName { get; } - public string Username { get; } + //public string Username { get; } // TODO: remove med... + [FilterProperty(TableName = "UserAgents", ColumnName = "Identifier")] public string IpAddress { get; } public string UserAgentHeader { get; } - [FilterProperty(TableName = "UserAgents", ColumnName = "Name")] public string UserAgentName { get; } - [FilterProperty(TableName = "Locations", ColumnName = "Name")] public string LocationName { get; } - [FilterProperty(TableName = "Locations", ColumnName = "ShortName")] public string LocationShortName { get; } - [FilterProperty(TableName = "Regions", ColumnName = "Name")] public string RegionName { get; } - [FilterProperty(TableName = "Cities", ColumnName = "Name")] public string CityName { get; } - public string UserOwnerName { get; } - public string UserDisplayName { get; } - [FilterProperty(TableName = "CodecTypes", ColumnName = "Name")] public string CodecTypeName { get; } - public List> MetaData { get; } // Profiles @@ -124,6 +114,5 @@ public RegisteredUserAgentAndProfilesDiscovery( public string InCallWithId { get; } public string InCallWithSip { get; } public string InCallWithName { get; } - } } diff --git a/CCM.Core/Entities/RegisteredUserAgentCodecInformation.cs b/CCM.Core/Entities/RegisteredUserAgentCodecInformation.cs index 4f90c4ae..4a9afd1a 100644 --- a/CCM.Core/Entities/RegisteredUserAgentCodecInformation.cs +++ b/CCM.Core/Entities/RegisteredUserAgentCodecInformation.cs @@ -32,23 +32,17 @@ public RegisteredUserAgentCodecInformation( string sipAddress, string ip, string api, - string gpoNames, - int nrOfInputs, - int nrOfGpos) + string userAgent) { SipAddress = sipAddress; Ip = ip; Api = api; - GpoNames = gpoNames; - NrOfInputs = nrOfInputs; - NrOfGpos = nrOfGpos; + UserAgent = userAgent; } public string SipAddress { get; } public string Ip { get; } public string Api { get; } - public string GpoNames { get; } - public int NrOfInputs { get; } - public int NrOfGpos { get; } + public string UserAgent { get; } } } diff --git a/CCM.Core/Entities/RegisteredUserAgentDiscovery.cs b/CCM.Core/Entities/RegisteredUserAgentDiscovery.cs index 71e0fbc9..7f874f54 100644 --- a/CCM.Core/Entities/RegisteredUserAgentDiscovery.cs +++ b/CCM.Core/Entities/RegisteredUserAgentDiscovery.cs @@ -42,7 +42,6 @@ public RegisteredUserAgentDiscovery( DateTime updated, string sipUri, string displayName, - string username, string ipAddress, string userAgentHeader, Guid? userAgentId, @@ -62,7 +61,6 @@ List> metaData Updated = updated; SipUri = sipUri; DisplayName = displayName; - Username = username; IpAddress = ipAddress; UserAgentHeader = userAgentHeader; UserAgentId = userAgentId; @@ -77,41 +75,23 @@ List> metaData CodecTypeName = codecTypeName; MetaData = metaData; } - // TODO: This one doesn't need the FilterProperties. Should also change the editor for the filtering + // TODO: Should also change the editor for the filtering public Guid Id { get; } public DateTime Updated { get; } public string SipUri { get; } public string DisplayName { get; } - public string Username { get; } public string IpAddress { get; } public string UserAgentHeader { get; } - public Guid? UserAgentId { get; } - - //[FilterProperty(TableName = "UserAgents", ColumnName = "Name")] public string UserAgentName { get; } - public Guid? LocationId { get; } - - //[FilterProperty(TableName = "Locations", ColumnName = "Name")] public string LocationName { get; } - - //[FilterProperty(TableName = "Locations", ColumnName = "ShortName")] public string LocationShortName { get; } - - //[FilterProperty(TableName = "Regions", ColumnName = "Name")] public string RegionName { get; } - - //[FilterProperty(TableName = "Cities", ColumnName = "Name")] public string CityName { get; } - public string UserOwnerName { get; } - public string UserDisplayName { get; } - - //[FilterProperty(TableName = "CodecTypes", ColumnName = "Name")] public string CodecTypeName { get; } - public List> MetaData { get; } } } diff --git a/CCM.Core/Entities/RegisteredUserAgentMiniInformation.cs b/CCM.Core/Entities/RegisteredUserAgentMiniInformation.cs new file mode 100644 index 00000000..3aeaa383 --- /dev/null +++ b/CCM.Core/Entities/RegisteredUserAgentMiniInformation.cs @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; + +namespace CCM.Core.Entities +{ + public class RegisteredUserAgentMiniInformation + { + public RegisteredUserAgentMiniInformation( + Guid id, + string sip, + int expires, + long serverTimeStamp, + DateTime updated) + { + Id = id; + SIP = sip; + Expires = expires; + ServerTimeStamp = serverTimeStamp; + Updated = updated; + } + + public Guid Id { get; } + public string SIP { get; } + public int Expires { get; } + public long ServerTimeStamp { get; } + public DateTime Updated { get; } + } +} diff --git a/CCM.Core/Entities/Registration/UserAgentInfo.cs b/CCM.Core/Entities/Registration/UserAgentInfo.cs index 206f993f..66ce4cc8 100644 --- a/CCM.Core/Entities/Registration/UserAgentInfo.cs +++ b/CCM.Core/Entities/Registration/UserAgentInfo.cs @@ -38,7 +38,7 @@ public class UserAgentInfo public UserAgentInfo( Guid userAgentId, string identifier, - MatchType matchType) + UserAgentPatternMatchType matchType) { UserAgentId = userAgentId; Identifier = identifier; @@ -47,6 +47,6 @@ public UserAgentInfo( public Guid UserAgentId { get; } public string Identifier { get; } - public MatchType MatchType { get; } + public UserAgentPatternMatchType MatchType { get; } } } diff --git a/CCM.Core/Entities/SipAccount.cs b/CCM.Core/Entities/SipAccount.cs index f95f578f..e80ffbdb 100644 --- a/CCM.Core/Entities/SipAccount.cs +++ b/CCM.Core/Entities/SipAccount.cs @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using CCM.Core.Entities.Base; using CCM.Core.Enums; using CCM.Core.Interfaces; @@ -39,7 +40,13 @@ public class SipAccount : CoreEntityWithTimestamps, ISipFilter public SipAccountType AccountType { get; set; } public bool AccountLocked { get; set; } public string Password { get; set; } + public DateTime? LastUsed { get; set; } + public string LastUserAgent { get; set; } + public string LastKnownAddress { get; set; } + public string ExternalReference { get; set; } public CodecType CodecType { get; set; } public Owner Owner { get; set; } + + public bool IsUnused => LastUsed == null || LastUsed < DateTime.UtcNow.AddDays(-360); } } diff --git a/CCM.Core/Entities/Specific/OldCall.cs b/CCM.Core/Entities/Specific/OldCall.cs index 665e27e9..8f637c2c 100644 --- a/CCM.Core/Entities/Specific/OldCall.cs +++ b/CCM.Core/Entities/Specific/OldCall.cs @@ -28,9 +28,37 @@ namespace CCM.Core.Entities.Specific { - public class OldCall : OnGoingCall + public class OldCall { + public string CallId { get; set; } + public DateTime Started { get; set; } public DateTime Ended { get; set; } public string Duration { get; set; } + public bool IsPhoneCall { get; set; } + public string SDP { get; set; } + + public string FromDisplayName { get; set; } + public string FromSip { get; set; } + public string FromId { get; set; } + public string FromLocationName { get; set; } + public string FromLocationShortName { get; set; } + public string FromLocationCategory { get; set; } + public string FromComment { get; set; } + public string FromRegionName { get; set; } + public string FromCodecTypeName { get; set; } + public string FromCodecTypeColor { get; set; } + public string FromCodecTypeCategory { get; set; } + + public string ToDisplayName { get; set; } + public string ToSip { get; set; } + public string ToId { get; set; } + public string ToLocationName { get; set; } + public string ToLocationShortName { get; set; } + public string ToLocationCategory { get; set; } + public string ToComment { get; set; } + public string ToRegionName { get; set; } + public string ToCodecTypeName { get; set; } + public string ToCodecTypeColor { get; set; } + public string ToCodecTypeCategory { get; set; } } } diff --git a/CCM.Core/Entities/Specific/OnGoingCall.cs b/CCM.Core/Entities/Specific/OnGoingCall.cs index c8b179e9..a5f945a4 100644 --- a/CCM.Core/Entities/Specific/OnGoingCall.cs +++ b/CCM.Core/Entities/Specific/OnGoingCall.cs @@ -33,24 +33,35 @@ public class OnGoingCall public string CallId { get; set; } public DateTime Started { get; set; } public bool IsPhoneCall { get; set; } + public string SDP { get; set; } + public string FromDisplayName { get; set; } public string FromSip { get; set; } public string FromId { get; set; } public string FromLocationName { get; set; } public string FromLocationShortName { get; set; } + public string FromLocationCategory { get; set; } public string FromComment { get; set; } public string FromRegionName { get; set; } public string FromCodecTypeName { get; set; } public string FromCodecTypeColor { get; set; } + public string FromCodecTypeCategory { get; set; } + public string FromCategory { get; set; } + public string FromExternalReference { get; set; } + public string ToDisplayName { get; set; } public string ToSip { get; set; } public string ToId { get; set; } public string ToLocationName { get; set; } public string ToLocationShortName { get; set; } + public string ToLocationCategory { get; set; } public string ToComment { get; set; } public string ToRegionName { get; set; } public string ToCodecTypeName { get; set; } public string ToCodecTypeColor { get; set; } + public string ToCodecTypeCategory { get; set; } + public string ToCategory { get; set; } + public string ToExternalReference { get; set; } public int DurationSeconds => Convert.ToInt32(DateTime.UtcNow.Subtract(Started).TotalSeconds); } diff --git a/CCM.Data/Repositories/LocationInfoRepository.cs b/CCM.Core/Entities/Specific/ProfileFullDetail.cs similarity index 69% rename from CCM.Data/Repositories/LocationInfoRepository.cs rename to CCM.Core/Entities/Specific/ProfileFullDetail.cs index a519a811..04a1f2fd 100644 --- a/CCM.Data/Repositories/LocationInfoRepository.cs +++ b/CCM.Core/Entities/Specific/ProfileFullDetail.cs @@ -24,31 +24,29 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; -using System.Linq; -using CCM.Core.Entities.Specific; -using CCM.Core.Interfaces.Repositories; -using LazyCache; -namespace CCM.Data.Repositories +namespace CCM.Core.Entities.Specific { - // TODO: Maybe move info LocationRepository? - public class LocationInfoRepository : BaseRepository, ILocationInfoRepository + public class ProfileFullDetail { - public LocationInfoRepository(IAppCache cache) : base(cache) + public ProfileFullDetail(Guid id, string name, string description, string longDescription, string sdp, List supportedUserAgents) { + Id = id; + Name = name; + Description = description; + LongDescription = longDescription; + Sdp = sdp; + SupportedUserAgents = supportedUserAgents; } - public List GetAll() - { - using (var db = GetDbContext()) - { - return db.Locations.Select(l => new LocationInfo() - { - Id = l.Id, - Name = l.Name - }).ToList(); - } - } + public Guid Id; + public string Name { get; } + public string Description { get; } + public string LongDescription { get; } + public string Sdp { get; } + + public List SupportedUserAgents { get; } } } diff --git a/CCM.Core/Entities/Specific/RegisteredSipDetails.cs b/CCM.Core/Entities/Specific/RegisteredSipDetails.cs index bf96eed4..1bd0ea2c 100644 --- a/CCM.Core/Entities/Specific/RegisteredSipDetails.cs +++ b/CCM.Core/Entities/Specific/RegisteredSipDetails.cs @@ -25,43 +25,36 @@ */ using System; -using System.Collections.Generic; namespace CCM.Core.Entities.Specific { public class RegisteredSipDetails { public Guid Id { get; set; } + public string Sip { get; set; } public string DisplayName { get; set; } - public string Comment { get; set; } - public bool InCall { get; set; } - public string CallWithName { get; set; } + public string UserDisplayName { get; set; } + public string Ip { get; set; } + public string Api { get; set; } + public string Image { get; set; } + public string Registrar { get; set; } + public string Comment { get; set; } + public string UserExternalReference { get; set; } + + public string UserAgentHeader { get; set; } + public string UserAgentName { get; set; } + public string LocationName { get; set; } public string LocationComment { get; set; } - + public string RegionName { get; set; } public string CityName { get; set; } - - public string Ip { get; set; } - public string Api { get; set; } - public string UserAgentHeader { get; set; } - public string Sip { get; set; } - public string Registrar { get; set; } - public string UserDisplayName { get; set; } + public string UserInterfaceLink { get; set; } public bool UserInterfaceIsOpen { get; set; } public bool UseScrollbars { get; set; } - public string Image { get; set; } - public bool ActiveX { get; set; } public int Width { get; set; } public int Height { get; set; } - public int Inputs { get; set; } - public int NrOfGpos { get; set; } - public int InputMinDb { get; set; } - public int InputMaxDb { get; set; } - public int InputGainStep { get; set; } - public int Lines { get; set; } - public List CodecPresets { get; set; } } } diff --git a/CCM.Core/Enums/MatchType.cs b/CCM.Core/Entities/Statistics/CallEventTypeStatistics.cs similarity index 92% rename from CCM.Core/Enums/MatchType.cs rename to CCM.Core/Entities/Statistics/CallEventTypeStatistics.cs index d1c581b0..511eee29 100644 --- a/CCM.Core/Enums/MatchType.cs +++ b/CCM.Core/Entities/Statistics/CallEventTypeStatistics.cs @@ -24,12 +24,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace CCM.Core.Enums +namespace CCM.Core.Entities.Statistics { - public enum MatchType + public enum CallEventTypeStatistics { - Begins_With = 0, - Contains = 1, - Ends_With = 2 + End = 0, + Start = 1 } -} +} \ No newline at end of file diff --git a/CCM.Core/Entities/Statistics/CategoryBasedStatistics.cs b/CCM.Core/Entities/Statistics/CategoryBasedStatistics.cs new file mode 100644 index 00000000..08e02c84 --- /dev/null +++ b/CCM.Core/Entities/Statistics/CategoryBasedStatistics.cs @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; + +namespace CCM.Core.Entities.Statistics +{ + public class CategoryCallStatistic + { + public int NumberOfCalls { get; set; } = 0; + public string Part1Category { get; set; } = ""; + public string Part2Category { get; set; } = ""; + public List CallTimes { get; set; } = new List(); + public double TotalCallTime { get; set; } = 0; + } + + public class CategoryItemStatistic + { + public int NumberOfCalls { get; set; } = 0; + public string Category { get; set; } = ""; + public List CallTimes { get; set; } = new List(); + public double TotalCallTime { get; set; } = 0; + } +} diff --git a/CCM.Core/Entities/Statistics/DateBasedStatistics.cs b/CCM.Core/Entities/Statistics/DateBasedStatistics.cs index ab84beb5..d1bf31c4 100644 --- a/CCM.Core/Entities/Statistics/DateBasedStatistics.cs +++ b/CCM.Core/Entities/Statistics/DateBasedStatistics.cs @@ -32,16 +32,16 @@ namespace CCM.Core.Entities.Statistics { public class DateBasedStatistics { - public double AverageTime - { - get { return NumberOfCalls == 0 ? 0 : TotaltTimeForCalls/NumberOfCalls; } - } - public DateTime Date { get; set; } + public int NumberOfCalls { get; private set; } public double MaxCallTime { get; private set; } + public string MaxCallTimeView => TimeSpan.FromMinutes(Convert.ToInt32(MaxCallTime)).ToString(@"hh\:mm\:ss"); public double MinCallTime { get; private set; } - public int NumberOfCalls { get; private set; } - public double TotaltTimeForCalls { get; private set; } + public string MinCallTimeView => TimeSpan.FromMinutes(Convert.ToInt32(MinCallTime)).ToString(@"hh\:mm\:ss"); + public double TotalTimeForCalls { get; private set; } + public string TotalTimeForCallsView => TimeSpan.FromMinutes(Convert.ToInt32(TotalTimeForCalls)).ToString(@"hh\:mm"); + public double AverageTime => NumberOfCalls == 0 ? 0 : TotalTimeForCalls / NumberOfCalls; + public string AverageTimeView => TimeSpan.FromMinutes(Convert.ToInt32(AverageTime)).ToString(@"hh\:mm"); public void AddTime(double timeInMinutes) { @@ -59,7 +59,7 @@ public void AddTime(double timeInMinutes) MaxCallTime = timeInMinutes; } - TotaltTimeForCalls += timeInMinutes; + TotalTimeForCalls += timeInMinutes; NumberOfCalls++; } } diff --git a/CCM.Core/Entities/Statistics/HourBasedStatistics.cs b/CCM.Core/Entities/Statistics/HourBasedStatistics.cs index 70796bbd..f9618fe4 100644 --- a/CCM.Core/Entities/Statistics/HourBasedStatistics.cs +++ b/CCM.Core/Entities/Statistics/HourBasedStatistics.cs @@ -77,7 +77,7 @@ public bool AddEvent(HourBasedCallEvent callEvent) if (_maxSimultaneousCallsPerDay.Count < 1) _maxSimultaneousCallsPerDay.Add(0); if (callEvent.EventTime > Date.AddHours(1)) return false; - if (callEvent.EventType == CallEventType.Start) + if (callEvent.EventType == CallEventTypeStatistics.Start) { OngoingCalls++; if (OngoingCalls > _maxSimultaneousCallsPerDay[0]) @@ -148,33 +148,32 @@ public static List Aggregate(IEnumerable GetOrderedEvents(IList callHistories, - Guid locationId) + public static IEnumerable GetOrderedEvents(IList callHistories, Guid locationId) { return GetEvents(callHistories, locationId).OrderBy(e => e.EventTime).ThenBy(e => (int)e.EventType); } - public static IEnumerable GetEvents(IList callHistories, Guid locationId) + private static IEnumerable GetEvents(IList callHistories, Guid locationId) { foreach (var call in callHistories) { if (call.FromLocationId == locationId || call.ToLocationId == locationId) { yield return - Create(CallEventType.Start, call); + Create(CallEventTypeStatistics.Start, call); yield return - Create(CallEventType.End, call); + Create(CallEventTypeStatistics.End, call); } } } - public static HourBasedCallEvent Create(CallEventType eventType, CallHistory call) + private static HourBasedCallEvent Create(CallEventTypeStatistics eventType, CallHistory call) { return new HourBasedCallEvent { - EventTime = eventType == CallEventType.Start ? call.Started : call.Ended, + EventTime = eventType == CallEventTypeStatistics.Start ? call.Started : call.Ended, EventType = eventType, }; } @@ -185,6 +184,7 @@ public class HourBasedStatisticsForLocation public Guid LocationId { get; set; } public string LocationName { get; set; } public IList Statistics { get; set; } + public int MaxCallCount => Statistics.Max(data => data.MaxSimultaneousCalls); public IEnumerable> GetSeries() { diff --git a/CCM.Core/Entities/Statistics/LocationBasedStatistics.cs b/CCM.Core/Entities/Statistics/LocationBasedStatistics.cs index 45174593..200f7685 100644 --- a/CCM.Core/Entities/Statistics/LocationBasedStatistics.cs +++ b/CCM.Core/Entities/Statistics/LocationBasedStatistics.cs @@ -36,7 +36,7 @@ public class LocationBasedStatistics public double AverageTime { - get { return NumberOfCalls == 0 ? 0 : TotaltTimeForCalls/NumberOfCalls; } + get { return NumberOfCalls == 0 ? 0 : TotalTimeForCalls/NumberOfCalls; } } public Guid LocationId { get; set; } @@ -44,7 +44,7 @@ public double AverageTime public double MaxCallTime { get; private set; } public double MinCallTime { get; private set; } public int NumberOfCalls { get; private set; } - public double TotaltTimeForCalls { get; private set; } + public double TotalTimeForCalls { get; private set; } public int MaxSimultaneousCalls { get; private set; } public int OngoingCalls { get; private set; } @@ -58,7 +58,7 @@ public IEnumerable MaxSimultaneousEventDates public void AddEvent(LocationCallEvent callEvent, DateTime reportPeriodStart, DateTime reportPeriodEnd) { - if (callEvent.EventType == CallEventType.Start) + if (callEvent.EventType == CallEventTypeStatistics.Start) { OngoingCalls++; if (OngoingCalls == MaxSimultaneousCalls) @@ -89,52 +89,51 @@ public void AddEvent(LocationCallEvent callEvent, DateTime reportPeriodStart, Da var durationInReportPeriod = ((callEvent.EndTime > reportPeriodEnd ? reportPeriodEnd : callEvent.EndTime) - (callEvent.StartTime < reportPeriodStart ? reportPeriodStart : callEvent.StartTime)).TotalMinutes; - TotaltTimeForCalls += durationInReportPeriod; + TotalTimeForCalls += durationInReportPeriod; } } public class LocationCallEvent { public DateTime EventTime { get; set; } - public CallEventType EventType { get; set; } + public CallEventTypeStatistics EventType { get; set; } public Guid LocationId { get; set; } public string LocationName { get; set; } public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } - public static IEnumerable GetOrderedEvents(IList callHistories, - CallHistoryFilter filter) + public static IEnumerable GetOrderedEvents(IList callHistories, CallHistoryFilter filter) { return GetEvents(callHistories, filter).OrderBy(e => e.EventTime).ThenBy(e => (int)e.EventType); } - public static IEnumerable GetEvents(IList callHistories, CallHistoryFilter filter) + private static IEnumerable GetEvents(IList callHistories, CallHistoryFilter filter) { foreach (var call in callHistories) { if ((call.FromLocationId == call.ToLocationId && filter.IsMatch(call)) || filter.IsFromMatch(call)) { yield return - Create(CallEventType.Start, call, c => Tuple.Create(c.FromLocationId, c.FromLocationName)); + Create(CallEventTypeStatistics.Start, call, c => Tuple.Create(c.FromLocationId, c.FromLocationName)); yield return - Create(CallEventType.End, call, c => Tuple.Create(c.FromLocationId, c.FromLocationName)); + Create(CallEventTypeStatistics.End, call, c => Tuple.Create(c.FromLocationId, c.FromLocationName)); } if (call.FromLocationId != call.ToLocationId && filter.IsToMatch(call)) { yield return - Create(CallEventType.Start, call, c => Tuple.Create(c.ToLocationId, c.ToLocationName)); + Create(CallEventTypeStatistics.Start, call, c => Tuple.Create(c.ToLocationId, c.ToLocationName)); yield return - Create(CallEventType.End, call, c => Tuple.Create(c.ToLocationId, c.ToLocationName)); + Create(CallEventTypeStatistics.End, call, c => Tuple.Create(c.ToLocationId, c.ToLocationName)); } } } - public static LocationCallEvent Create(CallEventType eventType, CallHistory call, Func> locationSelector) + private static LocationCallEvent Create(CallEventTypeStatistics eventType, CallHistory call, Func> locationSelector) { var location = locationSelector(call); return new LocationCallEvent { - EventTime = eventType == CallEventType.Start ? call.Started : call.Ended, + EventTime = eventType == CallEventTypeStatistics.Start ? call.Started : call.Ended, EventType = eventType, EndTime = call.Ended, LocationId = location.Item1, @@ -142,13 +141,6 @@ public static LocationCallEvent Create(CallEventType eventType, CallHistory call StartTime = call.Started }; } - - } - - public enum CallEventType - { - End = 0, - Start = 1 } public class CallHistoryFilter diff --git a/CCM.Core/Entities/Studio.cs b/CCM.Core/Entities/Studio.cs deleted file mode 100644 index 646290a2..00000000 --- a/CCM.Core/Entities/Studio.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using CCM.Core.Entities.Base; - -namespace CCM.Core.Entities -{ - public class Studio : CoreEntityWithTimestamps - { - public string Name { get; set; } - public string CodecSipAddress { get; set; } - public string CameraAddress { get; set; } - public bool CameraActive { get; set; } - public string CameraUsername { get; set; } - public string CameraPassword { get; set; } - public string CameraVideoUrl { get; set; } - public string CameraImageUrl { get; set; } - public string CameraPlayAudioUrl { get; set; } - public string AudioClipNames { get; set; } - public string InfoText { get; set; } - public string MoreInfoUrl { get; set; } - public int NrOfAudioInputs { get; set; } - public string AudioInputNames { get; set; } - public int AudioInputDefaultGain { get; set; } - public int NrOfGpos { get; set; } - public string GpoNames { get; set; } - public int InactivityTimeout { get; set; } - } -} diff --git a/CCM.Core/Entities/UserAgent.cs b/CCM.Core/Entities/UserAgent.cs index b3c09454..dafbf4e4 100644 --- a/CCM.Core/Entities/UserAgent.cs +++ b/CCM.Core/Entities/UserAgent.cs @@ -33,35 +33,26 @@ namespace CCM.Core.Entities { public class UserAgent : CoreEntityWithTimestamps, ISipFilter { - // TODO: XXX Limit the amount of things returned here. Functions don't really need api information. That's mostly codec control - public UserAgent() { - Profiles = new List(); - CodecPresets = new List(); + Profiles = new List(); } public string Name { get; set; } public string Identifier { get; set; } - public MatchType MatchType { get; set; } + public UserAgentPatternMatchType MatchType { get; set; } + public string Api { get; set; } + public Category Category { get; set; } + // TODO: XXX Limit the amount of things returned here. Functions don't really need api information. That's mostly codec control + // Everything below move to separate table public string Image { get; set; } public string UserInterfaceLink { get; set; } - public bool Ax { get; set; } public int Width { get; set; } public int Height { get; set; } public string Comment { get; set; } - public string Api { get; set; } - public int Lines { get; set; } - public int Inputs { get; set; } - public int NrOfGpos { get; set; } - public int InputMinDb { get; set; } - public int InputMaxDb { get; set; } - public int InputGainStep { get; set; } - public string GpoNames { get; set; } public bool UserInterfaceIsOpen { get; set; } public bool UseScrollbars { get; set; } - public List Profiles { get; set; } - public List CodecPresets { get; set; } + public List Profiles { get; set; } } } diff --git a/CCM.Core/Entities/UserAgentAndProfiles.cs b/CCM.Core/Entities/UserAgentAndProfiles.cs index 2fa92365..3fc28ba2 100644 --- a/CCM.Core/Entities/UserAgentAndProfiles.cs +++ b/CCM.Core/Entities/UserAgentAndProfiles.cs @@ -36,25 +36,16 @@ public UserAgentAndProfiles( Guid id, string name, string identifier, - MatchType matchType, + UserAgentPatternMatchType matchType, string imagePath, string userInterfaceLink, - bool activeX, int width, int height, string comment, string apiType, - int connectionLines, - int inputs, - int outputs, - int nrOfGpos, - int inputMinDb, - int inputMaxDb, - int inputGainStep, - string gpoNames, bool userInterfaceIsOpen, bool useScrollbars, - List profiles) + List profiles) { Id = id; Name = name; @@ -62,19 +53,10 @@ public UserAgentAndProfiles( MatchType = matchType; Image = imagePath; UserInterfaceLink = userInterfaceLink; - Ax = activeX; Width = width; Height = height; Comment = comment; Api = apiType; - Lines = connectionLines; - Inputs = inputs; - Outputs = outputs; // TODO: add this - NrOfGpos = nrOfGpos; - InputMinDb = inputMinDb; - InputMaxDb = inputMaxDb; - InputGainStep = inputGainStep; - GpoNames = gpoNames; UserInterfaceIsOpen = userInterfaceIsOpen; UseScrollbars = useScrollbars; Profiles = profiles; @@ -83,24 +65,15 @@ public UserAgentAndProfiles( public Guid Id { get; } public string Name { get; } public string Identifier { get; } - public MatchType MatchType { get; } + public UserAgentPatternMatchType MatchType { get; } public string Image { get; } public string UserInterfaceLink { get; } - public bool Ax { get; } public int Width { get; } public int Height { get; } public string Comment { get; } public string Api { get; } - public int Lines { get; } - public int Inputs { get; } - public int Outputs { get; } // New addition - public int NrOfGpos { get; } - public int InputMinDb { get; } - public int InputMaxDb { get; } - public int InputGainStep { get; } - public string GpoNames { get; } public bool UserInterfaceIsOpen { get; } public bool UseScrollbars { get; } - public List Profiles { get; } + public List Profiles { get; } } } diff --git a/CCM.Core/Enums/Settings.cs b/CCM.Core/Enums/Settings.cs index 24759058..4cd91a57 100644 --- a/CCM.Core/Enums/Settings.cs +++ b/CCM.Core/Enums/Settings.cs @@ -24,15 +24,53 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; + namespace CCM.Core.Enums { public enum SettingsEnum { + [DefaultSetting("Time in seconds before SIP registration is obsolete","120")] MaxRegistrationAge, + [DefaultSetting("The SIP domain", "@domain.sip.com")] // TODO: Is this in use? and really necessary?? SIPDomain, + [DefaultSetting("Number of closed calls to show on startpage", "50")] LatestCallCount, + [DefaultSetting("Codec Control on/off", "true")] CodecControlActive, + [DefaultSetting("Receive Kamailio messages in old '::' string separated format", "false")] UseOldKamailioEvent, - UseSipEvent + [DefaultSetting("Receive Kamailio messages in JSON-format", "true")] + UseSipEvent, + [DefaultSetting("Folder for User-Agent images", "")] + UserAgentImagesFolder, + [DefaultSetting("URL to CCM Discovery service", "http://ccm.discovery.com")] + DiscoveryServiceUrl, + [DefaultSetting("URL to Codec Control service for startpage codec control", "https://codeccontrol.com")] + CodecControlHost, + [DefaultSetting("Username for Codec Control authentication", "")] + CodecControlUserName, + [DefaultSetting("Password for Codec Control authentication", "")] + CodecControlPassword, + [DefaultSetting("Cache time for information that changes more frequently in seconds", "30")] + CacheTimeLiveData, + [DefaultSetting("Cache time for information that is changed less often in seconds", "60")] + CacheTimeConfigData, + } + + [AttributeUsage(AttributeTargets.All)] + public class DefaultSettingAttribute : Attribute + { + protected string DefaultValue { get; set; } + protected string DefaultDescription { get; set; } + + public virtual string Value => DefaultValue; + public virtual string Description => DefaultDescription; + + public DefaultSettingAttribute(string defaultDescription, string defaultValue) + { + DefaultValue = defaultValue; + DefaultDescription = defaultDescription; + } } } diff --git a/CCM.Core/Enums/UserAgentPatternMatchType.cs b/CCM.Core/Enums/UserAgentPatternMatchType.cs new file mode 100644 index 00000000..4f0e15bc --- /dev/null +++ b/CCM.Core/Enums/UserAgentPatternMatchType.cs @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.ComponentModel; + +namespace CCM.Core.Enums +{ + public enum UserAgentPatternMatchType + { + [Description("Begins_With")] Begins_With = 0, + [Description("Contains")] Contains = 1, + [Description("Ends_With")] Ends_With = 2, + [Description("Regular_Expression")] Regular_Expression = 3 + } +} diff --git a/CCM.Core/Helpers/ApplicationBuildInformation.cs b/CCM.Core/Helpers/ApplicationBuildInformation.cs new file mode 100644 index 00000000..54fd4209 --- /dev/null +++ b/CCM.Core/Helpers/ApplicationBuildInformation.cs @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace CCM.Core.Helpers +{ + public class ApplicationBuildInformation + { + public string Name { get; set; } = ""; + public string LogFolder { get; set; } + public string ReleaseDate { get; set; } + public string Version { get; set; } + public string Environment { get; set; } = "Dev"; + public string Server { get; set; } = "localhost"; + } +} \ No newline at end of file diff --git a/CCM.Core/Helpers/ApplicationConstants.cs b/CCM.Core/Helpers/ApplicationConstants.cs deleted file mode 100644 index d0e6a1c1..00000000 --- a/CCM.Core/Helpers/ApplicationConstants.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -namespace CCM.Core.Helpers -{ - public static class Roles - { - public const string Admin = "Admin"; - public const string Remote = "Remote"; - public const string AccountManager = "AccountManager"; - } - - public static class Owners - { - public const string SrOwnerName = "SR"; // TODO: This is way to hardcoded Owners.SrOwnerName - } - - public static class CodecTypes - { - public const string Personliga = "Personliga"; // TODO: This is way to hardcoded CodecTypes.Personliga - } -} diff --git a/CCM.Core/Helpers/ApplicationSettings.cs b/CCM.Core/Helpers/ApplicationSettings.cs deleted file mode 100644 index ea04f448..00000000 --- a/CCM.Core/Helpers/ApplicationSettings.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Configuration; - -namespace CCM.Core.Helpers -{ - public static class ApplicationSettings - { - public static Uri DiscoveryHost => new Uri(ConfigurationManager.AppSettings["DiscoveryHost"]); - public static string DiscoveryLogLevelUrl => new Uri(DiscoveryHost, "api/loglevel").ToString(); - public static int CacheTimeLiveData => Int32.Parse(ConfigurationManager.AppSettings["CacheTimeLiveData"]); - public static int CacheTimeConfigData => Int32.Parse(ConfigurationManager.AppSettings["CacheTimeConfigData"]); - - } -} diff --git a/CCM.Core/Interfaces/Kamailio/IKamailioDataParser.cs b/CCM.Core/Helpers/AuthenticationAccountRoles.cs similarity index 87% rename from CCM.Core/Interfaces/Kamailio/IKamailioDataParser.cs rename to CCM.Core/Helpers/AuthenticationAccountRoles.cs index fbdca473..d27aea7e 100644 --- a/CCM.Core/Interfaces/Kamailio/IKamailioDataParser.cs +++ b/CCM.Core/Helpers/AuthenticationAccountRoles.cs @@ -24,12 +24,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using CCM.Core.SipEvent.Parser; - -namespace CCM.Core.Interfaces.Kamailio +namespace CCM.Core.Helpers { - public interface IKamailioDataParser + public static class Roles { - KamailioData ParseToKamailioData(string message); + public const string Admin = "Admin"; + public const string Remote = "Remote"; + public const string AccountManager = "AccountManager"; } } diff --git a/CCM.Core/Helpers/DisplayNameHelper.cs b/CCM.Core/Helpers/DisplayNameHelper.cs index e4c18d67..4fb7e463 100644 --- a/CCM.Core/Helpers/DisplayNameHelper.cs +++ b/CCM.Core/Helpers/DisplayNameHelper.cs @@ -26,29 +26,96 @@ using System; using CCM.Core.Entities; +using CCM.Core.Entities.Specific; using CCM.Core.Extensions; -using CCM.Core.Properties; namespace CCM.Core.Helpers { + /// + /// TODO: important, all displaynames that is created with this process should be called presentationName instead... + /// Presentationname should be in this order: + /// - Saved user DisplayName + /// - Displayname from the codec/user-agent + /// - Call Displayname from the service because the codec is not registered + /// - Username/SIP-Address as told by the registrar (with our domain removed if there is one) + /// - Call Username from the service because the codec is not registered + /// public class DisplayNameHelper { - public static string GetDisplayName(RegisteredSip registeredSip, string sipDomain) + public static string GetDisplayName(CallRegisteredCodec registeredCodec, string callDisplayName, string callUserName, string sipDomain) { - return GetDisplayName(registeredSip.DisplayName, registeredSip.User != null ? registeredSip.User.DisplayName : string.Empty, string.Empty, registeredSip.Username, registeredSip.SIP, "", sipDomain); + return GetDisplayName( + registeredCodec?.User?.DisplayName ?? string.Empty, + registeredCodec?.DisplayName ?? string.Empty, + callDisplayName, + registeredCodec?.SIP ?? string.Empty, + callUserName, + string.Empty, + sipDomain); } - //public static string GetDisplayName(RegisteredSipDto registeredSip, string sipDomain) - //{ - // return GetDisplayName(registeredSip.DisplayName, registeredSip.UserDisplayName, string.Empty, registeredSip.UserName, registeredSip.Sip, "", sipDomain); - //} + public static string GetDisplayName(RegisteredSipDetails registeredSip, string sipDomain) + { + return GetDisplayName( + registeredSip.UserDisplayName, + registeredSip.DisplayName, + string.Empty, + registeredSip.Sip, + string.Empty, + string.Empty, + sipDomain); + } + + public static string GetDisplayName(RegisteredUserAgent registeredUserAgent, string sipDomain) + { + return GetDisplayName( + registeredUserAgent.UserDisplayName, + registeredUserAgent.DisplayName, + string.Empty, + registeredUserAgent.SipUri, + string.Empty, + string.Empty, + sipDomain); + } + + public static string GetDisplayName(SipAccount sipAccount, string sipDomain) + { + return GetDisplayName( + sipAccount.DisplayName, + string.Empty, + string.Empty, + sipAccount.UserName, + string.Empty, + string.Empty, + sipDomain); + } - public static string GetDisplayName(string primaryDisplayName, string secondaryDisplayName, string tertiaryDisplayName, string primaryUserName, string secondaryUserName, string tertiaryUserName, - string homeDomain, string defaultDisplayName = "") + public static string GetDisplayName(RegisteredUserAgentDiscovery registeredUserAgentDiscovery, string sipDomain) + { + return GetDisplayName( + registeredUserAgentDiscovery.UserDisplayName, + registeredUserAgentDiscovery.DisplayName, + string.Empty, + registeredUserAgentDiscovery.SipUri, + string.Empty, + string.Empty, + sipDomain); + } + + // TODO: make general but better... + public static string GetDisplayName( + string primaryDisplayName, + string secondaryDisplayName, + string tertiaryDisplayName, + string primaryUserName, + string secondaryUserName, + string tertiaryUserName, + string homeDomain, + string defaultDisplayName = "") { if (!string.IsNullOrWhiteSpace(primaryDisplayName)) { return primaryDisplayName; } if (!string.IsNullOrWhiteSpace(secondaryDisplayName)) { return secondaryDisplayName; } - if (!string.IsNullOrEmpty(tertiaryDisplayName)) { return tertiaryDisplayName; } + if (!string.IsNullOrWhiteSpace(tertiaryDisplayName)) { return tertiaryDisplayName; } if (!string.IsNullOrEmpty(primaryUserName)) { return GetUserNameWithoutHomeDomain(primaryUserName, homeDomain); } if (!string.IsNullOrEmpty(secondaryUserName)) { return GetUserNameWithoutHomeDomain(secondaryUserName, homeDomain); } @@ -59,7 +126,7 @@ public static string GetDisplayName(string primaryDisplayName, string secondaryD private static string GetUserNameWithoutHomeDomain(string userName, string homeDomain) { - var domainIndex = userName.IndexOf(string.Format("@{0}", homeDomain), StringComparison.CurrentCulture); + var domainIndex = userName.IndexOf($"@{homeDomain}", StringComparison.CurrentCulture); if (domainIndex > 0) { return userName.Remove(domainIndex); @@ -75,19 +142,17 @@ public static string AnonymizePhonenumber(string s) } s = s.Trim(); - var username = s.LeftOf("@"); - + // Phone number if (username.IsNumeric()) { - // Phone number if (username.Length <= 6) { // Internal short phone number - return username; + return s; } - return Resources.External_Phone_Number; + return Resources.Resources.External_Phone_Number; } return s; } @@ -100,20 +165,16 @@ public static string AnonymizeDisplayName(string s) } s = s.Trim(); - var username = s.LeftOf("@"); - + // Phone number if (username.IsNumeric()) { - // Phone number if (username.Length <= 6) { // Internal short phone number - return string.Format("Ank {0}", username); - // TODO: Resourcify so that it becomes international + return $"{Resources.Resources.Internal_Phone_Connection_Prefix} {username}"; } - - return Resources.External_Phone_Number; + return Resources.Resources.External_Phone_Number; } return s; } diff --git a/CCM.Core/Helpers/EnumHelper.cs b/CCM.Core/Helpers/EnumHelper.cs index fbed3256..2a021bd8 100644 --- a/CCM.Core/Helpers/EnumHelper.cs +++ b/CCM.Core/Helpers/EnumHelper.cs @@ -24,16 +24,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using Microsoft.Extensions.Localization; using System; +using System.Collections.Generic; using System.ComponentModel; +using System.Reflection; using System.Resources; -using CCM.Core.Properties; +using CCM.Core.Enums; namespace CCM.Core.Helpers { public static class EnumHelper { - private static ResourceManager coreResourceManager = new ResourceManager(typeof(Resources)); + // Tobias tillgg: Denna smller inte men frgan r vad som ska hnda. + private static ResourceManager coreResourceManager = new ResourceManager("CCM.Core.Resources.Resources", Assembly.GetExecutingAssembly()); + + //private static ResourceManager coreResourceManager = new ResourceManager("Resources.resx", Assembly.GetExecutingAssembly()); + //private static ResourceManager coreResourceManager = new ResourceManager(typeof(Resources)); public static string DescriptionAsResource(this Enum enumValue) { @@ -48,12 +55,25 @@ public static string DescriptionAsResource(this Enum enumValue) return coreResourceManager.GetString(((DescriptionAttribute)attributes[0]).Description) ?? string.Format($"Update your resource file with resource key in '{enumType.ToString()}'."); } - public static string Description(this Enum enumValue) + //public static string DefaultDescription(this Enum enumValue) + //{ + // var enumType = enumValue.GetType(); + // var field = enumType.GetField(enumValue.ToString()); + // var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false); + // return attributes.Length == 0 ? enumValue.ToString() : ((DescriptionAttribute)attributes[0]).Description; + //} + + public static (string, string) DefaultValue(this Enum enumValue) { var enumType = enumValue.GetType(); var field = enumType.GetField(enumValue.ToString()); - var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false); - return attributes.Length == 0 ? enumValue.ToString() : ((DescriptionAttribute)attributes[0]).Description; + var attributes = field.GetCustomAttributes(typeof(DefaultSettingAttribute), false); + + if (attributes.Length == 0) + { + return (enumValue.ToString(), "Unknown description"); + } + return (((DefaultSettingAttribute) attributes[0]).Value, ((DefaultSettingAttribute)attributes[0]).Description); } } } diff --git a/CCM.Core/Helpers/GuidHelper.cs b/CCM.Core/Helpers/GuidHelper.cs index dca6daad..f9647f55 100644 --- a/CCM.Core/Helpers/GuidHelper.cs +++ b/CCM.Core/Helpers/GuidHelper.cs @@ -30,6 +30,9 @@ namespace CCM.Core.Helpers { public static class GuidHelper { - public static string GuidString(Guid? guid) { return guid == null || guid == Guid.Empty ? String.Empty : guid.ToString(); } + public static string AsString(Guid? guid) + { + return guid == null || guid == Guid.Empty ? String.Empty : guid.ToString(); + } } } diff --git a/CCM.Core/Helpers/HttpService.cs b/CCM.Core/Helpers/HttpService.cs deleted file mode 100644 index a66d304d..00000000 --- a/CCM.Core/Helpers/HttpService.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; -using NLog; - -namespace CCM.Core.Helpers -{ - // TODO: Remove me if im not in use - //public class HttpService - //{ - // protected static readonly Logger Log = LogManager.GetCurrentClassLogger(); - - // public static async Task GetAsync(Uri url) where T : class - // { - // using (var client = new HttpClient()) - // { - // var response = await client.GetAsync(url); - - // if (!response.IsSuccessStatusCode) - // { - // Log.Warn("Request to {0} failed.", url); - // return null; - // } - // string jsonString = await response.Content.ReadAsStringAsync(); - // return JsonConvert.DeserializeObject(jsonString); - // } - // } - - // public static async Task PostJsonAsync(Uri url, object data = null) - // { - // using (var client = new HttpClient()) - // { - // try - // { - // HttpContent content = null; - // if (data != null) - // { - // var s = JsonConvert.SerializeObject(data); - // content = new StringContent(s, Encoding.UTF8, "application/json"); - // } - // return await client.PostAsync(url, content); - // } - // catch (Exception) - // { - // return new HttpResponseMessage { StatusCode = HttpStatusCode.NotFound }; - // } - // } - // } - - //} -} diff --git a/CCM.Core/Helpers/TimeMeasurer.cs b/CCM.Core/Helpers/TimeMeasurer.cs index 1e884f9d..87da7aa6 100644 --- a/CCM.Core/Helpers/TimeMeasurer.cs +++ b/CCM.Core/Helpers/TimeMeasurer.cs @@ -1,110 +1,110 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Diagnostics; -using System.Linq; -using NLog; -using NLog.Config; - -namespace CCM.Core.Helpers -{ - public class TimeMeasurer : IDisposable - { - protected static readonly Logger LogSystem = LogManager.GetCurrentClassLogger(); - private readonly LogLevel _level; - private readonly Stopwatch _stopwatch; - private readonly string _message; - private readonly bool _isEnabled; - - public TimeMeasurer(string message, bool logStartMessage = false, LogLevel level = null) - { - _level = level ?? LogLevel.Debug; - - LoggingRule rule = LogManager.Configuration.LoggingRules.FirstOrDefault(); - _isEnabled = rule != null && rule.IsLoggingEnabledForLevel(_level); - - if (_isEnabled) - { - _message = message; - - if (logStartMessage) - { - string s = string.Format("BEGIN:{0}", _message); - Log(s); - } - - _stopwatch = new Stopwatch(); - _stopwatch.Start(); - } - } - - private void Log(string s) - { - LogSystem.Log(_level, s); - - if (_level <= LogLevel.Debug) - { - Debug.WriteLine(s); - } - } - - public TimeSpan ElapsedTime - { - get - { - return _isEnabled ? _stopwatch.Elapsed : TimeSpan.Zero; - } - } - - public void Dispose() - { - - Dispose(true); - // Use SupressFinalize in case a subclass - // of this type implements a finalizer. - GC.SuppressFinalize(this); - } - - // The bulk of the clean-up code is implemented in Dispose(bool) - protected virtual void Dispose(bool disposing) - { - if (_isEnabled) - { - _stopwatch.Stop(); - TimeSpan runTime = _stopwatch.Elapsed; - - string runTimeString = runTime.TotalSeconds > 1 - ? string.Format("{0} s", runTime.TotalSeconds) - : string.Format("{0} ms", runTime.TotalMilliseconds); - - var formattedString = string.Format("END:{0} [{1}]", _message, runTimeString); - Log(formattedString); - } - - } - } -} +///* +// * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden +// * +// * Redistribution and use in source and binary forms, with or without +// * modification, are permitted provided that the following conditions +// * are met: +// * 1. Redistributions of source code must retain the above copyright +// * notice, this list of conditions and the following disclaimer. +// * 2. Redistributions in binary form must reproduce the above copyright +// * notice, this list of conditions and the following disclaimer in the +// * documentation and/or other materials provided with the distribution. +// * 3. The name of the author may not be used to endorse or promote products +// * derived from this software without specific prior written permission. +// * +// * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +// * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +// * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +// * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// */ + +//using System; +//using System.Diagnostics; +//using System.Linq; +//using NLog; +//using NLog.Config; + +//namespace CCM.Core.Helpers +//{ +// public class TimeMeasurer : IDisposable +// { +// protected static readonly Logger LogSystem = LogManager.GetCurrentClassLogger(); +// private readonly LogLevel _level; +// private readonly Stopwatch _stopwatch; +// private readonly string _message; +// private readonly bool _isEnabled; + +// public TimeMeasurer(string message, bool logStartMessage = false, LogLevel level = null) +// { +// _level = level ?? LogLevel.Debug; + +// LoggingRule rule = LogManager.Configuration.LoggingRules.FirstOrDefault(); +// _isEnabled = rule != null && rule.IsLoggingEnabledForLevel(_level); + +// if (_isEnabled) +// { +// _message = message; + +// if (logStartMessage) +// { +// string s = string.Format("BEGIN:{0}", _message); +// Log(s); +// } + +// _stopwatch = new Stopwatch(); +// _stopwatch.Start(); +// } +// } + +// private void Log(string s) +// { +// LogSystem.Log(_level, s); + +// if (_level <= LogLevel.Debug) +// { +// Debug.WriteLine(s); +// } +// } + +// public TimeSpan ElapsedTime +// { +// get +// { +// return _isEnabled ? _stopwatch.Elapsed : TimeSpan.Zero; +// } +// } + +// public void Dispose() +// { + +// Dispose(true); +// // Use SupressFinalize in case a subclass +// // of this type implements a finalizer. +// GC.SuppressFinalize(this); +// } + +// // The bulk of the clean-up code is implemented in Dispose(bool) +// protected virtual void Dispose(bool disposing) +// { +// if (_isEnabled) +// { +// _stopwatch.Stop(); +// TimeSpan runTime = _stopwatch.Elapsed; + +// string runTimeString = runTime.TotalSeconds > 1 +// ? string.Format("{0} s", runTime.TotalSeconds) +// : string.Format("{0} ms", runTime.TotalMilliseconds); + +// var formattedString = string.Format("END:{0} [{1}]", _message, runTimeString); +// Log(formattedString); +// } + +// } +// } +//} diff --git a/CCM.Core/Interfaces/IDiscoveryService.cs b/CCM.Core/Interfaces/IDiscoveryServiceManager.cs similarity index 97% rename from CCM.Core/Interfaces/IDiscoveryService.cs rename to CCM.Core/Interfaces/IDiscoveryServiceManager.cs index 7b603ef8..c205ed99 100644 --- a/CCM.Core/Interfaces/IDiscoveryService.cs +++ b/CCM.Core/Interfaces/IDiscoveryServiceManager.cs @@ -29,7 +29,7 @@ namespace CCM.Core.Interfaces { - public interface IDiscoveryService + public interface IDiscoveryServiceManager { UserAgentsResultDto GetUserAgents(string caller, string callee, IList> filters, bool includeCodecsInCall = false); List GetProfiles(); diff --git a/CCM.Core/Interfaces/Managers/IExternalStoreMessageManager.cs b/CCM.Core/Interfaces/Managers/IExternalStoreMessageManager.cs new file mode 100644 index 00000000..29f7f452 --- /dev/null +++ b/CCM.Core/Interfaces/Managers/IExternalStoreMessageManager.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using CCM.Core.SipEvent; +using CCM.Core.SipEvent.Messages; +using CCM.Core.SipEvent.Models; + +namespace CCM.Core.Interfaces.Managers +{ + public interface IExternalStoreMessageManager + { + SipEventHandlerResult HandleDialog(ExternalDialogMessage dialogMessage); + } +} diff --git a/CCM.Core/Interfaces/Managers/IRegisteredSipsManager.cs b/CCM.Core/Interfaces/Managers/IRegisteredCodecsManager.cs similarity index 97% rename from CCM.Core/Interfaces/Managers/IRegisteredSipsManager.cs rename to CCM.Core/Interfaces/Managers/IRegisteredCodecsManager.cs index 6073a15b..9a3c5e4a 100644 --- a/CCM.Core/Interfaces/Managers/IRegisteredSipsManager.cs +++ b/CCM.Core/Interfaces/Managers/IRegisteredCodecsManager.cs @@ -29,7 +29,7 @@ namespace CCM.Core.Interfaces.Managers { - public interface IRegisteredSipsManager + public interface IRegisteredCodecsManager { IEnumerable GetRegisteredUserAgentsAndProfiles(); } diff --git a/CCM.Core/Interfaces/Managers/ISettingsManager.cs b/CCM.Core/Interfaces/Managers/ISettingsManager.cs index 30432681..d3d5d119 100644 --- a/CCM.Core/Interfaces/Managers/ISettingsManager.cs +++ b/CCM.Core/Interfaces/Managers/ISettingsManager.cs @@ -40,5 +40,12 @@ public interface ISettingsManager bool CodecControlActive { get; } bool UseOldKamailioEvent { get; } bool UseSipEvent { get; } + string UserAgentImagesFolder { get; } + string DiscoveryServiceUrl { get; } + string CodecControlHost { get; } + string CodecControlUserName { get; } + string CodecControlPassword { get; } + int CacheTimeLiveData { get; } + int CacheTimeConfigData { get; } } } diff --git a/CCM.Core/Interfaces/Managers/ISipAccountManager.cs b/CCM.Core/Interfaces/Managers/ISipAccountManager.cs deleted file mode 100644 index 3471eaec..00000000 --- a/CCM.Core/Interfaces/Managers/ISipAccountManager.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using CCM.Core.Entities; - -namespace CCM.Core.Interfaces.Managers -{ - public interface ISipAccountManager - { - SipAccount GetById(Guid userId); - SipAccount GetByUserName(string userName); - SipAccount GetByRegisteredSip(Guid registeredSipId); - SipAccount GetSipAccountByUserName(string username); - List GetAll(); - List Find(string startsWith); - void Create(SipAccount account); - void Update(SipAccount account); - void UpdatePassword(Guid id, string password); - void UpdateComment(Guid id, string comment); - bool Delete(Guid id); - } -} diff --git a/CCM.Core/Interfaces/Managers/ISipMessageManager.cs b/CCM.Core/Interfaces/Managers/ISipMessageManager.cs index 0d34f9d4..9708092b 100644 --- a/CCM.Core/Interfaces/Managers/ISipMessageManager.cs +++ b/CCM.Core/Interfaces/Managers/ISipMessageManager.cs @@ -26,6 +26,7 @@ using CCM.Core.SipEvent; using CCM.Core.SipEvent.Messages; +using CCM.Core.SipEvent.Models; namespace CCM.Core.Interfaces.Managers { diff --git a/CCM.Core/Interfaces/Managers/IStatisticsManager.cs b/CCM.Core/Interfaces/Managers/IStatisticsManager.cs index ff0dc70a..aaca9af5 100644 --- a/CCM.Core/Interfaces/Managers/IStatisticsManager.cs +++ b/CCM.Core/Interfaces/Managers/IStatisticsManager.cs @@ -34,14 +34,19 @@ namespace CCM.Core.Interfaces.Managers public interface IStatisticsManager { List GetCodecTypes(); - List GetLocationStatistics(DateTime startTime, DateTime endTime, Guid regionId, Guid ownerId, Guid codecTypeId); List GetOwners(); List GetRegions(); - List GetRegionStatistics(DateTime startDate, DateTime endDate, Guid regionId); - List GetSipUsers(); - List GetSipStatistics(DateTime startDate, DateTime endDate, Guid userId); - IList GetCodecTypeStatistics(DateTime startDate, DateTime endDate, Guid codecTypeId); + List GetSipAccounts(); IList GetLocationsForRegion(Guid regionId); - HourBasedStatisticsForLocation GetHourStatisticsForLocation(DateTime startTime, DateTime endTime, Guid locationId, bool noAggregation); + + List GetLocationStatistics(DateTime startDate, DateTime endDate, Guid regionId, Guid ownerId, Guid codecTypeId); + HourBasedStatisticsForLocation GetHourStatisticsForLocation(DateTime startDate, DateTime endDate, Guid locationId, bool noAggregation); + + IList GetRegionStatistics(DateTime startDate, DateTime endDate, Guid regionId); + IList GetSipAccountStatistics(DateTime startDate, DateTime endDate, Guid userId); + IList GetCodecTypeStatistics(DateTime startDate, DateTime endDate, Guid codecTypeId); + + IList GetCategoryCallStatistics(DateTime startDate, DateTime endDate); + IList GetCategoryStatistics(DateTime startDate, DateTime endDate); } } diff --git a/CCM.Core/Interfaces/Kamailio/IKamailioMessageParser.cs b/CCM.Core/Interfaces/Parser/IKamailioEventParser.cs similarity index 94% rename from CCM.Core/Interfaces/Kamailio/IKamailioMessageParser.cs rename to CCM.Core/Interfaces/Parser/IKamailioEventParser.cs index ea00025b..5ef3c91c 100644 --- a/CCM.Core/Interfaces/Kamailio/IKamailioMessageParser.cs +++ b/CCM.Core/Interfaces/Parser/IKamailioEventParser.cs @@ -26,9 +26,9 @@ using CCM.Core.SipEvent.Messages; -namespace CCM.Core.Interfaces.Kamailio +namespace CCM.Core.Interfaces.Parser { - public interface IKamailioMessageParser + public interface IKamailioEventParser { SipMessageBase Parse(string message); } diff --git a/CCM.Core/Interfaces/Kamailio/ISipEventParser.cs b/CCM.Core/Interfaces/Parser/ISipEventParser.cs similarity index 92% rename from CCM.Core/Interfaces/Kamailio/ISipEventParser.cs rename to CCM.Core/Interfaces/Parser/ISipEventParser.cs index d535671c..123b2fb7 100644 --- a/CCM.Core/Interfaces/Kamailio/ISipEventParser.cs +++ b/CCM.Core/Interfaces/Parser/ISipEventParser.cs @@ -24,13 +24,13 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using CCM.Core.SipEvent; +using CCM.Core.SipEvent.Event; using CCM.Core.SipEvent.Messages; -namespace CCM.Core.Interfaces.Kamailio +namespace CCM.Core.Interfaces.Parser { public interface ISipEventParser { - SipMessageBase Parse(KamailioSipEvent sipEvent); + SipMessageBase Parse(KamailioSipEventData sipEventData); } } \ No newline at end of file diff --git a/CCM.Core/Interfaces/Repositories/ICallHistoryRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedCallHistoryRepository.cs similarity index 57% rename from CCM.Core/Interfaces/Repositories/ICallHistoryRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedCallHistoryRepository.cs index 09d91846..d80f6c67 100644 --- a/CCM.Core/Interfaces/Repositories/ICallHistoryRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedCallHistoryRepository.cs @@ -31,17 +31,43 @@ namespace CCM.Core.Interfaces.Repositories { - public interface ICallHistoryRepository + public interface ICachedCallHistoryRepository { bool Save(CallHistory callHistory); CallHistory GetById(Guid id); CallHistory GetCallHistoryByCallId(Guid callId); - IList GetOldCalls(int callCount, bool anonymize); - IList GetOldCallsFiltered(string region, string codecType, string sipAddress, string searchString, bool anonymize, bool onlyPhoneCalls, int callCount); + IList GetOldCalls(int callCount); + IList GetOldCallsFiltered(string region, string codecType, string sipAddress, string searchString, bool onlyPhoneCalls, int callCount, bool limitByMonth); + + IList GetCallHistoriesByDate(DateTime startDate, DateTime endDate); + IList GetCallHistoriesForRegion(DateTime startDate, DateTime endDate, Guid regionId); + IList GetCallHistoriesForRegisteredSip(DateTime startDate, DateTime endDate, string sipId); + IList GetCallHistoriesForCodecType(DateTime startDate, DateTime endDate, Guid codecTypeId); + IList GetCallHistoriesForLocation(DateTime startDate, DateTime endDate, Guid locationId); + } + + public interface ICallHistoryRepository + { + bool Save(CallHistory callHistory); + CallHistory GetById(Guid id); + IReadOnlyCollection GetOneMonthOldCalls(); + IReadOnlyCollection GetOneMonthCallHistories(); + + IReadOnlyList GetOneYearCallHistory(); + IList GetCallHistoriesByDate(DateTime startTime, DateTime endTime); + IList GetCallHistoriesByDate(IReadOnlyList callHistories, DateTime startTime, DateTime endTime); + IList GetCallHistoriesForRegion(DateTime startDate, DateTime endDate, Guid regionId); + IList GetCallHistoriesForRegion(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, Guid regionId); + IList GetCallHistoriesForRegisteredSip(DateTime startDate, DateTime endDate, string sipId); + IList GetCallHistoriesForRegisteredSip(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, string sipId); + IList GetCallHistoriesForCodecType(DateTime startDate, DateTime endDate, Guid codecTypeId); + IList GetCallHistoriesForCodecType(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, Guid codecTypeId); + IList GetCallHistoriesForLocation(DateTime startDate, DateTime endDate, Guid locationId); + IList GetCallHistoriesForLocation(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, Guid locationId); } } diff --git a/CCM.Core/Interfaces/Repositories/ICallRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedCallRepository.cs similarity index 78% rename from CCM.Core/Interfaces/Repositories/ICallRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedCallRepository.cs index e4ec5a44..258006c0 100644 --- a/CCM.Core/Interfaces/Repositories/ICallRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedCallRepository.cs @@ -31,9 +31,22 @@ namespace CCM.Core.Interfaces.Repositories { + public interface ICachedCallRepository + { + IReadOnlyCollection GetOngoingCalls(bool anonymize); + OnGoingCall GetOngoingCallById(Guid callId); + bool CallExists(string callId, string hashId, string hashEnt); + void UpdateCall(Call call); + void CloseCall(Guid callId); + Call GetCallBySipAddress(string sipAddress); + CallInfo GetCallInfo(string callId, string hashId, string hashEnt); + CallInfo GetCallInfoById(Guid callId); + } + public interface ICallRepository { IReadOnlyCollection GetOngoingCalls(bool anonymize); + OnGoingCall GetOngoingCallById(Guid callId); bool CallExists(string callId, string hashId, string hashEnt); void UpdateCall(Call call); void CloseCall(Guid callId); diff --git a/CCM.Core/Interfaces/Repositories/ILocationRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedLocationRepository.cs similarity index 83% rename from CCM.Core/Interfaces/Repositories/ILocationRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedLocationRepository.cs index c2354616..8cc9eecb 100644 --- a/CCM.Core/Interfaces/Repositories/ILocationRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedLocationRepository.cs @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; +using System; using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.Entities.Specific; @@ -32,10 +32,19 @@ namespace CCM.Core.Interfaces.Repositories { + public interface ICachedLocationRepository : IRepository + { + List FindLocations(string searchString); + List GetAllLocationNetworks(); + Dictionary GetLocationsAndProfiles(); + List GetAllLocationInfo(); + } + public interface ILocationRepository : IRepository { List FindLocations(string searchString); List GetAllLocationNetworks(); Dictionary GetLocationsAndProfiles(); + List GetAllLocationInfo(); } } diff --git a/CCM.Core/Interfaces/Repositories/IProfileGroupRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedProfileGroupRepository.cs similarity index 88% rename from CCM.Core/Interfaces/Repositories/IProfileGroupRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedProfileGroupRepository.cs index 9eca65c9..ad82ca26 100644 --- a/CCM.Core/Interfaces/Repositories/IProfileGroupRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedProfileGroupRepository.cs @@ -31,8 +31,13 @@ namespace CCM.Core.Interfaces.Repositories { + public interface ICachedProfileGroupRepository : IRepository + { + List FindProfileGroups(string search); + } + public interface IProfileGroupRepository : IRepository { - void SetProfileGroupSortWeight(IList> profileGroupTuples); + List FindProfileGroups(string search); } } diff --git a/CCM.Core/Interfaces/Repositories/IProfileRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedProfileRepository.cs similarity index 77% rename from CCM.Core/Interfaces/Repositories/IProfileRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedProfileRepository.cs index fb41fb5b..78d90897 100644 --- a/CCM.Core/Interfaces/Repositories/IProfileRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedProfileRepository.cs @@ -24,7 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.Entities.Specific; @@ -32,11 +31,19 @@ namespace CCM.Core.Interfaces.Repositories { - public interface IProfileRepository : IRepository + public interface ICachedProfileRepository : IRepository { - List FindProfiles(string searchString); + List FindProfiles(string searchString); IList GetAllProfileNamesAndSdp(); IList GetAllProfileInfos(); - void SetProfileSortIndex(IList> profileTuples); + IReadOnlyCollection GetFullDetails(); + } + + public interface IProfileRepository : IRepository + { + List FindProfiles(string searchString); + IList GetAllProfileNamesAndSdp(); + IList GetAllProfileInfos(); + IReadOnlyCollection GetFullDetails(); } } diff --git a/CCM.Core/Interfaces/Repositories/IRegisteredSipRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedRegisteredCodecRepository.cs similarity index 73% rename from CCM.Core/Interfaces/Repositories/IRegisteredSipRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedRegisteredCodecRepository.cs index 9bf9d027..4bf601df 100644 --- a/CCM.Core/Interfaces/Repositories/IRegisteredSipRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedRegisteredCodecRepository.cs @@ -27,15 +27,27 @@ using System.Collections.Generic; using CCM.Core.Entities; using CCM.Core.SipEvent; +using CCM.Core.SipEvent.Models; namespace CCM.Core.Interfaces.Repositories { - public interface IRegisteredSipRepository + public interface ICachedRegisteredCodecRepository { SipEventHandlerResult UpdateRegisteredSip(UserAgentRegistration registration); IEnumerable GetRegisteredUserAgentsDiscovery(); IEnumerable GetRegisteredUserAgents(); SipEventHandlerResult DeleteRegisteredSip(string sipAddress); IEnumerable GetRegisteredUserAgentsCodecInformation(); + IEnumerable GetRegisteredCodecsUpdateTimes(); + } + + public interface IRegisteredCodecRepository + { + SipEventHandlerResult UpdateRegisteredSip(UserAgentRegistration registration); + IEnumerable GetRegisteredUserAgentsDiscovery(); + IEnumerable GetRegisteredUserAgents(); + SipEventHandlerResult DeleteRegisteredSip(string sipAddress); + IEnumerable GetRegisteredUserAgentsCodecInformation(); + IEnumerable GetRegisteredCodecsUpdateTimes(); } } diff --git a/CCM.Core/Interfaces/Repositories/ISettingsRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedSettingsRepository.cs similarity index 91% rename from CCM.Core/Interfaces/Repositories/ISettingsRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedSettingsRepository.cs index 06b841a9..2ef31ed8 100644 --- a/CCM.Core/Interfaces/Repositories/ISettingsRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedSettingsRepository.cs @@ -29,6 +29,12 @@ namespace CCM.Core.Interfaces.Repositories { + public interface ICachedSettingsRepository + { + List GetAll(); + void Save(List settings, string userName); + } + public interface ISettingsRepository { List GetAll(); diff --git a/CCM.Core/Interfaces/Repositories/ISipAccountRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedSipAccountRepository.cs similarity index 69% rename from CCM.Core/Interfaces/Repositories/ISipAccountRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedSipAccountRepository.cs index 6bed64d2..01a10702 100644 --- a/CCM.Core/Interfaces/Repositories/ISipAccountRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedSipAccountRepository.cs @@ -28,22 +28,35 @@ using System.Collections.Generic; using System.Threading.Tasks; using CCM.Core.Entities; +using CCM.Core.Interfaces.Repositories.Base; namespace CCM.Core.Interfaces.Repositories { - public interface ISipAccountRepository + public interface ICachedSipAccountRepository : IRepository { - SipAccount GetById(Guid id); SipAccount GetByRegisteredSipId(Guid registeredSipId); SipAccount GetByUserName(string userName); - List GetAllIncludingRelations(); - List GetAll(); + SipAccount GetSipAccountByUserName(string username); List Find(string startsWith); void Create(SipAccount ccmUser); void Update(SipAccount ccmUser); void UpdateComment(Guid id, string comment); + void UpdateSipAccountQuick(Guid id, string presentationName, string externalReference); void UpdatePassword(Guid id, string password); - void Delete(Guid id); + Task AuthenticateAsync(string username, string password); + } + + public interface ISipAccountRepository : IRepository + { + SipAccount GetByRegisteredSipId(Guid registeredSipId); + SipAccount GetByUserName(string userName); + List Find(string startsWith); + void Create(SipAccount ccmUser); + void Update(SipAccount ccmUser); + void UpdateComment(Guid id, string comment); + void UpdateSipAccountQuick(Guid id, string presentationName, string externalReference); + void UpdatePassword(Guid id, string password); + bool DeleteWithResult(Guid id); Task AuthenticateAsync(string username, string password); } } diff --git a/CCM.Core/Interfaces/Repositories/IUserAgentRepository.cs b/CCM.Core/Interfaces/Repositories/ICachedUserAgentRepository.cs similarity index 89% rename from CCM.Core/Interfaces/Repositories/IUserAgentRepository.cs rename to CCM.Core/Interfaces/Repositories/ICachedUserAgentRepository.cs index 86d6b6ff..1b67a79f 100644 --- a/CCM.Core/Interfaces/Repositories/IUserAgentRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICachedUserAgentRepository.cs @@ -31,12 +31,14 @@ namespace CCM.Core.Interfaces.Repositories { + public interface ICachedUserAgentRepository : IRepository + { + Dictionary GetUserAgentsTypesAndProfiles(); + List Find(string search); + } + public interface IUserAgentRepository : IRepository { - //void Save(UserAgent userAgent); - //void Delete(Guid id); - //UserAgent GetById(Guid id); - //List GetAll(); Dictionary GetUserAgentsTypesAndProfiles(); List Find(string search); } diff --git a/CCM.Core/Interfaces/Repositories/ICodecPresetRepository.cs b/CCM.Core/Interfaces/Repositories/ICategoryRepository.cs similarity index 93% rename from CCM.Core/Interfaces/Repositories/ICodecPresetRepository.cs rename to CCM.Core/Interfaces/Repositories/ICategoryRepository.cs index e3ee4dbd..39bcb1a4 100644 --- a/CCM.Core/Interfaces/Repositories/ICodecPresetRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICategoryRepository.cs @@ -30,8 +30,8 @@ namespace CCM.Core.Interfaces.Repositories { - public interface ICodecPresetRepository : IRepository + public interface ICategoryRepository : IRepository { - List Find(string search); + List FindCategories(string search); } } diff --git a/CCM.Core/Interfaces/Repositories/ICcmUserRepository.cs b/CCM.Core/Interfaces/Repositories/ICcmUserRepository.cs index d8efa006..8c3cb5e2 100644 --- a/CCM.Core/Interfaces/Repositories/ICcmUserRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ICcmUserRepository.cs @@ -41,7 +41,7 @@ public interface ICcmUserRepository bool Update(CcmUser ccmUser); void UpdatePassword(Guid id, string passwordHash, string salt); bool Delete(Guid userId); - CcmRole GetUserRole(CcmUser ccmUser); + //CcmRole GetUserRole(CcmUser ccmUser); Task AuthenticateAsync(string username, string password); } } diff --git a/CCM.Core/Interfaces/Repositories/ILocationInfoRepository.cs b/CCM.Core/Interfaces/Repositories/ILocationInfoRepository.cs deleted file mode 100644 index fcd882bf..00000000 --- a/CCM.Core/Interfaces/Repositories/ILocationInfoRepository.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using CCM.Core.Entities.Specific; - -namespace CCM.Core.Interfaces.Repositories -{ - public interface ILocationInfoRepository - { - List GetAll(); - } -} diff --git a/CCM.Core/Interfaces/Repositories/ILogRepository.cs b/CCM.Core/Interfaces/Repositories/ILogRepository.cs index 784ac5cd..3e4bb3e3 100644 --- a/CCM.Core/Interfaces/Repositories/ILogRepository.cs +++ b/CCM.Core/Interfaces/Repositories/ILogRepository.cs @@ -35,6 +35,8 @@ public interface ILogRepository { Task> GetLastAsync(int nrOfRows, string application, DateTime? startTime, DateTime? endTime, int minLevel, string search, Guid activityId); Task> GetLogInfoAsync(); + Task GetLogTableInfoAsync(); void DeleteOldest(int nrOfRowsToDelete = 100); + void DeleteAll(); } } diff --git a/CCM.Core/Interfaces/Repositories/IMetaRepository.cs b/CCM.Core/Interfaces/Repositories/IMetaRepository.cs index edf5bbdc..fdbcaf4b 100644 --- a/CCM.Core/Interfaces/Repositories/IMetaRepository.cs +++ b/CCM.Core/Interfaces/Repositories/IMetaRepository.cs @@ -33,7 +33,7 @@ namespace CCM.Core.Interfaces.Repositories { public interface IMetaRepository : IRepository { - List GetMetaTypePropertyValues(AvailableMetaType metaType); + //List GetMetaTypePropertyValues(AvailableMetaType metaType); bool CheckMetaTypeNameAvailability(string name, Guid id); List GetMetaTypeProperties(); List FindMetaTypes(string search); diff --git a/CCM.Core/Interfaces/Repositories/IRegisteredSipDetailsRepository.cs b/CCM.Core/Interfaces/Repositories/IRegisteredCodecDetailsRepository.cs similarity index 96% rename from CCM.Core/Interfaces/Repositories/IRegisteredSipDetailsRepository.cs rename to CCM.Core/Interfaces/Repositories/IRegisteredCodecDetailsRepository.cs index cb51d0eb..6d5b8792 100644 --- a/CCM.Core/Interfaces/Repositories/IRegisteredSipDetailsRepository.cs +++ b/CCM.Core/Interfaces/Repositories/IRegisteredCodecDetailsRepository.cs @@ -29,7 +29,7 @@ namespace CCM.Core.Interfaces.Repositories { - public interface IRegisteredSipDetailsRepository + public interface IRegisteredCodecDetailsRepository { RegisteredSipDetails GetRegisteredSipById(Guid id); } diff --git a/CCM.Core/Interfaces/Repositories/IRoleRepository.cs b/CCM.Core/Interfaces/Repositories/IRoleRepository.cs index fe250f76..8c8e43d1 100644 --- a/CCM.Core/Interfaces/Repositories/IRoleRepository.cs +++ b/CCM.Core/Interfaces/Repositories/IRoleRepository.cs @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using CCM.Core.Entities; @@ -32,5 +33,7 @@ namespace CCM.Core.Interfaces.Repositories public interface IRoleRepository { List GetRoles(); + CcmRole GetById(string roleId); + CcmRole GetById(Guid roleId); } } diff --git a/CCM.Core/Interfaces/Repositories/IStudioRepository.cs b/CCM.Core/Interfaces/Repositories/IStudioRepository.cs deleted file mode 100644 index cb5c6c29..00000000 --- a/CCM.Core/Interfaces/Repositories/IStudioRepository.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using CCM.Core.Entities; -using CCM.Core.Interfaces.Repositories.Base; - -namespace CCM.Core.Interfaces.Repositories -{ - public interface IStudioRepository : IRepository - { - List FindStudios(string search); - } -} diff --git a/CCM.Core/Service/DiscoveryService.cs b/CCM.Core/Managers/DiscoveryServiceManager.cs similarity index 87% rename from CCM.Core/Service/DiscoveryService.cs rename to CCM.Core/Managers/DiscoveryServiceManager.cs index 8416e474..d71a30f3 100644 --- a/CCM.Core/Service/DiscoveryService.cs +++ b/CCM.Core/Managers/DiscoveryServiceManager.cs @@ -44,29 +44,26 @@ namespace CCM.Core.Service /// The core service of CCM, Discovery Service / Active Phonebook /// Profiles (SDPs), Filters and User Agents /// - public class DiscoveryService : IDiscoveryService + public class DiscoveryServiceManager : IDiscoveryServiceManager { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); private readonly ISettingsManager _settingsManager; private readonly IFilterManager _filterManager; - private readonly IProfileRepository _profileRepository; - private readonly IRegisteredSipRepository _registeredSipRepository; - private readonly IRegisteredSipsManager _registeredSipsManager; + private readonly ICachedProfileRepository _cachedProfileRepository; + private readonly IRegisteredCodecsManager _registeredCodecsManager; private readonly IAppCache _cache; - public DiscoveryService( + public DiscoveryServiceManager( ISettingsManager settingsManager, IFilterManager filterManager, - IProfileRepository profileRepository, - IRegisteredSipRepository registeredSipRepository, - IRegisteredSipsManager registeredSipsManager, + ICachedProfileRepository cachedProfileRepository, + IRegisteredCodecsManager registeredCodecsManager, IAppCache cache) { _settingsManager = settingsManager; _filterManager = filterManager; - _profileRepository = profileRepository; - _registeredSipRepository = registeredSipRepository; - _registeredSipsManager = registeredSipsManager; + _cachedProfileRepository = cachedProfileRepository; + _registeredCodecsManager = registeredCodecsManager; _cache = cache; } @@ -76,7 +73,7 @@ public DiscoveryService( /// The profiles public List GetProfiles() { - IList profiles = _profileRepository.GetAllProfileNamesAndSdp(); + IList profiles = _cachedProfileRepository.GetAllProfileNamesAndSdp(); var result = profiles.Select(p => new ProfileDto { Name = p.Name, Sdp = p.Sdp }).ToList(); return result; } @@ -88,7 +85,7 @@ public List GetProfiles() public List GetFilters() { // TODO: Add "All" filtering with A-G G-Z possibilities - IList filters = _cache.GetAvailableFilters(_filterManager.GetAvailableFiltersIncludingOptions); + IList filters = _cache.GetAvailableFilters(_filterManager.GetAvailableFiltersIncludingOptions, _settingsManager.CacheTimeConfigData); var result = filters.Select(filter => new FilterDto { @@ -118,7 +115,7 @@ public UserAgentsResultDto GetUserAgents(string caller, string callee, IList registeredUserAgents = _registeredSipsManager.GetRegisteredUserAgentsAndProfiles().ToList(); + IList registeredUserAgents = _registeredCodecsManager.GetRegisteredUserAgentsAndProfiles().ToList(); // Get profiles for caller or if no caller is present return all available profiles IList callerProfiles; @@ -129,7 +126,7 @@ public UserAgentsResultDto GetUserAgents(string caller, string callee, IList s.SipUri == callee); // TODO: Does this needs to be ToList to not be modified? + var calleeSip = registeredUserAgents.FirstOrDefault(s => s.SipUri == callee); if (calleeSip == null) { @@ -181,7 +178,7 @@ private IList GetProfilesForRegisteredSip(string sipId, IList { var regSip = registeredUserAgents.FirstOrDefault(s => s.SipUri == sipId); var profileNames = regSip?.OrderedProfiles ?? new List(); - return _profileRepository.GetAllProfileNamesAndSdp().Where(p => profileNames.Contains(p.Name)).ToList(); + return _cachedProfileRepository.GetAllProfileNamesAndSdp().Where(p => profileNames.Contains(p.Name)).ToList(); } /// @@ -189,7 +186,7 @@ private IList GetProfilesForRegisteredSip(string sipId, IList /// private List GetFilteringValues(IList> selectedFilters) { - var availableFilters = _cache.GetAvailableFilters(_filterManager.GetAvailableFiltersIncludingOptions); + var availableFilters = _cache.GetAvailableFilters(_filterManager.GetAvailableFiltersIncludingOptions, _settingsManager.CacheTimeConfigData); var filterSelections = (from selectedFilter in selectedFilters.Where(f => !string.IsNullOrEmpty(f.Value)) let matchingFilter = availableFilters.FirstOrDefault(f => f.Name == selectedFilter.Key) @@ -224,15 +221,12 @@ private UserAgentsResultDto MatchProfilesAndUserAgents(IEnumerable", displayName, callee.SipUri), - PresentationName = displayName, + SipId = $"{callee.DisplayName} <{callee.SipUri}>", + PresentationName = callee.DisplayName, ConnectedTo = callee.InCallWithName ?? string.Empty, InCall = callee.InCall, MetaData = callee.MetaData?.Select(meta => new KeyValuePair(meta.Key, meta.Value)).ToList(), // TODO: needs to be in a new list again? diff --git a/CCM.Core/Managers/FilterManager.cs b/CCM.Core/Managers/FilterManager.cs index 714ed73e..81cda3a8 100644 --- a/CCM.Core/Managers/FilterManager.cs +++ b/CCM.Core/Managers/FilterManager.cs @@ -58,9 +58,7 @@ public List GetFilterProperties() foreach (var property in filterProperties) { - var filterAttribute = property.GetCustomAttributes(typeof(FilterPropertyAttribute), false).FirstOrDefault() as FilterPropertyAttribute; - - if (filterAttribute != null) + if (property.GetCustomAttributes(typeof(FilterPropertyAttribute), false).FirstOrDefault() is FilterPropertyAttribute filterAttribute) { var filter = new AvailableFilter { @@ -103,8 +101,7 @@ public List GetAllFilters() public List GetAvailableFiltersIncludingOptions() { var filters = GetAllFilters() ?? new List(); - - return filters.Select(filter => new AvailableFilter + var result = filters.Select(filter => new AvailableFilter { Name = filter.Name, FilteringName = filter.FilteringName, @@ -112,6 +109,8 @@ public List GetAvailableFiltersIncludingOptions() ColumnName = filter.ColumnName, Options = _filterRepository.GetFilterPropertyValues(filter.TableName, filter.ColumnName) }).ToList(); + + return result; } public Filter GetFilter(Guid id) diff --git a/CCM.Core/Managers/LocationManager.cs b/CCM.Core/Managers/LocationManager.cs index 898964ed..b491e615 100644 --- a/CCM.Core/Managers/LocationManager.cs +++ b/CCM.Core/Managers/LocationManager.cs @@ -34,11 +34,11 @@ namespace CCM.Core.Managers { public class LocationManager : ILocationManager { - private readonly ILocationRepository _locationRepository; + private readonly ICachedLocationRepository _cachedLocationRepository; - public LocationManager(ILocationRepository locationRepository) + public LocationManager(ICachedLocationRepository cachedLocationRepository) { - _locationRepository = locationRepository; + _cachedLocationRepository = cachedLocationRepository; } public Guid GetLocationIdByIp(string ip) @@ -49,10 +49,11 @@ public Guid GetLocationIdByIp(string ip) return Guid.Empty; } - var networks = _locationRepository.GetAllLocationNetworks().Where(n => n.Network.AddressFamily == ipAddress.AddressFamily); + var networks = _cachedLocationRepository.GetAllLocationNetworks().Where(n => n.Network.AddressFamily == ipAddress.AddressFamily); Guid match = networks - .Where(n => IPNetwork.Contains(n.Network, ipAddress)) + //.Where(n => IPNetwork.Contains(n.Network, ipAddress)) // TODO: redid this one, not sure correct, verify + .Where(n => n.Network.Contains(ipAddress)) .OrderByDescending(n => n.Cidr) .Select(n => n.Id) .FirstOrDefault(); diff --git a/CCM.Core/Managers/LogLevelManager.cs b/CCM.Core/Managers/LogLevelManager.cs index 0a0d872d..c801f865 100644 --- a/CCM.Core/Managers/LogLevelManager.cs +++ b/CCM.Core/Managers/LogLevelManager.cs @@ -58,9 +58,13 @@ public static bool SetLogLevel(string logLevel) foreach (var l in LogLevel.AllLevels) { if (level > l) + { rule.DisableLoggingForLevel(l); + } else + { rule.EnableLoggingForLevel(l); + } } } diff --git a/CCM.Core/Managers/RegisteredSipsManager.cs b/CCM.Core/Managers/RegisteredCodecsManager.cs similarity index 76% rename from CCM.Core/Managers/RegisteredSipsManager.cs rename to CCM.Core/Managers/RegisteredCodecsManager.cs index 3e06a1b7..84178d86 100644 --- a/CCM.Core/Managers/RegisteredSipsManager.cs +++ b/CCM.Core/Managers/RegisteredCodecsManager.cs @@ -35,29 +35,29 @@ namespace CCM.Core.Managers { - public class RegisteredSipsManager : IRegisteredSipsManager + public class RegisteredCodecsManager : IRegisteredCodecsManager { - private readonly IRegisteredSipRepository _registeredSipRepository; - private readonly ICallRepository _callRepository; - private readonly IUserAgentRepository _userAgentRepository; - private readonly ILocationRepository _locationRepository; - private readonly IProfileGroupRepository _profileGroupRepository; + private readonly ICachedRegisteredCodecRepository _cachedRegisteredCodecRepository; + private readonly ICachedCallRepository _cachedCallRepository; + private readonly ICachedUserAgentRepository _cachedUserAgentRepository; + private readonly ICachedLocationRepository _cachedLocationRepository; + private readonly ICachedProfileGroupRepository _cachedProfileGroupRepository; private readonly ISettingsManager _settingsManager; - public RegisteredSipsManager( - IRegisteredSipRepository registeredSipRepository, - ICallRepository callRepository, - IUserAgentRepository userAgentRepository, - ILocationRepository locationRepository, - IProfileGroupRepository profileGroupRepository, + public RegisteredCodecsManager( + ICachedRegisteredCodecRepository cachedRegisteredCodecRepository, + ICachedCallRepository cachedCallRepository, + ICachedUserAgentRepository cachedUserAgentRepository, + ICachedLocationRepository cachedLocationRepository, + ICachedProfileGroupRepository cachedProfileGroupRepository, ISettingsManager settingsManager) { - _registeredSipRepository = registeredSipRepository; - _callRepository = callRepository; - _userAgentRepository = userAgentRepository; - _locationRepository = locationRepository; - _profileGroupRepository = profileGroupRepository; + _cachedRegisteredCodecRepository = cachedRegisteredCodecRepository; + _cachedCallRepository = cachedCallRepository; + _cachedUserAgentRepository = cachedUserAgentRepository; + _cachedLocationRepository = cachedLocationRepository; + _cachedProfileGroupRepository = cachedProfileGroupRepository; _settingsManager = settingsManager; } @@ -67,7 +67,7 @@ public IEnumerable GetRegisteredUserAge var sipDomain = _settingsManager.SipDomain; // Registered user agents - IEnumerable registeredUserAgentsList = _registeredSipRepository.GetRegisteredUserAgentsDiscovery(); + IEnumerable registeredUserAgentsList = _cachedRegisteredCodecRepository.GetRegisteredUserAgentsDiscovery(); if (registeredUserAgentsList == null) { @@ -75,16 +75,16 @@ public IEnumerable GetRegisteredUserAge } // User agent types and profiles for each User Agent - IDictionary userAgentsTypesList = _userAgentRepository.GetUserAgentsTypesAndProfiles(); + IDictionary userAgentsTypesList = _cachedUserAgentRepository.GetUserAgentsTypesAndProfiles(); // Locations and profile groups - IDictionary locationsAndProfileGroupList = _locationRepository.GetLocationsAndProfiles(); + IDictionary locationsAndProfileGroupList = _cachedLocationRepository.GetLocationsAndProfiles(); // Profile groups - IReadOnlyList profileGroupsList = _profileGroupRepository.GetAll(); + IReadOnlyList profileGroupsList = _cachedProfileGroupRepository.GetAll(); // Ongoing calls - IReadOnlyCollection callsList = _callRepository.GetOngoingCalls(true); + IReadOnlyCollection callsList = _cachedCallRepository.GetOngoingCalls(true); return registeredUserAgentsList.Select(regSip => { @@ -92,12 +92,12 @@ public IEnumerable GetRegisteredUserAge // of recommended profiles in the Discovery service. // Sorting is based on the sort order of the location. - // Match register user agent user agent profiles + // Match registered user agent user agent profiles var profilesUserAgent = Enumerable.Empty(); if (regSip.UserAgentId != null && userAgentsTypesList.TryGetValue(regSip.UserAgentId.Value, out var profilesUa)) { - profilesUserAgent = profilesUa.Profiles.OrderBy(z => z.SortIndex).Select(y => y.Name); // TODO: No sort is done here...it's done earlier. trust? Is it the right sort? + profilesUserAgent = profilesUa.Profiles.OrderBy(z => z.OrderIndex).Select(y => y.Name); // TODO: No sort is done here...it's done earlier. trust? Is it the right sort? } // Match location profiles and add profile names to locations profile groups @@ -139,15 +139,13 @@ public IEnumerable GetRegisteredUserAge inCallWithName = isFromCaller ? call.ToDisplayName : call.FromDisplayName; } - // Registered user agent - var dispName = DisplayNameHelper.GetDisplayName(regSip.DisplayName, regSip.UserDisplayName, - string.Empty, regSip.Username, regSip.SipUri, "", sipDomain); + // Registered user agent and displayname correction + var presentationName = DisplayNameHelper.GetDisplayName(regSip, sipDomain); return new RegisteredUserAgentAndProfilesDiscovery( id: regSip.Id, sipUri: regSip.SipUri, - displayName: dispName, - username: regSip.Username, + displayName: presentationName, ipAddress: regSip.IpAddress, userAgentHeader: regSip.UserAgentHeader, userAgentName: regSip.UserAgentName, diff --git a/CCM.Core/Managers/SettingsManager.cs b/CCM.Core/Managers/SettingsManager.cs index 4ee2b176..9f080521 100644 --- a/CCM.Core/Managers/SettingsManager.cs +++ b/CCM.Core/Managers/SettingsManager.cs @@ -29,6 +29,7 @@ using System.Linq; using CCM.Core.Entities; using CCM.Core.Enums; +using CCM.Core.Helpers; using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using NLog; @@ -38,11 +39,11 @@ namespace CCM.Core.Managers public class SettingsManager : ISettingsManager { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - private readonly ISettingsRepository _settingsRepository; + private readonly ICachedSettingsRepository _cachedSettingsRepository; - public SettingsManager(ISettingsRepository settingsRepository) + public SettingsManager(ICachedSettingsRepository cachedSettingsRepository) { - _settingsRepository = settingsRepository; + _cachedSettingsRepository = cachedSettingsRepository; } public string SipDomain => GetSetting(SettingsEnum.SIPDomain); @@ -51,15 +52,22 @@ public SettingsManager(ISettingsRepository settingsRepository) public bool CodecControlActive => GetSetting(SettingsEnum.CodecControlActive); public bool UseOldKamailioEvent => GetSetting(SettingsEnum.UseOldKamailioEvent); public bool UseSipEvent => GetSetting(SettingsEnum.UseSipEvent); + public string UserAgentImagesFolder => GetSetting(SettingsEnum.UserAgentImagesFolder); + public string DiscoveryServiceUrl => GetSetting(SettingsEnum.DiscoveryServiceUrl); + public string CodecControlHost => GetSetting(SettingsEnum.CodecControlHost); + public string CodecControlUserName => GetSetting(SettingsEnum.CodecControlUserName); + public string CodecControlPassword => GetSetting(SettingsEnum.CodecControlPassword); + public int CacheTimeLiveData => GetSetting(SettingsEnum.CacheTimeLiveData); + public int CacheTimeConfigData => GetSetting(SettingsEnum.CacheTimeConfigData); - public List GetSettings() + public void SaveSettings(List newSettings, string userName) { - return _settingsRepository.GetAll(); + _cachedSettingsRepository.Save(newSettings, userName); } - public void SaveSettings(List newSettings, string userName) + public List GetSettings() { - _settingsRepository.Save(newSettings, userName); + return _cachedSettingsRepository.GetAll(); } private string GetSetting(SettingsEnum enumName) diff --git a/CCM.Core/Managers/SipAccountManager.cs b/CCM.Core/Managers/SipAccountManager.cs deleted file mode 100644 index 60cb1834..00000000 --- a/CCM.Core/Managers/SipAccountManager.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using CCM.Core.Entities; -using CCM.Core.Interfaces.Managers; -using CCM.Core.Interfaces.Repositories; -using NLog; - -namespace CCM.Core.Managers -{ - public class SipAccountManager : ISipAccountManager - { - //TODO: This one is jsut a bit strange why it's needed. not really performing anything mind blowing that could not just be in the repository - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - - private readonly ISipAccountRepository _sipAccountRepository; - - public SipAccountManager(ISipAccountRepository sipAccountRepository) - { - _sipAccountRepository = sipAccountRepository; - } - - public void Create(SipAccount account) - { - if (_sipAccountRepository.GetByUserName(account.UserName) != null) - { - log.Warn("Can't create user. Username {0} already exists in CCM database", account.UserName); - throw new ApplicationException("User name already exists."); - } - - _sipAccountRepository.Create(account); - } - - public bool Delete(Guid id) - { - _sipAccountRepository.Delete(id); - return true; - } - - public SipAccount GetById(Guid id) - { - return _sipAccountRepository.GetById(id); - } - - public List GetAll() - { - return _sipAccountRepository.GetAllIncludingRelations() ?? new List(); - } - - public List Find(string startsWith) - { - return _sipAccountRepository.Find(startsWith) ?? new List(); - } - - public SipAccount GetByUserName(string userName) - { - // TODO: Move this one to be using the GetSipAccountByUserName - return _sipAccountRepository.GetByUserName(userName); - } - - public SipAccount GetSipAccountByUserName(string username) - { - // TODO: Keep this one. But maybe if nothing can be found, trigger cache reload of sipAccounts and search again. - return _sipAccountRepository.GetAll().ToList().FirstOrDefault(u => u.UserName.ToLower() == username); - } - - public void Update(SipAccount account) - { - _sipAccountRepository.Update(account); - } - - public SipAccount GetByRegisteredSip(Guid registeredSipId) - { - return _sipAccountRepository.GetByRegisteredSipId(registeredSipId); - } - - public void UpdateComment(Guid id, string comment) - { - _sipAccountRepository.UpdateComment(id, comment); - } - - public void UpdatePassword(Guid id, string password) - { - _sipAccountRepository.UpdatePassword(id, password); - } - } -} diff --git a/CCM.Core/Managers/StatisticsManager.cs b/CCM.Core/Managers/StatisticsManager.cs index 5cfd9e77..7085d0dd 100644 --- a/CCM.Core/Managers/StatisticsManager.cs +++ b/CCM.Core/Managers/StatisticsManager.cs @@ -31,33 +31,33 @@ using CCM.Core.Entities.Statistics; using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; +using Microsoft.AspNetCore.Http.Internal; namespace CCM.Core.Managers { - public class StatisticsManager : IStatisticsManager { - private readonly ICallHistoryRepository _callHistoryRepository; + private readonly ICachedCallHistoryRepository _cachedCallHistoryRepository; private readonly ICodecTypeRepository _codecTypeRepository; - private readonly ILocationRepository _locationRepository; + private readonly ICachedLocationRepository _cachedLocationRepository; private readonly IOwnersRepository _ownersRepository; private readonly IRegionRepository _regionRepository; - private readonly ISipAccountRepository _sipAccountRepository; + private readonly ICachedSipAccountRepository _cachedSipAccountRepository; public StatisticsManager( - ICallHistoryRepository callHistoryRepository, + ICachedCallHistoryRepository cachedCallHistoryRepository, ICodecTypeRepository codecTypeRepository, IOwnersRepository ownersRepository, IRegionRepository regionRepository, - ILocationRepository locationRepository, - ISipAccountRepository sipAccountRepository) + ICachedLocationRepository cachedLocationRepository, + ICachedSipAccountRepository cachedSipAccountRepository) { - _callHistoryRepository = callHistoryRepository; + _cachedCallHistoryRepository = cachedCallHistoryRepository; _codecTypeRepository = codecTypeRepository; _ownersRepository = ownersRepository; _regionRepository = regionRepository; - _locationRepository = locationRepository; - _sipAccountRepository = sipAccountRepository; + _cachedLocationRepository = cachedLocationRepository; + _cachedSipAccountRepository = cachedSipAccountRepository; } public List GetCodecTypes() @@ -65,43 +65,152 @@ public List GetCodecTypes() return _codecTypeRepository.GetAll(false); } - public List GetLocationStatistics(DateTime startTime, DateTime endTime, Guid regionId, Guid ownerId, Guid codecTypeId) + public List GetOwners() { - var callHistories = _callHistoryRepository.GetCallHistoriesByDate(startTime, endTime); + return _ownersRepository.GetAll(); + } - if (callHistories == null) + public List GetRegions() + { + return _regionRepository.GetAll(); + } + + public List GetSipAccounts() + { + return _cachedSipAccountRepository.GetAll(); + } + + public IList GetCategoryCallStatistics(DateTime startDate, DateTime endDate) + { + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() + var categoryStatistics = new List(); + var callHistory = _cachedCallHistoryRepository.GetCallHistoriesByDate(startDate, endDate); + if (callHistory == null) { - return new List(); + return categoryStatistics; } + return GenerateDateBasedCategoryStatistics(callHistory, startDate, endDate) ?? new List(); + } - var locations = new Dictionary(); - var filter = new CallHistoryFilter(regionId, ownerId, codecTypeId); - foreach (var callEvent in LocationCallEvent.GetOrderedEvents(callHistories, filter)) + public IList GetCategoryStatistics(DateTime startDate, DateTime endDate) + { + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() + var categoryStatistics = new List(); + var callHistory = _cachedCallHistoryRepository.GetCallHistoriesByDate(startDate, endDate); + if (callHistory == null) { - if (!locations.ContainsKey(callEvent.LocationId)) - locations.Add(callEvent.LocationId, new LocationBasedStatistics { LocationId = callEvent.LocationId, LocationName = callEvent.LocationName}); - locations[callEvent.LocationId].AddEvent(callEvent, startTime, endTime); + return categoryStatistics; } - - var locationStatisticses = locations.Values.ToList(); - AddMissingLocations(locationStatisticses, regionId); - - return locationStatisticses.OrderBy(l => l.LocationName).ToList(); + return GenerateCategoryStatistics(callHistory, startDate, endDate) ?? new List(); } - public List GetOwners() + private List GenerateDateBasedCategoryStatistics(IList callHistories, DateTime reportPeriodStart, DateTime reportPeriodEnd) { - return _ownersRepository.GetAll(); + if (!callHistories.Any()) return new List(); + + Dictionary, CategoryCallStatistic> receivers = new Dictionary, CategoryCallStatistic>(); + + foreach (var call in callHistories) + { + var fromCat = string.IsNullOrEmpty(call.FromCodecTypeCategory) == false ? call.FromCodecTypeCategory.ToLower() : string.IsNullOrEmpty(call.FromLocationCategory) == false ? call.FromLocationCategory.ToLower() : ""; + var toCat = string.IsNullOrEmpty(call.ToCodecTypeCategory) == false ? call.ToCodecTypeCategory.ToLower() : string.IsNullOrEmpty(call.ToLocationCategory) == false ? call.ToLocationCategory.ToLower() : ""; + + string[] combi = { fromCat, toCat }; + Array.Sort(combi); + var key = new Tuple(combi[0], combi[1]); + + double callTime = (call.Ended - call.Started).TotalSeconds; + + if (receivers.TryGetValue(key, out CategoryCallStatistic item)) + { + item.NumberOfCalls++; + item.Part1Category = combi[0] ?? ""; + item.Part2Category = combi[1] ?? ""; + item.CallTimes.Add(callTime); + item.TotalCallTime += callTime; + } + else + { + receivers.Add(key, new CategoryCallStatistic + { + NumberOfCalls = 1, + Part1Category = combi[0] ?? "", + Part2Category = combi[1] ?? "", + CallTimes = new List { callTime }, + TotalCallTime = callTime + }); + } + } + + return receivers.Values.ToList(); } - public List GetRegions() + private List GenerateCategoryStatistics(IList callHistories, DateTime reportPeriodStart, DateTime reportPeriodEnd) { - return _regionRepository.GetAll(); + if (!callHistories.Any()) return new List(); + + var categories = new Dictionary(); + + foreach (var call in callHistories) + { + var fromCat = string.IsNullOrEmpty(call.FromCodecTypeCategory) == false ? call.FromCodecTypeCategory.ToLower() : string.IsNullOrEmpty(call.FromLocationCategory) == false ? call.FromLocationCategory.ToLower() : ""; + var toCat = string.IsNullOrEmpty(call.ToCodecTypeCategory) == false ? call.ToCodecTypeCategory.ToLower() : string.IsNullOrEmpty(call.ToLocationCategory) == false ? call.ToLocationCategory.ToLower() : ""; + + double callTime = (call.Ended - call.Started).TotalSeconds; + + // Categories statistics + if (string.IsNullOrEmpty(fromCat)) + { + fromCat = call?.FromCodecTypeName?.ToLower() ?? ""; + } + if (categories.TryGetValue(fromCat, out CategoryItemStatistic existingFrom)) + { + existingFrom.NumberOfCalls++; + existingFrom.Category = fromCat; + existingFrom.CallTimes.Add(callTime); + existingFrom.TotalCallTime += callTime; + } + else + { + categories.Add(fromCat, new CategoryItemStatistic + { + NumberOfCalls = 1, + Category = fromCat, + CallTimes = new List { callTime }, + TotalCallTime = callTime + }); + } + + if (string.IsNullOrEmpty(toCat)) + { + toCat = call?.ToCodecTypeName ?? ""; + } + if (categories.TryGetValue(toCat, out CategoryItemStatistic existingTo)) + { + existingTo.NumberOfCalls++; + existingTo.Category = toCat; + existingTo.CallTimes.Add(callTime); + existingTo.TotalCallTime += callTime; + } + else + { + categories.Add(toCat, new CategoryItemStatistic + { + NumberOfCalls = 1, + Category = toCat, + CallTimes = new List { callTime }, + TotalCallTime = callTime + }); + } + } + + return categories.Values.ToList(); } - public List GetRegionStatistics(DateTime startDate, DateTime endDate, Guid regionId) + public IList GetRegionStatistics(DateTime startDate, DateTime endDate, Guid regionId) { - var callHistories = _callHistoryRepository.GetCallHistoriesForRegion(startDate, endDate, regionId); + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() + var callHistories = _cachedCallHistoryRepository.GetCallHistoriesForRegion(startDate, endDate, regionId); if (callHistories == null) { @@ -112,15 +221,11 @@ public List GetRegionStatistics(DateTime startDate, DateTim return regionStatistics.OrderBy(r => r.Date).ToList(); } - public List GetSipUsers() + public IList GetSipAccountStatistics(DateTime startDate, DateTime endDate, Guid userId) { - return _sipAccountRepository.GetAll(); - } - - public List GetSipStatistics(DateTime startDate, DateTime endDate, Guid userId) - { - var user = _sipAccountRepository.GetById(userId); - var callHistories = user != null ? _callHistoryRepository.GetCallHistoriesForRegisteredSip(startDate, endDate, user.UserName) : new List(); + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() + var user = _cachedSipAccountRepository.GetById(userId); + var callHistories = user != null ? _cachedCallHistoryRepository.GetCallHistoriesForRegisteredSip(startDate, endDate, user.UserName) : new List(); var sipStatistics = GenerateDateBasedStatisticses(callHistories, startDate, endDate) .OrderBy(s => s.Date) @@ -131,9 +236,10 @@ public List GetSipStatistics(DateTime startDate, DateTime e public IList GetCodecTypeStatistics(DateTime startDate, DateTime endDate, Guid codecTypeId) { + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() var codecTypeStatistics = new List(); - var callHistories = _callHistoryRepository.GetCallHistoriesForCodecType(startDate, endDate, codecTypeId); + var callHistories = _cachedCallHistoryRepository.GetCallHistoriesForCodecType(startDate, endDate, codecTypeId); if (callHistories == null) { @@ -148,22 +254,55 @@ public IList GetCodecTypeStatistics(DateTime startDate, Dat public IList GetLocationsForRegion(Guid regionId) { return - _locationRepository.GetAll() + _cachedLocationRepository.GetAll() .Where(l => regionId == Guid.Empty || (l.Region != null && l.Region.Id == regionId)) .ToList(); } - public HourBasedStatisticsForLocation GetHourStatisticsForLocation(DateTime startTime, DateTime endTime, Guid locationId, bool noAggregation) + public List GetLocationStatistics(DateTime startDate, DateTime endDate, Guid regionId, Guid ownerId, Guid codecTypeId) { - var location = _locationRepository.GetById(locationId); - if (location == null) - return new HourBasedStatisticsForLocation { LocationId = locationId, LocationName = "", Statistics = new List()}; + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() + var callHistories = _cachedCallHistoryRepository.GetCallHistoriesByDate(startDate, endDate); + if (callHistories == null) + { + return new List(); + } + + var locations = new Dictionary(); + var filter = new CallHistoryFilter(regionId, ownerId, codecTypeId); + foreach (var callEvent in LocationCallEvent.GetOrderedEvents(callHistories, filter)) + { + if (!locations.ContainsKey(callEvent.LocationId)) + locations.Add(callEvent.LocationId, new LocationBasedStatistics { LocationId = callEvent.LocationId, LocationName = callEvent.LocationName }); + locations[callEvent.LocationId].AddEvent(callEvent, startDate, endDate); + } + + var locationStatisticses = locations.Values.ToList(); + AddMissingLocations(locationStatisticses, regionId); + + return locationStatisticses.OrderBy(l => l.LocationName).ToList(); + } + + public HourBasedStatisticsForLocation GetHourStatisticsForLocation(DateTime startDate, DateTime endDate, Guid locationId, bool noAggregation) + { + endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() + var location = _cachedLocationRepository.GetById(locationId); + if (location == null) + { + return new HourBasedStatisticsForLocation + { + LocationId = locationId, + LocationName = "", + Statistics = new List() + }; + } var allStats = new List(); - var callHistories = _callHistoryRepository.GetCallHistoriesForLocation(startTime, endTime, locationId); - var current = HourBasedStatistics.Create(startTime); + var callHistories = _cachedCallHistoryRepository.GetCallHistoriesForLocation(startDate, endDate, locationId); + var current = HourBasedStatistics.Create(startDate); allStats.Add(current); - foreach (var callEvent in HourBasedCallEvent.GetOrderedEvents(callHistories, locationId).Where(e => e.EventTime < endTime)) + // TODO: check eventtime z endtime + foreach (var callEvent in HourBasedCallEvent.GetOrderedEvents(callHistories, locationId).Where(e => e.EventTime < endDate)) { while (!current.AddEvent(callEvent)) { @@ -182,7 +321,7 @@ public HourBasedStatisticsForLocation GetHourStatisticsForLocation(DateTime star private void AddMissingLocations(IList locationStatisticses, Guid regionId) { - var locations = _locationRepository.GetAll(); + var locations = _cachedLocationRepository.GetAll(); foreach (var location in locations) { @@ -199,7 +338,7 @@ private void AddMissingLocations(IList locationStatisti private IEnumerable GenerateDateBasedStatisticses(IList callHistories, DateTime reportPeriodStart, DateTime reportPeriodEnd) { if (!callHistories.Any()) return Enumerable.Empty(); - + // TODO: check what ToLocalTime does no compensation is done here yet for endDate = endDate.AddDays(1.0); // Correction for ToUniversalTime() var minDate = reportPeriodStart.ToLocalTime().Date; // callHistories.Min(c => c.Started); var endLocal = reportPeriodEnd.ToLocalTime(); var maxDate = endLocal.Date == endLocal ? endLocal.Date.AddDays(-1) : endLocal.Date; // callHistories.Max(c => c.Started.ToLocalTime().Date); diff --git a/CCM.Core/Properties/AssemblyInfo.cs b/CCM.Core/Properties/AssemblyInfo.cs deleted file mode 100644 index 0959e2b9..00000000 --- a/CCM.Core/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("CCM.Core")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Sveriges Radio AB")] -[assembly: AssemblyProduct("CCM.Core")] -[assembly: AssemblyCopyright("Copyright © Sveriges Radio AB 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("a875e16f-5e03-4a76-be05-cf5f843a8d17")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.0.1")] -[assembly: AssemblyFileVersion("0.1.0.1")] diff --git a/CCM.Core/Properties/Resources.Designer.cs b/CCM.Core/Resources/Resources.Designer.cs similarity index 69% rename from CCM.Core/Properties/Resources.Designer.cs rename to CCM.Core/Resources/Resources.Designer.cs index 260051a5..eb5298ac 100644 --- a/CCM.Core/Properties/Resources.Designer.cs +++ b/CCM.Core/Resources/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace CCM.Core.Properties { +namespace CCM.Core.Resources { using System; @@ -19,7 +19,7 @@ namespace CCM.Core.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CCM.Core.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CCM.Core.Resources.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -60,6 +60,24 @@ internal Resources() { } } + /// + /// Looks up a localized string similar to Börjar med. + /// + internal static string Begins_With { + get { + return ResourceManager.GetString("Begins_With", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Innehåller. + /// + internal static string Contains { + get { + return ResourceManager.GetString("Contains", resourceCulture); + } + } + /// /// Looks up a localized string similar to Pool-kodare. /// @@ -87,6 +105,15 @@ internal static string Description_SipAlias { } } + /// + /// Looks up a localized string similar to Slutar med. + /// + internal static string Ends_With { + get { + return ResourceManager.GetString("Ends_With", resourceCulture); + } + } + /// /// Looks up a localized string similar to Externt nummer. /// @@ -95,5 +122,23 @@ internal static string External_Phone_Number { return ResourceManager.GetString("External_Phone_Number", resourceCulture); } } + + /// + /// Looks up a localized string similar to Ank. + /// + internal static string Internal_Phone_Connection_Prefix { + get { + return ResourceManager.GetString("Internal_Phone_Connection_Prefix", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reguljärt uttryck. + /// + internal static string Regular_Expression { + get { + return ResourceManager.GetString("Regular_Expression", resourceCulture); + } + } } } diff --git a/CCM.Core/Properties/Resources.resx b/CCM.Core/Resources/Resources.resx similarity index 92% rename from CCM.Core/Properties/Resources.resx rename to CCM.Core/Resources/Resources.resx index 9283093a..83bc134f 100644 --- a/CCM.Core/Properties/Resources.resx +++ b/CCM.Core/Resources/Resources.resx @@ -117,6 +117,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Börjar med + + + Innehåller + Pool-kodare @@ -126,7 +132,16 @@ SIP-alias + + Slutar med + Externt nummer + + Ank + + + Reguljärt uttryck + \ No newline at end of file diff --git a/CCM.Core/SipEvent/Parser/KamailioData.cs b/CCM.Core/SipEvent/Event/KamailioMessageData.cs similarity index 96% rename from CCM.Core/SipEvent/Parser/KamailioData.cs rename to CCM.Core/SipEvent/Event/KamailioMessageData.cs index 9f88a136..6456d5c2 100644 --- a/CCM.Core/SipEvent/Parser/KamailioData.cs +++ b/CCM.Core/SipEvent/Event/KamailioMessageData.cs @@ -27,9 +27,9 @@ using System.Collections.Generic; using CCM.Core.SipEvent.Messages; -namespace CCM.Core.SipEvent.Parser +namespace CCM.Core.SipEvent.Event { - public class KamailioData + public class KamailioMessageData { public SipEventMessageType MessageType { get; set; } public Dictionary Fields { get; set; } diff --git a/CCM.Core/SipEvent/Event/KamailioSipEventData.cs b/CCM.Core/SipEvent/Event/KamailioSipEventData.cs new file mode 100644 index 00000000..c7c781e6 --- /dev/null +++ b/CCM.Core/SipEvent/Event/KamailioSipEventData.cs @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Globalization; +using System.Text.Json.Serialization; +using CCM.Core.SipEvent.Messages; + +namespace CCM.Core.SipEvent.Event +{ + public class KamailioSipEventData + { + [JsonPropertyName("version")] public int Version { get; set; } = 1; + // Topic: Registration + [JsonPropertyName("event")] public string Event { get; set; } // "register"/"regexpire"/"dialog" + [JsonPropertyName("timestamp")] public long TimeStamp { get; set; } // TODO: THIS ONE IS OFF.. MAKE SURE TIME IS CORRECT ON SERVER + [JsonPropertyName("registrar")] public string Registrar { get; set; } // "registrar.com" + [JsonPropertyName("regtype")] public string RegType { get; set; } // "rereg/new/delete" + [JsonPropertyName("expires")] public int Expires { get; set; } + [JsonPropertyName("method")] public string Method { get; set; } // "REGISTER" + [JsonPropertyName("from_uri")] public string FromUri { get; set; } // "sip:test1249@registrar.com" + [JsonPropertyName("from_displayname")] public string FromDisplayName { get; set; } // "Karlstad 11" + + [JsonPropertyName("to_uri")] public string ToUri { get; set; } // "" + [JsonPropertyName("to_displayname")] public string ToDisplayName { get; set; } // "" + [JsonPropertyName("user_agent")] public string UserAgentHeader { get; set; } // "Asterisk PBX 11.13" + [JsonPropertyName("contact_uri")] public string ContactUri { get; set; } // "" + [JsonPropertyName("call_id")] public string CallId { get; set; } // "338a@registrar.com" + + // Topic: Dialog start + [JsonPropertyName("request_uri")] public string RequestUri { get; set; } // "sip:registrar.com", The actual requested destination. where to_uri contains the first "destination" that could be a relay + [JsonPropertyName("dialog_state")] public string DialogState { get; set; } // "start" + [JsonPropertyName("dhash_id")] public string DialogHashId { get; set; } // "10300" + [JsonPropertyName("dhash_ent")] public string DialogHashEntry { get; set; } // "2697" + [JsonPropertyName("to_tag")] public string ToTag { get; set; } // "" + [JsonPropertyName("from_tag")] public string FromTag { get; set; } // "svE1Cx0ksdjnQ-Csidg60B6H02bNXbfQ" + [JsonPropertyName("sdp")] public string Sdp { get; set; } // "v=0....." + + // Topic: Dialog End + [JsonPropertyName("hangup_reason")] public string HangupReason { get; set; } // "NORMAL" + + [JsonPropertyName("ip")] public IpInfo Ip { get; set; } + + public string ToLogString() + { + var timestamp = this.UnixTimeStampToDateTime(this.TimeStamp); + return $"Kamailio Sip Event:{this.Event.ToString()}, TimeStamp:{timestamp}, Registrar:{this.Registrar}, RegType:{this.RegType}, Expires:{this.Expires.ToString()}, Method:{this.Method}, User-Agent:{this.UserAgentHeader}, FromURI:{this.FromUri}, CallId:{this.CallId.ToString()}" + + $", DialogState:{this.DialogState}, DialogHashId:{this.DialogHashId}, DialogHashEntry:{this.DialogHashEntry}, HangupReason:{this.HangupReason}"; + } + + public string UnixTimeStampToDateTime(long unixTimeStamp) + { + DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); + + try + { + dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime(); + return dtDateTime.ToString(CultureInfo.InvariantCulture); + } + catch (Exception) + { + return dtDateTime.ToString(CultureInfo.InvariantCulture); + } + } + + public class IpInfo + { + [JsonPropertyName("sender_ip")] public string SenderIp { get; set; } // "192.121.194.213" + [JsonPropertyName("sender_port")] public int SenderPort { get; set; } // 5080 + [JsonPropertyName("our_ip")] public string OurIp { get; set; } // 192.121.194.200 + [JsonPropertyName("our_port")] public int OurPort { get; set; } // 5060 + } + } +} \ No newline at end of file diff --git a/CCM.Core/SipEvent/ExternalStoreMessageManager.cs b/CCM.Core/SipEvent/ExternalStoreMessageManager.cs new file mode 100644 index 00000000..d766fe05 --- /dev/null +++ b/CCM.Core/SipEvent/ExternalStoreMessageManager.cs @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using CCM.Core.Entities; +using CCM.Core.Enums; +using CCM.Core.Interfaces.Managers; +using CCM.Core.Interfaces.Repositories; +using CCM.Core.SipEvent.Messages; +using CCM.Core.SipEvent.Models; +using Microsoft.Extensions.Logging; + +namespace CCM.Core.SipEvent +{ + public class ExternalStoreMessageManager : IExternalStoreMessageManager + { + private readonly ILogger _logger; + + private readonly ICachedCallRepository _cachedCallRepository; + private readonly ICachedRegisteredCodecRepository _cachedRegisteredCodecRepository; + + public ExternalStoreMessageManager(ICachedRegisteredCodecRepository cachedRegisteredCodecRepository, ICachedCallRepository cachedCallRepository, ILogger logger) + { + _cachedRegisteredCodecRepository = cachedRegisteredCodecRepository; + _cachedCallRepository = cachedCallRepository; + _logger = logger; + } + + /// + /// Handles the dialog received + /// + /// + public SipEventHandlerResult HandleDialog(ExternalDialogMessage dialogMessage) + { + switch (dialogMessage.Status) + { + case ExternalDialogStatus.Start: + return RegisterCall(dialogMessage); + case ExternalDialogStatus.End: + return CloseCall(dialogMessage); + default: + return NothingChangedResult; + } + } + + public SipEventHandlerResult RegisterCall(ExternalDialogMessage message) + { + _logger.LogDebug($"Register call from:{message.FromUsername} to:{message.ToUsername}, call id:{message.CallId}"); + + if (_cachedCallRepository.CallExists(message.CallId, "", "") && message.Ended != null) + { + _logger.LogDebug($"Call with id:{message.CallId} should be Ended closing it instead of registering it"); + return CloseCall(message); + } + + if (_cachedCallRepository.CallExists(message.CallId, "", "")) + { + _logger.LogDebug($"Call with id:{message.CallId} already exists"); + return NothingChangedResult; + } + + var call = new Call + { + FromSip = message.FromUsername, + FromDisplayName = message.FromDisplayName, + FromId = Guid.Parse(message.FromId), + FromCategory = message.FromCategory, + ToSip = message.ToUsername, + ToDisplayName = message.ToDisplayName, + ToId = Guid.Parse(message.ToId), + ToCategory = message.ToCategory, + Started = message.Started ?? DateTime.UtcNow, + Closed = (message.Ended != null), + CallId = message.CallId, + DialogHashId = "", + DialogHashEnt = "", + Updated = DateTime.UtcNow, + State = SipCallState.NONE, + SDP = message.SDP + }; + + _cachedCallRepository.UpdateCall(call); + + return SipMessageResult(SipEventChangeStatus.CallStarted, call.Id, call.FromSip); + } + + public SipEventHandlerResult CloseCall(ExternalDialogMessage message) + { + _logger.LogDebug($"Closing call with id:{message.CallId}"); + + try + { + CallInfo call = _cachedCallRepository.GetCallInfo(message.CallId, "", ""); + + if (call == null) + { + _logger.LogWarning($"Unable to find call with call id:{message.CallId}"); + return NothingChangedResult; + } + + if (call.Closed) + { + _logger.LogWarning($"Call with call id:{message.CallId} already closed"); + return NothingChangedResult; + } + + _cachedCallRepository.CloseCall(call.Id); + return SipMessageResult(SipEventChangeStatus.CallClosed, call.Id, call.FromSipAddress); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error while closing call with call id:{message.CallId}"); + return NothingChangedResult; + } + } + + private SipEventHandlerResult NothingChangedResult => SipMessageResult(SipEventChangeStatus.NothingChanged); + private SipEventHandlerResult SipMessageResult(SipEventChangeStatus status) { return new SipEventHandlerResult() { ChangeStatus = status }; } + private SipEventHandlerResult SipMessageResult(SipEventChangeStatus status, Guid id) { return new SipEventHandlerResult() { ChangeStatus = status, ChangedObjectId = id }; } + private SipEventHandlerResult SipMessageResult(SipEventChangeStatus status, Guid id, string sipAddress) { return new SipEventHandlerResult() { ChangeStatus = status, ChangedObjectId = id, SipAddress = sipAddress }; } + } +} diff --git a/CCM.Core/SipEvent/KamailioSipEvent.cs b/CCM.Core/SipEvent/KamailioSipEvent.cs deleted file mode 100644 index b20e79af..00000000 --- a/CCM.Core/SipEvent/KamailioSipEvent.cs +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Globalization; -using CCM.Core.SipEvent.Messages; -using Newtonsoft.Json; -using NLog; - -namespace CCM.Core.SipEvent -{ - public class KamailioSipEvent - { - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - - // Topic: Registration - [JsonProperty(PropertyName = "event")] public SipEventType Event { get; set; } // "register"/"regexpire" - [JsonProperty(PropertyName = "timestamp")] public long TimeStamp { get; set; } - [JsonProperty(PropertyName = "registrar")] public string Registrar { get; set; } // "sipregistrar.sr.se" - [JsonProperty(PropertyName = "regtype")] public string RegType { get; set; } // "rereg/new/delete" - [JsonProperty(PropertyName = "expires")] public int Expires { get; set; } - [JsonProperty(PropertyName = "method")] public string Method { get; set; } // "REGISTER" - [JsonProperty(PropertyName = "from_uri")] public string FromUri { get; set; } // "sip:test1249@contrib.sr.se" - [JsonProperty(PropertyName = "from_displayname")] public string FromDisplayName { get; set; } // "Karlstad 11" - [JsonProperty(PropertyName = "to_uri")] public string ToUri { get; set; } // "" - [JsonProperty(PropertyName = "to_displayname")] public string ToDisplayName { get; set; } // "" - [JsonProperty(PropertyName = "auth_user")] public string AuthUser { get; set; } // "test1249" - [JsonProperty(PropertyName = "user_agent")] public string UserAgentHeader { get; set; } // "Asterisk PBX 11.13" - [JsonProperty(PropertyName = "contact_uri")] public string ContactUri { get; set; } // "" - [JsonProperty(PropertyName = "call_id")] public string CallId { get; set; } // "338a@contrib.sr.se" - - // Topic: Dialog start - [JsonProperty(PropertyName = "sipserver")] public string SipServer { get; set; } // "sipregistrar.sr.se" - [JsonProperty(PropertyName = "request_uri")] public string RequestUri { get; set; } // "sip:contrib.sr.se", The actual requested destination. where to_uri contains the first "destination" that could be a relay - [JsonProperty(PropertyName = "dialog_state")] public string DialogState { get; set; } // "start" - [JsonProperty(PropertyName = "dhash_id")] public string DialogHashId { get; set; } // "10300" - [JsonProperty(PropertyName = "dhash_ent")] public string DialogHashEntry { get; set; } // "2697" - [JsonProperty(PropertyName = "pool_uri")] public string PoolUri { get; set; } // "sip:studio-pool-004@contrib.sr.se" - [JsonProperty(PropertyName = "to_tag")] public string ToTag { get; set; } // "" - [JsonProperty(PropertyName = "from_tag")] public string FromTag { get; set; } // "svE1Cx0ksdjnQ-Csidg60B6H02bNXbfQ" - [JsonProperty(PropertyName = "mediastatus")] public string MediaStatus { get; set; } // "NAT/RTPproxy" - [JsonProperty(PropertyName = "sdp")] public string Sdp { get; set; } // "v=0....." - [JsonProperty(PropertyName = "debug_origuri")] public string DebugOrigUri { get; set; } // "" - - // Topic: Dialog End - [JsonProperty(PropertyName = "hangup_reason")] public string HangupReason { get; set; } // "NORMAL" - - [JsonProperty(PropertyName = "ip")] public IpInfo Ip { get; set; } - - public string ToLogString() - { - var timestamp = this.UnixTimeStampToDateTime(this.TimeStamp); - return $"Kamailio Sip Event:{this.Event.ToString()}, TimeStamp:{timestamp}, Registrar:{this.Registrar}, RegType:{this.RegType}, Expires:{this.Expires.ToString()}, Method:{this.Method}, User-Agent:{this.UserAgentHeader}, FromURI:{this.FromUri}, CallId:{this.CallId.ToString()}" + - $", SipServer:{this.SipServer}, DialogState:{this.DialogState}, DialogHashId:{this.DialogHashId}, DialogHashEntry:{this.DialogHashEntry}, HangupReason:{this.HangupReason}"; - } - - public string UnixTimeStampToDateTime(long unixTimeStamp) - { - DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); - - try - { - dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime(); - return dtDateTime.ToString(CultureInfo.InvariantCulture); - } - catch (Exception) - { - return dtDateTime.ToString(CultureInfo.InvariantCulture); - } - } - } - - public class IpInfo - { - [JsonProperty(PropertyName = "sender_ip")] public string SenderIp { get; set; } // "192.121.194.213" - [JsonProperty(PropertyName = "sender_port")] public int SenderPort { get; set; } // "5080" - [JsonProperty(PropertyName = "our_ip")] public string OurIp { get; set; } // 192.121.194.200 - [JsonProperty(PropertyName = "our_port")] public int OurPort { get; set; } // "5060" - } -} \ No newline at end of file diff --git a/CCM.Web/Infrastructure/CamelCaseControllerConfigAttribute.cs b/CCM.Core/SipEvent/Messages/ExternalDialogMessage.cs similarity index 59% rename from CCM.Web/Infrastructure/CamelCaseControllerConfigAttribute.cs rename to CCM.Core/SipEvent/Messages/ExternalDialogMessage.cs index cfac8caf..7c8f5724 100644 --- a/CCM.Web/Infrastructure/CamelCaseControllerConfigAttribute.cs +++ b/CCM.Core/SipEvent/Messages/ExternalDialogMessage.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden * * Redistribution and use in source and binary forms, with or without @@ -25,25 +25,34 @@ */ using System; -using System.Linq; -using System.Net.Http.Formatting; -using System.Web.Http.Controllers; -using Newtonsoft.Json.Serialization; -namespace CCM.Web.Infrastructure +namespace CCM.Core.SipEvent.Messages { - public class CamelCaseControllerConfigAttribute : Attribute, IControllerConfiguration + public class ExternalDialogMessage { - public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) - { - controllerSettings.Formatters.Clear(); + public string CallId { get; set; } + + public ExternalDialogStatus Status { get; set; } + public DateTime? Started { get; set; } = null; + public DateTime? Ended { get; set; } = null; + public bool IsPhoneCall { get; set; } + public string SDP { get; set; } - var formatter = new JsonMediaTypeFormatter - { - SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() } - }; + public string FromId { get; set; } + public string FromUsername { get; set; } + public string FromDisplayName { get; set; } + public string FromIPAddress { get; set; } + public string FromCategory { get; set; } - controllerSettings.Formatters.Add(formatter); + public string ToId { get; set; } + public string ToUsername { get; set; } + public string ToDisplayName { get; set; } + public string ToIPAddress { get; set; } + public string ToCategory { get; set; } + + public string ToDebugString() + { + return $"CallId:{CallId}, Started:{Started}, Ended:{Ended}, FromUsername:{FromUsername} ({FromCategory}), ToUsername:{ToUsername} ({ToCategory})"; } } } diff --git a/CCM.Web/Models/ApiExternal/HangupParameters.cs b/CCM.Core/SipEvent/Messages/ExternalDialogStatus.cs similarity index 92% rename from CCM.Web/Models/ApiExternal/HangupParameters.cs rename to CCM.Core/SipEvent/Messages/ExternalDialogStatus.cs index 93350c1a..5f139877 100644 --- a/CCM.Web/Models/ApiExternal/HangupParameters.cs +++ b/CCM.Core/SipEvent/Messages/ExternalDialogStatus.cs @@ -24,10 +24,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace CCM.Web.Models.ApiExternal +namespace CCM.Core.SipEvent.Messages { - public class HangupParameters + public enum ExternalDialogStatus { - public string SipAddress { get; set; } + Start, + End, + Complete } } diff --git a/CCM.Core/SipEvent/Messages/SipDialogMessage.cs b/CCM.Core/SipEvent/Messages/SipDialogMessage.cs index 17e94ffd..a744e66e 100644 --- a/CCM.Core/SipEvent/Messages/SipDialogMessage.cs +++ b/CCM.Core/SipEvent/Messages/SipDialogMessage.cs @@ -24,11 +24,13 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using CCM.Core.SipEvent.Models; + namespace CCM.Core.SipEvent.Messages { public class SipDialogMessage : SipMessageBase { - public DialogStatus Status { get; set; } + public SipDialogStatus Status { get; set; } public string CallId { get; set; } public string HashId { get; set; } public string HashEntry { get; set; } @@ -43,30 +45,17 @@ public class SipDialogMessage : SipMessageBase public override string ToDebugString() { - if (Status == DialogStatus.SingleBye) + if (Status == SipDialogStatus.SingleBye) { - return string.Format("CallId:{0}, FromSip:{1}, ToSip:{2}, FromTag:{3}, ToTag:{4}", - CallId, - FromSipUri != null ? FromSipUri.UserAtHost : string.Empty, - ToSipUri != null ? ToSipUri.UserAtHost : string.Empty, - FromTag, - ToTag); + return $"CallId:{CallId}, FromSip:{FromSipUri?.UserAtHost ?? string.Empty}, ToSip:{ToSipUri?.UserAtHost ?? string.Empty}, FromTag:{FromTag}, ToTag:{ToTag}"; } - if (Status == DialogStatus.End) + if (Status == SipDialogStatus.End) { - return string.Format("CallId:{0}, HashId:{1}, HashEntry:{2}, Hangup reason:{3}, FromDisplayName:{4} FromSip:{5}, ToDisplayName:{6} ToSip:{7}, FromTag:{8}, ToTag:{9}", - CallId, HashId, HashEntry, HangupReason, - FromDisplayName, FromSipUri != null ? FromSipUri.UserAtHost : string.Empty, - ToDisplayName, ToSipUri != null ? ToSipUri.UserAtHost : string.Empty, - FromTag, ToTag); + return $"CallId:{CallId}, HashId:{HashId}, HashEntry:{HashEntry}, Hangup reason:{HangupReason}, FromDisplayName:{FromDisplayName} FromSip:{FromSipUri?.UserAtHost ?? string.Empty}, ToDisplayName:{ToDisplayName} ToSip:{ToSipUri?.UserAtHost ?? string.Empty}, FromTag:{FromTag}, ToTag:{ToTag}"; } - return string.Format("CallId:{0}, HashId:{1}, HashEntry:{2}, FromDisplayName:{3} FromSip:{4}, ToDisplayName:{5} ToSip:{6}, FromTag:{7}, ToTag:{8}", - CallId, HashId, HashEntry, - FromDisplayName, FromSipUri != null ? FromSipUri.UserAtHost : string.Empty, - ToDisplayName, ToSipUri != null ? ToSipUri.UserAtHost : string.Empty, - FromTag, ToTag); + return $"CallId:{CallId}, HashId:{HashId}, HashEntry:{HashEntry}, FromDisplayName:{FromDisplayName} FromSip:{FromSipUri?.UserAtHost ?? string.Empty}, ToDisplayName:{ToDisplayName} ToSip:{ToSipUri?.UserAtHost ?? string.Empty}, FromTag:{FromTag}, ToTag:{ToTag}"; } } } diff --git a/CCM.Core/SipEvent/Messages/DialogStatus.cs b/CCM.Core/SipEvent/Messages/SipDialogStatus.cs similarity index 98% rename from CCM.Core/SipEvent/Messages/DialogStatus.cs rename to CCM.Core/SipEvent/Messages/SipDialogStatus.cs index f836a504..cebc1c09 100644 --- a/CCM.Core/SipEvent/Messages/DialogStatus.cs +++ b/CCM.Core/SipEvent/Messages/SipDialogStatus.cs @@ -26,7 +26,7 @@ namespace CCM.Core.SipEvent.Messages { - public enum DialogStatus + public enum SipDialogStatus { Start, End, diff --git a/CCM.Core/SipEvent/Messages/SipEventMessageType.cs b/CCM.Core/SipEvent/Messages/SipEventMessageType.cs index 58ef44fe..371c1334 100644 --- a/CCM.Core/SipEvent/Messages/SipEventMessageType.cs +++ b/CCM.Core/SipEvent/Messages/SipEventMessageType.cs @@ -28,8 +28,17 @@ namespace CCM.Core.SipEvent.Messages { public enum SipEventMessageType { - Request, // Codec registration - Dialog, // Calls - RegExpire // Codec registration has expired + /// + /// Codec registration + /// + Request, + /// + /// Calls + /// + Dialog, + /// + /// Codec registration has expired + /// + RegExpire } } \ No newline at end of file diff --git a/CCM.Core/SipEvent/Messages/SipRegistrationExpireMessage.cs b/CCM.Core/SipEvent/Messages/SipRegistrationExpireMessage.cs index c578d651..f65cbe2e 100644 --- a/CCM.Core/SipEvent/Messages/SipRegistrationExpireMessage.cs +++ b/CCM.Core/SipEvent/Messages/SipRegistrationExpireMessage.cs @@ -24,12 +24,17 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using CCM.Core.SipEvent.Models; + namespace CCM.Core.SipEvent.Messages { public class SipRegistrationExpireMessage : SipMessageBase { - public SipUri SipAddress { get; set; } // Sip-URI - public string ReceivedIp { get; set; } // IP-address the message was sent from + public SipUri SipAddress { get; set; } + /// + /// IP-address the message was sent from + /// + public string ReceivedIp { get; set; } public override string ToDebugString() { diff --git a/CCM.Core/SipEvent/Messages/SipRegistrationMessage.cs b/CCM.Core/SipEvent/Messages/SipRegistrationMessage.cs index d9e31a16..0c1cdc88 100644 --- a/CCM.Core/SipEvent/Messages/SipRegistrationMessage.cs +++ b/CCM.Core/SipEvent/Messages/SipRegistrationMessage.cs @@ -24,6 +24,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using CCM.Core.SipEvent.Models; + namespace CCM.Core.SipEvent.Messages { public class SipRegistrationMessage : SipMessageBase @@ -35,14 +37,13 @@ public class SipRegistrationMessage : SipMessageBase public string UserAgent { get; set; } public string Registrar { get; set; } public string RegType { get; set; } - public string Username { get; set; } // TODO: Obsolete. To be removed. Sip used both as sip address and user name (Anders) public string ToDisplayName { get; set; } public long UnixTimeStamp { get; set; } public int Expires { get; set; } public override string ToDebugString() { - return $"SIP:{Sip}, IP:{Ip}, Port:{Port}, UserAgent:{UserAgent}, Username:{Username}, Registrar:{Registrar}, RegType:{RegType}, ToDisplayName:{ToDisplayName}, UnixTimeStamp:{UnixTimeStamp}, Expires:{Expires}"; + return $"SIP:{Sip}, IP:{Ip}, Port:{Port}, UserAgent:{UserAgent}, Registrar:{Registrar}, RegType:{RegType}, ToDisplayName:{ToDisplayName}, UnixTimeStamp:{UnixTimeStamp}, Expires:{Expires}"; } } } \ No newline at end of file diff --git a/CCM.Core/SipEvent/SipEventChangeStatus.cs b/CCM.Core/SipEvent/Models/SipEventChangeStatus.cs similarity index 97% rename from CCM.Core/SipEvent/SipEventChangeStatus.cs rename to CCM.Core/SipEvent/Models/SipEventChangeStatus.cs index 855fc6a7..f60a6f68 100644 --- a/CCM.Core/SipEvent/SipEventChangeStatus.cs +++ b/CCM.Core/SipEvent/Models/SipEventChangeStatus.cs @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace CCM.Core.SipEvent +namespace CCM.Core.SipEvent.Models { public enum SipEventChangeStatus { diff --git a/CCM.Core/SipEvent/SipEventHandlerResult.cs b/CCM.Core/SipEvent/Models/SipEventHandlerResult.cs similarity index 92% rename from CCM.Core/SipEvent/SipEventHandlerResult.cs rename to CCM.Core/SipEvent/Models/SipEventHandlerResult.cs index 6730dd06..ab15cb17 100644 --- a/CCM.Core/SipEvent/SipEventHandlerResult.cs +++ b/CCM.Core/SipEvent/Models/SipEventHandlerResult.cs @@ -26,7 +26,7 @@ using System; -namespace CCM.Core.SipEvent +namespace CCM.Core.SipEvent.Models { public class SipEventHandlerResult { @@ -36,7 +36,7 @@ public class SipEventHandlerResult public override string ToString() { - return string.Format("{0} {1}", ChangeStatus, ChangedObjectId); + return $"Change status:{ChangeStatus}, Changed object id:{ChangedObjectId}, SIP address:{SipAddress}"; } public static SipEventHandlerResult NothingChanged => new SipEventHandlerResult { ChangeStatus = SipEventChangeStatus.NothingChanged }; diff --git a/CCM.Core/SipEvent/SipUri.cs b/CCM.Core/SipEvent/Models/SipUri.cs similarity index 97% rename from CCM.Core/SipEvent/SipUri.cs rename to CCM.Core/SipEvent/Models/SipUri.cs index 3dd759bc..927214ea 100644 --- a/CCM.Core/SipEvent/SipUri.cs +++ b/CCM.Core/SipEvent/Models/SipUri.cs @@ -27,7 +27,7 @@ using System; using System.Text.RegularExpressions; -namespace CCM.Core.SipEvent +namespace CCM.Core.SipEvent.Models { public class SipUri { @@ -59,7 +59,6 @@ public SipUri(string sipAddress) try { // Handle display name - string displayName = ""; if (sipAddress.Contains("<")) { @@ -91,7 +90,7 @@ public SipUri(string sipAddress) public override string ToString() { - return string.Format("{0} ({1})", UserAtHost, _sipString); + return $"{UserAtHost} ({_sipString})"; } } } diff --git a/CCM.Core/SipEvent/Parser/KamailioDataParser.cs b/CCM.Core/SipEvent/Parser/KamailioDataParser.cs deleted file mode 100644 index e5c90c43..00000000 --- a/CCM.Core/SipEvent/Parser/KamailioDataParser.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Linq; -using CCM.Core.Interfaces.Kamailio; -using CCM.Core.SipEvent.Messages; -using NLog; - -namespace CCM.Core.SipEvent.Parser -{ - public class KamailioDataParser : IKamailioDataParser - { - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - - /// - /// Parses Kamailio data with a '::'-separated string - /// KamailioDataParser uses this one. - /// - public KamailioData ParseToKamailioData(string message) - { - if (string.IsNullOrWhiteSpace(message)) - { - log.Warn("Message body empty"); - return null; - } - - string[] dataFields = message.Split('|'); - - if (dataFields.Length == 0) - { - return null; - } - - SipEventMessageType msgType; - if (!Enum.TryParse(dataFields[0], true, out msgType)) - { - log.Warn("Unable to get message type from {0}", dataFields[0]); - return null; - } - - var fieldsDictionary = dataFields - .Select(x => x.Split(new[] { "::" }, StringSplitOptions.None)) - .Where(x => x.Length == 2 && !String.IsNullOrEmpty(x[0].Trim())) - .ToDictionary(x => x[0].Trim(), x => x[1] == "" ? string.Empty : x[1].Trim()); - - return new KamailioData { MessageType = msgType, Fields = fieldsDictionary }; - } - - } -} diff --git a/CCM.Core/SipEvent/Parser/KamailioMessageParser.cs b/CCM.Core/SipEvent/Parser/KamailioEventParser.cs similarity index 68% rename from CCM.Core/SipEvent/Parser/KamailioMessageParser.cs rename to CCM.Core/SipEvent/Parser/KamailioEventParser.cs index a41ebc86..196e6354 100644 --- a/CCM.Core/SipEvent/Parser/KamailioMessageParser.cs +++ b/CCM.Core/SipEvent/Parser/KamailioEventParser.cs @@ -25,10 +25,14 @@ */ using System; +using System.Linq; using System.Text.RegularExpressions; -using CCM.Core.Interfaces.Kamailio; +using CCM.Core.Interfaces.Managers; +using CCM.Core.Interfaces.Parser; +using CCM.Core.SipEvent.Event; using CCM.Core.SipEvent.Messages; -using NLog; +using CCM.Core.SipEvent.Models; +using Microsoft.Extensions.Logging; namespace CCM.Core.SipEvent.Parser { @@ -42,20 +46,20 @@ namespace CCM.Core.SipEvent.Parser /// version of 'connect' that formats the messages with string /// separation. Or try to see if you can implement the JSON version. /// - public class KamailioMessageParser : IKamailioMessageParser + public class KamailioEventParser : IKamailioEventParser { - private readonly IKamailioDataParser _kamailioDataParser; - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - private const int DefaultExpireValue = 120; + private readonly ILogger _logger; + private readonly ISettingsManager _settingsManager; - public KamailioMessageParser(IKamailioDataParser kamailioDataParser) + public KamailioEventParser(ISettingsManager settingsManager, ILogger logger) { - _kamailioDataParser = kamailioDataParser; + _settingsManager = settingsManager; + _logger = logger; } public SipMessageBase Parse(string message) { - var kamailioData = _kamailioDataParser.ParseToKamailioData(message); + var kamailioData = ParseRawKamailioData(message); if (kamailioData == null) { return null; @@ -68,23 +72,61 @@ public SipMessageBase Parse(string message) case SipEventMessageType.Dialog: return ParseDialog(kamailioData); case SipEventMessageType.RegExpire: - return ParseRegExpire(kamailioData); + return ParseExpiredRegistration(kamailioData); } return null; } - private SipDialogMessage ParseDialog(KamailioData kamailioData) + private SipRegistrationMessage ParseRegistration(KamailioMessageData kamailioData) { - DialogStatus dialogStatus; - if (!Enum.TryParse(kamailioData.GetField("dstat"), true, out dialogStatus)) + var maxRegistrationAge = _settingsManager.MaxRegistrationAge; + + var registration = new SipRegistrationMessage() + { + Ip = kamailioData.GetField("si"), + Port = ParseInt(kamailioData.GetField("sp")), + UnixTimeStamp = ParseLong(kamailioData.GetField("TS")), + Sip = new SipUri(kamailioData.GetField("fu")), + FromDisplayName = ParseDisplayName(kamailioData.GetField("fn")), + UserAgent = kamailioData.GetField("ua"), + ToDisplayName = ParseDisplayName(kamailioData.GetField("tn")), + Expires = ParseInt(kamailioData.GetField("Expires"), maxRegistrationAge), + + // Not in use + //Username = kamailioData.GetField("Au"), + //ToUsername = kamailioData.GetField("rU"), + //RequestedSip = new SipUri(kamailioData.GetField("ru")), + //ReceivedIp = kamailioData.GetField("Ri"), + //ReceivedPort = ParseInt(kamailioData.GetField("Rp")), + //CallId = kamailioData.GetField("ci"), + }; + + return registration; + } + + private SipRegistrationExpireMessage ParseExpiredRegistration(KamailioMessageData kamailioData) + { + var expire = new SipRegistrationExpireMessage() + { + SipAddress = new SipUri(kamailioData.GetField("aor")), + ReceivedIp = kamailioData.GetField("ip"), + }; + + return expire; + } + + private SipDialogMessage ParseDialog(KamailioMessageData kamailioData) + { + SipDialogStatus sipDialogStatus; + if (!Enum.TryParse(kamailioData.GetField("dstat"), true, out sipDialogStatus)) { - log.Warn("Unable to parse dstat field of Kamailio dialog message"); + _logger.LogWarning("Unable to parse dstat field of Kamailio dialog message"); return null; } var dialog = new SipDialogMessage { - Status = dialogStatus, + Status = sipDialogStatus, CallId = kamailioData.GetField("ci"), HashId = kamailioData.GetField("hashid"), HashEntry = kamailioData.GetField("hashent"), @@ -107,50 +149,45 @@ private SipDialogMessage ParseDialog(KamailioData kamailioData) return dialog; } - private SipRegistrationMessage ParseRegistration(KamailioData kamailioData) + /// + /// Parses Kamailio data with a '::'-separated string + /// + private KamailioMessageData ParseRawKamailioData(string message) { - var registration = new SipRegistrationMessage() + if (string.IsNullOrWhiteSpace(message)) { - Ip = kamailioData.GetField("si"), - Port = ParseInt(kamailioData.GetField("sp")), - UnixTimeStamp = ParseLong(kamailioData.GetField("TS")), - Sip = new SipUri(kamailioData.GetField("fu")), - FromDisplayName = ParseDisplayName(kamailioData.GetField("fn")), - UserAgent = kamailioData.GetField("ua"), - Username = kamailioData.GetField("Au"), - ToDisplayName = ParseDisplayName(kamailioData.GetField("tn")), - Expires = ParseInt(kamailioData.GetField("Expires"), DefaultExpireValue), + _logger.LogWarning("Message body empty"); + return null; + } - // Not in use - //ToUsername = kamailioData.GetField("rU"), - //RequestedSip = new SipUri(kamailioData.GetField("ru")), - //ReceivedIp = kamailioData.GetField("Ri"), - //ReceivedPort = ParseInt(kamailioData.GetField("Rp")), - //CallId = kamailioData.GetField("ci"), - }; + string[] dataFields = message.Split('|'); - return registration; - } + if (dataFields.Length == 0) + { + return null; + } - private SipRegistrationExpireMessage ParseRegExpire(KamailioData kamailioData) - { - // TODO: Is this one ever called? - var expire = new SipRegistrationExpireMessage() + SipEventMessageType msgType; + if (!Enum.TryParse(dataFields[0], true, out msgType)) { - SipAddress = new SipUri(kamailioData.GetField("aor")), - ReceivedIp = kamailioData.GetField("ip"), - }; + _logger.LogWarning("Unable to get message type from {0}", dataFields[0]); + return null; + } - return expire; - } + var fieldsDictionary = dataFields + .Select(x => x.Split(new[] { "::" }, StringSplitOptions.None)) + .Where(x => x.Length == 2 && !String.IsNullOrEmpty(x[0].Trim())) + .ToDictionary(x => x[0].Trim(), x => x[1] == "" ? string.Empty : x[1].Trim()); + return new KamailioMessageData { MessageType = msgType, Fields = fieldsDictionary }; + } - public static string ParseDisplayName(string s) + private static string ParseDisplayName(string s) { return string.IsNullOrEmpty(s) ? string.Empty : Regex.Unescape(s).Trim(' ', '"'); } - private int ParseInt(string s, int defaultValue = 0) + private static int ParseInt(string s, int defaultValue = 0) { int i; if (int.TryParse(s, out i)) @@ -158,15 +195,13 @@ private int ParseInt(string s, int defaultValue = 0) return i; } return defaultValue; - } - private long ParseLong(string s) + private static long ParseLong(string s) { long i; long.TryParse(s, out i); return i; } - } } diff --git a/CCM.Core/SipEvent/Parser/SipEventParser.cs b/CCM.Core/SipEvent/Parser/SipEventParser.cs index 5a383a9f..1de7d48c 100644 --- a/CCM.Core/SipEvent/Parser/SipEventParser.cs +++ b/CCM.Core/SipEvent/Parser/SipEventParser.cs @@ -26,8 +26,11 @@ using System; using System.Text.RegularExpressions; -using CCM.Core.Interfaces.Kamailio; +using CCM.Core.Interfaces.Parser; +using CCM.Core.SipEvent.Event; using CCM.Core.SipEvent.Messages; +using CCM.Core.SipEvent.Models; +using Microsoft.Extensions.Logging; using NLog; namespace CCM.Core.SipEvent.Parser @@ -41,28 +44,32 @@ namespace CCM.Core.SipEvent.Parser /// public class SipEventParser : ISipEventParser { - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); + private readonly ILogger _logger; - public SipMessageBase Parse(KamailioSipEvent sipEvent) + public SipEventParser(ILogger logger) { - switch (sipEvent.Event) + _logger = logger; + } + + public SipMessageBase Parse(KamailioSipEventData sipEventData) + { + switch (sipEventData.Event.ToLower()) { - case SipEventType.Register: - return ParseRegistration(sipEvent); - case SipEventType.Dialog: - return ParseDialog(sipEvent); - case SipEventType.RegExpire: - return ParseRegExpire(sipEvent); + case "register": + return ParseRegistration(sipEventData); + case "dialog": + return ParseDialog(sipEventData); + case "regexpire": + return ParseExpiredRegistration(sipEventData); } return null; } - private SipRegistrationMessage ParseRegistration(KamailioSipEvent kamailioData) + private SipRegistrationMessage ParseRegistration(KamailioSipEventData kamailioData) { var registration = new SipRegistrationMessage() { Sip = new SipUri(kamailioData.FromUri), - Username = kamailioData.AuthUser, // TODO: Obsolete. To be removed. FromDisplayName = ParseDisplayName(kamailioData.FromDisplayName), ToDisplayName = ParseDisplayName(kamailioData.ToDisplayName), UserAgent = kamailioData.UserAgentHeader, @@ -77,26 +84,36 @@ private SipRegistrationMessage ParseRegistration(KamailioSipEvent kamailioData) return registration; } - private SipRegistrationExpireMessage ParseRegExpire(KamailioSipEvent kamailioData) + private SipRegistrationExpireMessage ParseExpiredRegistration(KamailioSipEventData kamailioData) { + if (kamailioData == null) + { + _logger.LogError("SipEventParser: ParseExpiredRegistration kamiliodata is null"); + return new SipRegistrationExpireMessage() + { + SipAddress = new SipUri(""), + ReceivedIp = "" + }; + + } var expire = new SipRegistrationExpireMessage() { - SipAddress = new SipUri(kamailioData.FromUri), - ReceivedIp = kamailioData.Ip.SenderIp + SipAddress = new SipUri(kamailioData?.FromUri ?? "Unknown"), + ReceivedIp = kamailioData?.Ip?.SenderIp ?? "" }; return expire; } - private SipDialogMessage ParseDialog(KamailioSipEvent kamailioData) + private SipDialogMessage ParseDialog(KamailioSipEventData kamailioData) { - if (!Enum.TryParse(kamailioData.DialogState, true, out DialogStatus dialogStatus)) + if (!Enum.TryParse(kamailioData.DialogState, true, out SipDialogStatus dialogStatus)) { - log.Warn($"Dialog state field = {kamailioData.DialogState} of Kamailio dialog message"); + _logger.LogWarning($"Dialog state field = {kamailioData.DialogState} of Kamailio dialog message"); return null; } - var dialog = new SipDialogMessage + var dialog = new SipDialogMessage() { Status = dialogStatus, CallId = kamailioData.CallId, @@ -105,9 +122,11 @@ private SipDialogMessage ParseDialog(KamailioSipEvent kamailioData) FromDisplayName = ParseDisplayName(kamailioData.FromDisplayName), ToDisplayName = ParseDisplayName(kamailioData.ToDisplayName), FromSipUri = new SipUri(kamailioData.FromUri), - ToSipUri = new SipUri(kamailioData.RequestUri), //new SipUri(kamailioData.ToUri), + ToSipUri = new SipUri(kamailioData.RequestUri), + HangupReason = kamailioData.HangupReason, FromTag = kamailioData.FromTag, ToTag = kamailioData.ToTag, + Sdp = kamailioData.Sdp }; return dialog; @@ -117,6 +136,5 @@ public static string ParseDisplayName(string s) { return string.IsNullOrEmpty(s) ? string.Empty : Regex.Unescape(s).Trim(' ', '"'); } - } } \ No newline at end of file diff --git a/CCM.Core/SipEvent/KamailioMessageManager.cs b/CCM.Core/SipEvent/SipMessageManager.cs similarity index 55% rename from CCM.Core/SipEvent/KamailioMessageManager.cs rename to CCM.Core/SipEvent/SipMessageManager.cs index 9ca7d61f..1bb3251b 100644 --- a/CCM.Core/SipEvent/KamailioMessageManager.cs +++ b/CCM.Core/SipEvent/SipMessageManager.cs @@ -31,21 +31,26 @@ using CCM.Core.Interfaces.Managers; using CCM.Core.Interfaces.Repositories; using CCM.Core.SipEvent.Messages; +using CCM.Core.SipEvent.Models; +using Microsoft.Extensions.Logging; using NLog; namespace CCM.Core.SipEvent { - public class KamailioMessageManager : ISipMessageManager + public class SipMessageManager : ISipMessageManager { + private readonly ILogger _logger; protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - private readonly ICallRepository _callRepository; - private readonly IRegisteredSipRepository _sipRepository; - public KamailioMessageManager(IRegisteredSipRepository sipRepository, ICallRepository callRepository) + private readonly ICachedCallRepository _cachedCallRepository; + private readonly ICachedRegisteredCodecRepository _cachedRegisteredCodecRepository; + + public SipMessageManager(ICachedRegisteredCodecRepository cachedRegisteredCodecRepository, ICachedCallRepository cachedCallRepository, ILogger logger) { - _sipRepository = sipRepository; - _callRepository = callRepository; + _cachedRegisteredCodecRepository = cachedRegisteredCodecRepository; + _cachedCallRepository = cachedCallRepository; + _logger = logger; } /// @@ -54,10 +59,7 @@ public KamailioMessageManager(IRegisteredSipRepository sipRepository, ICallRepos /// public SipEventHandlerResult HandleSipMessage(SipMessageBase sipMessage) { - if (log.IsDebugEnabled) - { - log.Debug("Parsed Kamailio Message {0}", sipMessage.ToDebugString()); - } + //_logger.LogDebug("Parsed Kamailio Message {0}", sipMessage.ToDebugString()); switch (sipMessage) { @@ -83,7 +85,7 @@ public SipEventHandlerResult HandleSipMessage(SipMessageBase sipMessage) } default: { - log.Info("Unhandled Kamailio message: {0}", sipMessage.ToDebugString()); + _logger.LogInformation("Unhandled Kamailio message: {0}", sipMessage.ToDebugString()); return NothingChangedResult; } } @@ -103,22 +105,22 @@ public SipEventHandlerResult RegisterCodec(SipRegistrationMessage sipMessage) serverTimeStamp: sipMessage.UnixTimeStamp ); - return _sipRepository.UpdateRegisteredSip(userAgentRegistration); + return _cachedRegisteredCodecRepository.UpdateRegisteredSip(userAgentRegistration); } private SipEventHandlerResult UnregisterCodec(SipRegistrationExpireMessage expireMessage, string regType = null) { var sipAddress = expireMessage.SipAddress.UserAtHost; - if (regType == "delete") + if (regType == "delete") // TODO: Should this be an enum? Maybe define when this happen { - log.Info($"Unregister Codec {sipAddress}, {regType}"); - Call codecCall = _callRepository.GetCallBySipAddress(sipAddress); + _logger.LogInformation($"Unregister Codec {sipAddress}, {regType}"); + Call codecCall = _cachedCallRepository.GetCallBySipAddress(sipAddress); if (codecCall != null) { - log.Info($"Unregistrating codec but it's in a call {sipAddress}"); + _logger.LogWarning($"Unregistrating codec but it's in a call {sipAddress}"); } } - return _sipRepository.DeleteRegisteredSip(sipAddress); + return _cachedRegisteredCodecRepository.DeleteRegisteredSip(sipAddress); } /// @@ -127,19 +129,20 @@ private SipEventHandlerResult UnregisterCodec(SipRegistrationExpireMessage expir /// private SipEventHandlerResult HandleDialog(SipDialogMessage sipDialogMessage) { + log.Info($"######## Handle Dialog {sipDialogMessage.ToDebugString()}"); switch (sipDialogMessage.Status) { - case DialogStatus.Start: + case SipDialogStatus.Start: return RegisterCall(sipDialogMessage); - case DialogStatus.End: + case SipDialogStatus.End: // TODO: Check hangup reason. Only close calls where reason = Normal // TODO: Handle timeout message and add warning to call but don't end it - log.Info("Received End command from Kamailio. HangUp reason: {0}, From: {1}, To: {2}", sipDialogMessage.HangupReason, sipDialogMessage.FromSipUri, sipDialogMessage.ToSipUri); + _logger.LogInformation("Received End command from Kamailio. HangUp reason:{0}, from:{1}, to:{2}", sipDialogMessage.HangupReason, sipDialogMessage.FromSipUri, sipDialogMessage.ToSipUri); return CloseCall(sipDialogMessage); - case DialogStatus.SingleBye: - // If BYE in kamailio and no dialog is in Kamailio, a single bye is sent to CCM + case SipDialogStatus.SingleBye: + // If BYE in Kamailio and no dialog is in Kamailio, a single bye is sent to CCM // TODO: Handle single bye message and close call - log.Info("Received SingleBye command from Kamailio. HangUp reason: {0}, From: {1}, To: {2}", sipDialogMessage.HangupReason, sipDialogMessage.FromSipUri, sipDialogMessage.ToSipUri); + _logger.LogInformation("Received SingleBye command from Kamailio. HangUp reason:{0}, from:{1}, to:{2}", sipDialogMessage.HangupReason, sipDialogMessage.FromSipUri, sipDialogMessage.ToSipUri); return NothingChangedResult; default: return NothingChangedResult; @@ -148,72 +151,110 @@ private SipEventHandlerResult HandleDialog(SipDialogMessage sipDialogMessage) public SipEventHandlerResult RegisterCall(SipDialogMessage sipMessage) { - log.Debug("Register call from {0} to {1}, call id \"{2}\", hash id:\"{3}\", hash entry:\"{4}\"", - sipMessage.FromSipUri.UserAtHost, sipMessage.ToSipUri.UserAtHost, sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); + //_logger.LogDebug("Register call from:{0} to:{1}, call id:{2}, hash id:{3}, hash entry:{4}", + // sipMessage.FromSipUri.UserAtHost, sipMessage.ToSipUri.UserAtHost, sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); - if (_callRepository.CallExists(sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry)) + if (_cachedCallRepository.CallExists(sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry)) { - // TODO: Find out what HashId and HashEntry is and if they are both needed - log.Debug("Call with id {0}, hash id:{1}, hash entry:{2} already exists", sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); + _logger.LogDebug("Call with id:{0}, hash id:{1}, hash entry:{2} already exists", sipMessage.CallId, + sipMessage.HashId, sipMessage.HashEntry); return NothingChangedResult; } - var call = new Call(); // If the user-part is numeric, we make the assumption // that it is a phone number (even though sip-address // can be of the numeric kind) - var fromSip = sipMessage.FromSipUri.User.IsNumeric() ? sipMessage.FromSipUri.User : sipMessage.FromSipUri.UserAtHost; - var from = _sipRepository.GetRegisteredUserAgents().SingleOrDefault(x => x.SipUri == fromSip); - call.FromSip = fromSip; + var from = _cachedRegisteredCodecRepository + .GetRegisteredUserAgents() + .FirstOrDefault(x => + (x.SipUri == sipMessage.FromSipUri.User || x.SipUri == sipMessage.FromSipUri.UserAtHost)); call.FromDisplayName = sipMessage.FromDisplayName; + if (from != null) + { + call.FromSip = from.SipUri; + call.FromDisplayName = string.IsNullOrEmpty(from.UserDisplayName) + ? from.DisplayName + : from.UserDisplayName; // TODO: maybe displayname helper should exist here.. check this + } + else if (sipMessage.FromSipUri.User.IsNumeric()) + { + call.FromSip = sipMessage.FromSipUri.User; + call.IsPhoneCall = true; + } + else + { + call.FromSip = sipMessage.FromSipUri.UserAtHost; + } + call.FromId = from?.Id ?? Guid.Empty; - var toSip = sipMessage.ToSipUri.User.IsNumeric() ? sipMessage.ToSipUri.User : sipMessage.ToSipUri.UserAtHost; - var to = _sipRepository.GetRegisteredUserAgents().SingleOrDefault(x => x.SipUri == toSip); - call.ToSip = toSip; + var to = _cachedRegisteredCodecRepository + .GetRegisteredUserAgents() + .FirstOrDefault(x => + (x.SipUri == sipMessage.ToSipUri.User || x.SipUri == sipMessage.ToSipUri.UserAtHost)); + call.ToDisplayName = sipMessage.ToDisplayName; + if (to != null) + { + call.ToSip = to.SipUri; + call.ToDisplayName = + string.IsNullOrEmpty(to.UserDisplayName) + ? to.DisplayName + : to.UserDisplayName; // TODO: maybe displayname helper should exist here.. check this + } + else if (sipMessage.ToSipUri.User.IsNumeric()) + { + call.ToSip = sipMessage.ToSipUri.User; + call.IsPhoneCall = true; + } + else + { + call.ToSip = sipMessage.ToSipUri.UserAtHost; + } + call.ToId = to?.Id ?? Guid.Empty; call.Started = DateTime.UtcNow; call.CallId = sipMessage.CallId; - call.DlgHashId = sipMessage.HashId; - call.DlgHashEnt = sipMessage.HashEntry; + call.DialogHashId = sipMessage.HashId; + call.DialogHashEnt = sipMessage.HashEntry; call.Updated = DateTime.UtcNow; call.ToTag = sipMessage.ToTag; call.FromTag = sipMessage.FromTag; - call.IsPhoneCall = sipMessage.FromSipUri.User.IsNumeric() || sipMessage.ToSipUri.User.IsNumeric(); + call.SDP = sipMessage.Sdp; - _callRepository.UpdateCall(call); - return SipMessageResult(SipEventChangeStatus.CallStarted, call.Id); + _cachedCallRepository.UpdateCall(call); + + return SipMessageResult(SipEventChangeStatus.CallStarted, call.Id, call.FromSip); } public SipEventHandlerResult CloseCall(SipDialogMessage sipMessage) { - log.Debug("Closing call with id:\"{0}\", hash id:\"{1}\", hash entry:\"{2}\"", sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); + //_logger.LogDebug("Closing call with id:{0}, hash id:{1}, hash entry:{2}", sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); try { - CallInfo call = _callRepository.GetCallInfo(sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); + CallInfo call = _cachedCallRepository.GetCallInfo(sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); if (call == null) { - log.Warn("Unable to find call with call id: {0}, hash id:{1}, hash entry:{2}", sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); + _logger.LogWarning("Unable to find call with call id:{0}, hash id:{1}, hash entry:{2}", sipMessage.CallId, sipMessage.HashId, sipMessage.HashEntry); return NothingChangedResult; } if (call.Closed) { - log.Warn("Call with call id: {0} already closed", sipMessage.CallId); + _logger.LogWarning("Call with call id:{0} already closed", sipMessage.CallId); return NothingChangedResult; } - _callRepository.CloseCall(call.Id); - return SipMessageResult(SipEventChangeStatus.CallClosed, call.Id); + _cachedCallRepository.CloseCall(call.Id); + return SipMessageResult(SipEventChangeStatus.CallClosed, call.Id, call.FromSipAddress); } catch (Exception ex) { - log.Error(ex, "Error while closing call with call id: {0}", sipMessage.CallId); + _logger.LogError(ex, "Error while closing call with call id:{0}", sipMessage.CallId); return NothingChangedResult; } } @@ -221,6 +262,6 @@ public SipEventHandlerResult CloseCall(SipDialogMessage sipMessage) private SipEventHandlerResult NothingChangedResult => SipMessageResult(SipEventChangeStatus.NothingChanged); private SipEventHandlerResult SipMessageResult(SipEventChangeStatus status) { return new SipEventHandlerResult() { ChangeStatus = status }; } private SipEventHandlerResult SipMessageResult(SipEventChangeStatus status, Guid id) { return new SipEventHandlerResult() { ChangeStatus = status, ChangedObjectId = id }; } - + private SipEventHandlerResult SipMessageResult(SipEventChangeStatus status, Guid id, string sipAddress) { return new SipEventHandlerResult() { ChangeStatus = status, ChangedObjectId = id, SipAddress = sipAddress }; } } } diff --git a/CCM.Core/app.config b/CCM.Core/app.config deleted file mode 100644 index b50b547b..00000000 --- a/CCM.Core/app.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - -
- - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.Core/packages.config b/CCM.Core/packages.config deleted file mode 100644 index 93dbf7e3..00000000 --- a/CCM.Core/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.Data/CCM.Data.csproj b/CCM.Data/CCM.Data.csproj index 669c507d..f1b22771 100644 --- a/CCM.Data/CCM.Data.csproj +++ b/CCM.Data/CCM.Data.csproj @@ -1,181 +1,23 @@ - - - + + - Debug - AnyCPU - {C61B9F30-07FC-4739-BDD7-9E880D1A6F4B} - Library - Properties - CCM.Data - CCM.Data - v4.6.2 - 512 - ..\ - true - 7081803c - + netstandard2.1 + 8.0 - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\Production\ - - - - ..\packages\AutoMapper.6.2.2\lib\net45\AutoMapper.dll - - - ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll - - - ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll - - - ..\packages\LazyCache.0.7.1.44\lib\net45\LazyCache.dll - True - - - False - ..\packages\Microsoft.AspNet.Identity.Core.1.0.0\lib\net45\Microsoft.AspNet.Identity.Core.dll - - - ..\packages\MySql.Data.6.9.11\lib\net45\MySql.Data.dll - - - ..\packages\MySql.Data.Entity.6.9.11\lib\net45\MySql.Data.Entity.EF6.dll - - - ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\packages\NLog.4.5.3\lib\net45\NLog.dll - - - - - - - - - - - - ..\packages\System.Linq.Dynamic.1.0.4\lib\net40\System.Linq.Dynamic.dll - True - - - - ..\packages\IPNetwork2.2.0.3\lib\net40\System.Net.IPNetwork.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + - - {2b04cc56-7dfe-40f0-ba17-21d8b93e0b75} - CCM.Core - + - - - - - \ No newline at end of file + + diff --git a/CCM.Data/CCMDbContext.cs b/CCM.Data/CCMDbContext.cs index ae9c0c8d..9a883495 100644 --- a/CCM.Data/CCMDbContext.cs +++ b/CCM.Data/CCMDbContext.cs @@ -25,14 +25,12 @@ */ using System; -using System.Configuration; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; using System.Threading; using CCM.Core.Cache; using CCM.Data.Entities; using CCM.Data.Entities.Base; -using CCM.Data.Entities.DocumentDb; using LazyCache; using NLog; @@ -43,35 +41,41 @@ public class CcmDbContext : DbContext private readonly IAppCache _cache; protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public CcmDbContext(IAppCache cache) + public CcmDbContext(DbContextOptions options, IAppCache cache) : base(options) { _cache = cache; + } - if(ConfigurationManager.AppSettings["Environment"] == "Initiate") - { - //Database create database with any off these - //Database.SetInitializer(new CreateDatabaseIfNotExists()); - //Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); - //Database.SetInitializer(new DropCreateDatabaseAlways()); - } - else + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + // https://docs.microsoft.com/en-us/ef/core/modeling/keys?tabs=fluent-api + + modelBuilder.Entity() + .HasKey(c => new { c.ProfileGroupId, c.ProfileId }); + + modelBuilder.Entity().HasKey(c => new { c.Id }); + + modelBuilder.Entity().HasKey(c => new { c.UserAgentId, c.ProfileId }); + + // CodecType matching Users + modelBuilder.Entity(entity => { - //Database initial creation (off) use for production - Database.SetInitializer(null); - } + entity.HasMany(ct => ct.SipAccounts); + }); } - public DbSet RegisteredSips { get; set; } + public DbSet RegisteredCodecs { get; set; } public DbSet Calls { get; set; } public DbSet Users { get; set; } public DbSet SipAccounts { get; set; } public DbSet Roles { get; set; } public DbSet Settings { get; set; } - public DbSet Profiles { get; set; } + public DbSet Profiles { get; set; } public DbSet ProfileGroups { get; set; } public DbSet ProfileGroupProfileOrders { get; set; } public DbSet Locations { get; set; } public DbSet Owners { get; set; } + public DbSet Categories { get; set; } public DbSet UserAgents { get; set; } public DbSet Regions { get; set; } public DbSet Filters { get; set; } @@ -80,28 +84,13 @@ public CcmDbContext(IAppCache cache) public DbSet UserAgentProfileOrders { get; set; } public DbSet MetaTypes { get; set; } public DbSet CallHistories { get; set; } - public DbSet CodecPresets { get; set; } public DbSet Logs { get; set; } - public DbSet Studios { get; set; } - - // Document Db Entities - public DbSet ApiDefinition { get; set; } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - modelBuilder.Entity() - .HasMany(e => e.CodecPresets) - .WithMany(e => e.UserAgents) - .Map(m => m.ToTable("CodecPresetUserAgents").MapLeftKey("UserAgent_Id").MapRightKey("CodecPreset_Id")); - } - - protected string CurrentUserName() - { - return Thread.CurrentPrincipal?.Identity?.Name ?? "unknown"; - } + /// + /// Overrides the saving method to determine if cache should be cleared and if the + /// changes are relevant to update interested clients about. + /// + /// public override int SaveChanges() { // Set changed/updated info @@ -114,22 +103,18 @@ public override int SaveChanges() { ((EntityBase)entity.Entity).Id = Guid.NewGuid(); ((EntityBase)entity.Entity).CreatedOn = timeStamp; - ((EntityBase)entity.Entity).CreatedBy = CurrentUserName(); } ((EntityBase)entity.Entity).UpdatedOn = timeStamp; - ((EntityBase)entity.Entity).UpdatedBy = CurrentUserName(); } - // Should invalidate cache? - bool shouldInvalidateCache = ChangeTracker.Entries().Any( - x => x.Entity is EntityBase && (x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted) - ); + // Decide if we should invalidate cache + bool shouldInvalidateCache = ChangeTracker.Entries().Any(x => x.Entity is EntityBase && (x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted)); + // Make the actual save var saveChangesResult = base.SaveChanges(); shouldInvalidateCache = shouldInvalidateCache && saveChangesResult > 0; - if (shouldInvalidateCache) { log.Debug("Changes in data saved to database. Trigger full cache update."); @@ -138,6 +123,24 @@ public override int SaveChanges() } return saveChangesResult; + + //try + //{ + // _context.SaveChanges(); + //} + //catch (DbEntityValidationException dbEx) + //{ + // var sb = new StringBuilder(); + // foreach (var validationErrors in dbEx.EntityValidationErrors) + // { + // foreach (var validationError in validationErrors.ValidationErrors) + // { + // sb.AppendLine(string.Format("Property: {0} Error: {1}", + // validationError.PropertyName, validationError.ErrorMessage)); + // } + // } + // throw new Exception(sb.ToString(), dbEx); + //} } } } diff --git a/CCM.Data/Database/ChangeScripts/2018-10-17/settings_data.sql b/CCM.Data/Database/ChangeScripts/2018-10-17/settings_data.sql deleted file mode 100644 index dc6e674c..00000000 --- a/CCM.Data/Database/ChangeScripts/2018-10-17/settings_data.sql +++ /dev/null @@ -1,2 +0,0 @@ -INSERT INTO `Settings` (`Id`, `Name`, `Value`, `Description`, `CreatedBy`, `CreatedOn`, `UpdatedBy`, `UpdatedOn`) VALUES ('F21A6278-4A7C-4FE2-8871-D5BE6FFD7358', 'UseOldKamailioEvent', 'true', 'Ta emot Kamailio-meddelanden på gammalt format', 'root', '2018-10-17 22:52:00', 'root', '2018-10-17 22:52:00'); -INSERT INTO `Settings` (`Id`, `Name`, `Value`, `Description`, `CreatedBy`, `CreatedOn`, `UpdatedBy`, `UpdatedOn`) VALUES ('C2413728-20F1-4443-B13F-9F26D7DCE25D', 'UseSipEvent', 'false', 'Ta emot Kamailio-meddelanden på JSON-format', 'root', '2018-10-17 22:52:00', 'root', '2018-10-17 22:52:00'); diff --git a/CCM.Data/Database/ChangeScripts/2019-07-29/adding_registrar.sql b/CCM.Data/Database/ChangeScripts/2019-07-29/adding_registrar.sql deleted file mode 100644 index 77a9ac10..00000000 --- a/CCM.Data/Database/ChangeScripts/2019-07-29/adding_registrar.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE `uccm`.`registeredsips` -ADD COLUMN `Registrar` LONGTEXT NULL DEFAULT NULL AFTER `User_UserId`; \ No newline at end of file diff --git a/CCM.Data/Database/ChangeScripts/2019-08-27/adding_groupsortweight.sql b/CCM.Data/Database/ChangeScripts/2019-08-27/adding_groupsortweight.sql deleted file mode 100644 index e6ac1bc6..00000000 --- a/CCM.Data/Database/ChangeScripts/2019-08-27/adding_groupsortweight.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE `uccm`.`ProfileGroups` -ADD COLUMN `GroupSortWeight` INT NULL DEFAULT NULL AFTER `Description`; \ No newline at end of file diff --git a/CCM.Data/Database/ExampleData/Dump20190417-cleanup.sql b/CCM.Data/Database/ExampleData/Dump20190417-cleanup.sql deleted file mode 100644 index 67665bb2..00000000 --- a/CCM.Data/Database/ExampleData/Dump20190417-cleanup.sql +++ /dev/null @@ -1,827 +0,0 @@ --- MySQL dump 10.13 Distrib 8.0.13, for Win64 (x86_64) --- --- Host: localhost Database: ccm --- ------------------------------------------------------ --- Server version 5.7.23-log - - SET NAMES utf8 ; - --- --- Table structure for table `callhistories` --- - -DROP TABLE IF EXISTS `callhistories`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `callhistories` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `CallId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SipCallId` longtext COLLATE utf8mb4_swedish_ci, - `Started` datetime NOT NULL, - `Ended` datetime NOT NULL, - `DlgHashId` longtext COLLATE utf8mb4_swedish_ci, - `DlgHashEnt` longtext COLLATE utf8mb4_swedish_ci, - `ToTag` longtext COLLATE utf8mb4_swedish_ci, - `FromTag` longtext COLLATE utf8mb4_swedish_ci, - `FromId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromSip` longtext COLLATE utf8mb4_swedish_ci, - `FromUsername` longtext COLLATE utf8mb4_swedish_ci, - `FromDisplayName` longtext COLLATE utf8mb4_swedish_ci, - `FromComment` longtext COLLATE utf8mb4_swedish_ci, - `FromLocationId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromLocationName` longtext COLLATE utf8mb4_swedish_ci, - `FromLocationComment` longtext COLLATE utf8mb4_swedish_ci, - `FromLocationShortName` longtext COLLATE utf8mb4_swedish_ci, - `FromCodecTypeId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromCodecTypeName` longtext COLLATE utf8mb4_swedish_ci, - `FromCodecTypeColor` longtext COLLATE utf8mb4_swedish_ci, - `FromOwnerId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromOwnerName` longtext COLLATE utf8mb4_swedish_ci, - `FromRegionId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromRegionName` longtext COLLATE utf8mb4_swedish_ci, - `FromUserAgentHead` longtext COLLATE utf8mb4_swedish_ci, - `ToId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToSip` longtext COLLATE utf8mb4_swedish_ci, - `ToUsername` longtext COLLATE utf8mb4_swedish_ci, - `ToDisplayName` longtext COLLATE utf8mb4_swedish_ci, - `ToComment` longtext COLLATE utf8mb4_swedish_ci, - `ToLocationId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToLocationName` longtext COLLATE utf8mb4_swedish_ci, - `ToLocationComment` longtext COLLATE utf8mb4_swedish_ci, - `ToLocationShortName` longtext COLLATE utf8mb4_swedish_ci, - `ToCodecTypeId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToCodecTypeName` longtext COLLATE utf8mb4_swedish_ci, - `ToCodecTypeColor` longtext COLLATE utf8mb4_swedish_ci, - `ToOwnerId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToOwnerName` longtext COLLATE utf8mb4_swedish_ci, - `ToRegionId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToRegionName` longtext COLLATE utf8mb4_swedish_ci, - `ToUserAgentHead` longtext COLLATE utf8mb4_swedish_ci, - `IsPhoneCall` tinyint(4) NOT NULL, - PRIMARY KEY (`Id`), - KEY `CIX_CallHistories_Ended` (`Ended`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `callhistories` --- - -LOCK TABLES `callhistories` WRITE; -/*!40000 ALTER TABLE `callhistories` DISABLE KEYS */; -/*!40000 ALTER TABLE `callhistories` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `calls` --- - -DROP TABLE IF EXISTS `calls`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `calls` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SipCallID` longtext COLLATE utf8mb4_swedish_ci, - `DlgHashId` longtext COLLATE utf8mb4_swedish_ci, - `DlgHashEnt` longtext COLLATE utf8mb4_swedish_ci, - `FromId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromUsername` longtext COLLATE utf8mb4_swedish_ci, - `FromDisplayName` varchar(200) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `ToId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToUsername` longtext COLLATE utf8mb4_swedish_ci, - `ToDisplayName` varchar(200) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Started` datetime NOT NULL, - `Updated` datetime NOT NULL, - `Closed` tinyint(4) NOT NULL, - `State` int(11) DEFAULT NULL, - `ToTag` longtext COLLATE utf8mb4_swedish_ci, - `FromTag` longtext COLLATE utf8mb4_swedish_ci, - `IsPhoneCall` tinyint(4) NOT NULL, - PRIMARY KEY (`Id`), - KEY `IX_Closed` (`Closed`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `calls` --- - -LOCK TABLES `calls` WRITE; -/*!40000 ALTER TABLE `calls` DISABLE KEYS */; -INSERT INTO `calls` VALUES ('01563703-f728-427c-ad19-3e12afd006c4','98MToIWW3kETbtg3sHDibPM1mPjLSuWT','1060','2446','0324949f-42ed-499e-af3c-8dc1b9697ef1','studio-pool-001@sipdomain.com','Studio pool 1','136D9F77-CA80-49D3-BC27-02B77EE3B644','john.doe@sipdomain.com','John Doe','2019-02-11 17:06:59','2019-02-11 17:06:59',0,0,'','.jEnQGVuZTiH1spqxqwodXt3SwutsC84',0),('11d55837-0942-4032-ad9e-4ac56355b63d','HoAUpjWKlZqFOOq23Ap2T5fk.lqPGUQt','4376','1631','21ABB1AD-38B6-4211-9098-7F6906752F5E','ob-portable-001@sipdomain.com','OB Portable 1','27CD88DC-5FBC-439F-B470-BFEEE91852F3','studio-pool-002@sipdomain.com','Studio pool 2','2019-03-11 17:06:59','2019-03-11 17:06:59',0,0,'i51TTgEN5Hk9jThG-bnQmpj.5ld5ONg3','1L6vjZliAiaBP7m.vfh4BElhjL7jJZlW',0),('194c74fe-99ae-416d-a072-d294ba094588','-I.lzsaUUEVtZqTPAxLxFtBUTRiPlRDL','7318','2393','4DDBDBEB-89E7-4232-BEA4-748B4D5E7B37','dev-001@sipdomain.com','DEV 001','4e6f8ed4-1d22-46f4-a81a-d6dbc8f581ac','pis.rartsiger@sipdomain.com','Pis Rartsiger','2019-03-11 16:06:59','2019-03-11 16:06:59',0,0,'','ZDNREt36Jw8rprr0obdLW4szC5M2b7pO',0),('7cc8324f-9076-4e88-b873-c9d944b1193c','Rp0h9faDDxap1oWiQuM2Zdp9R88DNZj-','1240','3796','6821859E-53AC-4A3A-A14D-C63495F56655','facility-001@sipdomain.com','Facility 1','00000000-0000-0000-0000-000000000000','020304050','020304050','2019-03-15 12:06:59','2019-03-15 12:06:59',0,0,'as168fd8f7','XJX.vbm5ugNEFD13tj.IgqQN.3L5gVJH',1),('bce5624d-d8cf-486b-b85a-08e08254b0a4','Rp0h9faDDxap1oWiQuM2Zdp9R88DNZj-','1240','3796','7722B5B4-2089-4A0F-9BE9-57B6C89F5312','block-line@sipdomain.com','Block Connection','00000000-0000-0000-0000-000000000000','0700128752','0700128752','2019-03-15 12:06:59','2019-03-15 12:06:59',0,0,'','XJX.vbm5ugNEFD13tj.IgqQN.3L5gVJH',1),('c5d01b65-11df-4ec2-84c1-19e354ef4342','scXSCBr.GhjASSXHi7zWfFMpKkhBMLwI','3327','2341','9ec856fa-cc47-4031-8882-9a897fb2770c','local-department@sipdomain.com','Local Department','00000000-0000-0000-0000-000000000000','08562712312','08562712312','2019-02-15 12:06:59','2019-02-15 12:06:59',0,0,'','RxpfiYjMVhKpTuPh-N8qgdz0E4FWsh6c',1),('f49990ad-10a2-4bae-b85b-fced14f33123','Wb6lOHdCvSPXVbaiurX9gRueKSCbqZpo','2727','1581','6d19425f-6a23-404f-9854-3f9dc55bde3b','backpack-001@sipdomain.com','Backpack 1','974A8AA1-DA5F-4148-BAB0-FBC2BD70B868','tim.johnsson@@sipdomain.com','Tim Johnsson','2019-03-10 10:06:59','2019-03-10 10:06:59',0,0,'fx4wJKrbA55vQsz2Qs4hLdmGO1cLjq2U','kfelgXH.pZfrckItICHNwlxJPQqEmL2B',0),('fa04bfc1-5c16-46e4-8988-150f0d22049d','q58NoXa20zcXzxHBEEHV0Vy','699','3157','A4F083D7-327F-4490-A19D-474845E06946','lisa.fredriksen@sipdomain.com','Lisa Fredriksen','AE3EE31E-9B5C-49F2-9624-F90EB41CDD8B','mike.golden@sipdomain.com','Mike Golden','2019-03-12 10:06:59','2019-03-12 10:06:59',0,0,'OM7WgnlKBhfSHWFynXp3RPltIsLTAw7w','4mX3Hec79H22j',0),('ff1d5bf6-e1dc-404c-b90a-bdd26b941e21','3wAjka3YFcY0qsHF0s3oHE6hKJ3vDICd','2249','971','BDEB2094-A9B1-49CB-8722-5557C89AFC1C','miranda.stewart@sipdomain.com','Miranda Stewart','D029EAD8-2D71-4545-90A0-7CEE5F85E46A','yang.weng@sipdomain.com','Yang Weng','2019-02-12 10:06:59','2019-02-12 10:06:59',0,0,'','V9iCZFAOUOdDNX-zRJ.DN0WV5yQ0LBvm',0); -/*!40000 ALTER TABLE `calls` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `ccmusers` --- - -DROP TABLE IF EXISTS `ccmusers`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `ccmusers` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserName` longtext COLLATE utf8mb4_swedish_ci, - `FirstName` longtext COLLATE utf8mb4_swedish_ci, - `LastName` longtext COLLATE utf8mb4_swedish_ci, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `PasswordHash` longtext COLLATE utf8mb4_swedish_ci, - `Salt` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `Role_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IX_CcmUsers_Role_RoleId` (`Role_Id`), - CONSTRAINT `FK_CcmUsers_Roles_RoleId` FOREIGN KEY (`Role_Id`) REFERENCES `roles` (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `ccmusers` --- - -LOCK TABLES `ccmusers` WRITE; -/*!40000 ALTER TABLE `ccmusers` DISABLE KEYS */; -INSERT INTO `ccmusers` VALUES ('318c0f75-81dc-4455-8808-de53fca5fb34','discovery','Discovery','Test','Access account','kq+3HYdWGXLlrKVtb3Jprg==','CyIGvYj4S+cKfBV3PakHKP9zYaQ=','root','2019-04-15 15:51:44','root','2019-02-03 21:00:54',NULL),('C0E480FC-BD0C-4779-8324-85DD709B7FBE','root','root','Administrator',NULL,'kq+3HYdWGXLlrKVtb3Jprg==','NSVoZlkkdSFnclFCZEhzZyMmXiQ=','root','2019-04-15 15:51:44','root','2018-04-25 07:10:09','93F8370B-3321-42CB-A7BF-856AA8E6446E'); -/*!40000 ALTER TABLE `ccmusers` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `cities` --- - -DROP TABLE IF EXISTS `cities`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `cities` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `cities` --- - -LOCK TABLES `cities` WRITE; -/*!40000 ALTER TABLE `cities` DISABLE KEYS */; -INSERT INTO `cities` VALUES ('03C9DD9D-1A55-4CB4-861A-C837EBDAC859','Berlin','root','2015-04-29 21:57:28','root','2015-12-17 12:58:12'),('15C2F344-551D-4621-B5F0-C6F74F99D35D','Paris','root','2017-06-14 13:15:26','root','2017-06-14 13:15:26'),('91CB9B00-E4B7-4C5B-9603-51792B2623B0','Oslo','root','2015-04-28 12:17:24','root','2015-11-12 14:28:58'),('9588E6AE-01C6-49ED-9DF5-8AAF57D8DDFD','Stockholm','root','2014-11-19 12:54:41','root','2015-05-05 10:45:42'),('C999C4A4-F848-497D-8024-9AFD0CF87352','Helsinki','root','2014-10-22 11:14:12','root','2014-10-22 11:14:12'),('D1DF8E13-86BE-4950-A169-B36A3F16D7E9','New York','root','2015-04-01 19:53:06','root','2015-04-01 19:53:06'),('F614CA9A-B8DD-4CFE-8855-1988C8DDBB38','Los Angeles','root','2015-07-08 14:25:26','root','2016-02-08 09:08:14'); -/*!40000 ALTER TABLE `cities` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `codecpresets` --- - -DROP TABLE IF EXISTS `codecpresets`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `codecpresets` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `codecpresets` --- - -LOCK TABLES `codecpresets` WRITE; -/*!40000 ALTER TABLE `codecpresets` DISABLE KEYS */; -INSERT INTO `codecpresets` VALUES ('076F058C-11BF-416C-84C0-90E43C6F9B6B','Preset 1','root','2015-04-29 08:59:11','root','2015-04-29 08:59:11'),('2789E7A3-CBF6-4434-A1C5-7EF72D718B0A','Preset 7','root','2016-09-22 17:33:43','root','2016-09-22 17:33:43'),('6A6D3983-665C-4E87-BD98-2FBF24C953A0','Preset 6','root','2016-09-22 17:33:38','root','2016-09-22 17:33:38'),('82B6D5C3-79A9-4CD7-B3C7-EE96D9CA1922','Preset 4','root','2016-09-22 17:33:30','root','2016-09-22 17:33:30'),('9B098C2E-06AC-4546-9CBE-377BB3A30555','Preset 5','root','2016-09-22 17:33:35','root','2016-09-22 17:33:35'),('C3B8AD85-0E26-41A9-8125-4448A77431B6','Preset 2','root','2015-04-29 08:59:15','root','2015-04-29 08:59:15'),('D8C7DC2F-79AB-434C-BE03-F2F3830D0717','Preset 3','root','2016-09-22 17:33:18','root','2016-09-22 17:33:18'),('F225F656-3DFA-4A7A-A876-9B35C60F177B','Preset 8','root','2016-09-22 17:33:55','root','2016-09-22 17:33:55'); -/*!40000 ALTER TABLE `codecpresets` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `codecpresetuseragents` --- - -DROP TABLE IF EXISTS `codecpresetuseragents`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `codecpresetuseragents` ( - `CodecPreset_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserAgent_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - PRIMARY KEY (`CodecPreset_Id`,`UserAgent_Id`), - KEY `IX_CodecPreset_CodecPresetId` (`CodecPreset_Id`), - KEY `IX_UserAgent_UserAgentId` (`UserAgent_Id`), - CONSTRAINT `FK_CodecPresetUserAgents_CodecPresetId` FOREIGN KEY (`CodecPreset_Id`) REFERENCES `codecpresets` (`Id`) ON DELETE CASCADE, - CONSTRAINT `FK_CodecPresetUserAgents_UserAgentId` FOREIGN KEY (`UserAgent_Id`) REFERENCES `useragents` (`Id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `codecpresetuseragents` --- - -LOCK TABLES `codecpresetuseragents` WRITE; -/*!40000 ALTER TABLE `codecpresetuseragents` DISABLE KEYS */; -INSERT INTO `codecpresetuseragents` VALUES ('076F058C-11BF-416C-84C0-90E43C6F9B6B','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('076F058C-11BF-416C-84C0-90E43C6F9B6B','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('2789E7A3-CBF6-4434-A1C5-7EF72D718B0A','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('2789E7A3-CBF6-4434-A1C5-7EF72D718B0A','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('6A6D3983-665C-4E87-BD98-2FBF24C953A0','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('6A6D3983-665C-4E87-BD98-2FBF24C953A0','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('82B6D5C3-79A9-4CD7-B3C7-EE96D9CA1922','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('82B6D5C3-79A9-4CD7-B3C7-EE96D9CA1922','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('9B098C2E-06AC-4546-9CBE-377BB3A30555','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('9B098C2E-06AC-4546-9CBE-377BB3A30555','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('C3B8AD85-0E26-41A9-8125-4448A77431B6','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('C3B8AD85-0E26-41A9-8125-4448A77431B6','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('D8C7DC2F-79AB-434C-BE03-F2F3830D0717','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('D8C7DC2F-79AB-434C-BE03-F2F3830D0717','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('F225F656-3DFA-4A7A-A876-9B35C60F177B','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('F225F656-3DFA-4A7A-A876-9B35C60F177B','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'); -/*!40000 ALTER TABLE `codecpresetuseragents` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `codectypes` --- - -DROP TABLE IF EXISTS `codectypes`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `codectypes` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `Color` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `codectypes` --- - -LOCK TABLES `codectypes` WRITE; -/*!40000 ALTER TABLE `codectypes` DISABLE KEYS */; -INSERT INTO `codectypes` VALUES ('1488C1A6-B6C2-498E-9E85-8F80CFE4DD0C','Backpack','#854f4f','root','2015-07-09 07:20:37','root','2017-01-31 14:36:09'),('176B09ED-38EE-49AD-9FCD-922AC93CA71D','External','#ffc700','root','2014-09-16 12:12:10','root','2014-11-19 09:11:53'),('2FDB03E3-5E28-4640-A609-1B2098C8819C','Virtual','#a73cd9','root','2017-07-28 09:04:04','root','2017-07-28 09:04:04'),('531C49AF-4ED1-4E32-851F-482748B1259F','Studio','#00abff','root','2014-09-16 12:11:38','root','2017-01-31 14:34:02'),('63A48BAC-1C58-4E84-9BC3-6DD8494B45D5','Development','#e74c3c','root','2014-09-16 12:12:51','root','2014-11-19 09:12:38'),('675EBEC4-2F0A-46CE-880C-FD0B50BC7CA3','Pool-codecs','#d1a229','root','2017-07-28 09:08:33','root','2017-07-28 09:08:33'),('794B9AE5-FEF6-4232-BF85-DBB9DAD23F96','National service','#000000','root','2017-03-09 12:30:42','root','2017-03-09 12:40:45'),('7AE664E7-551D-4ED5-A394-BD9BBB3CC33F','Trucks','#e53ce7','root','2014-10-22 06:47:35','root','2014-11-19 09:12:03'),('96b76f87-2216-4561-9b74-609554b4deaf','Correspondents','#565656','root','2017-11-09 09:12:47','root','2017-11-09 09:13:06'),('9EA80A94-C092-4FBD-8858-9B5DA446F0ED','Phones','#9685b3','root','2017-08-10 11:54:07','root','2017-08-10 11:54:07'),('9FBE2AA7-0080-45A4-9B50-07A12C12ED8A','Personal','#ffff00','root','2014-09-16 12:12:33','root','2014-09-16 12:12:33'),('a4f254a9-1c6f-4c30-b0dc-6f4179693206','Intercom','#b27810','root','2018-01-22 12:11:24','root','2018-01-22 12:11:37'),('F50604D9-3442-452A-B600-28D8D1E2F056','Portable','#00ff75','root','2014-09-16 12:10:07','root','2017-01-31 14:35:55'); -/*!40000 ALTER TABLE `codectypes` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `filters` --- - -DROP TABLE IF EXISTS `filters`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `filters` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `PropertyName` longtext COLLATE utf8mb4_swedish_ci, - `Type` longtext COLLATE utf8mb4_swedish_ci, - `FilteringName` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `filters` --- - -LOCK TABLES `filters` WRITE; -/*!40000 ALTER TABLE `filters` DISABLE KEYS */; -INSERT INTO `filters` VALUES ('26B43F3C-47B4-40C1-AFEE-0853DADDF557','Codec type','Name','CodecTypes','CodecTypeName','root','2015-11-24 14:42:38','root','2019-02-06 01:55:28'),('ED60C2B3-50B8-419F-83A9-5E91EB366F79','Region','Name','Regions','RegionName','root','2014-09-16 12:25:24','root','2019-12-16 12:24:33'); -/*!40000 ALTER TABLE `filters` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `locations` --- - -DROP TABLE IF EXISTS `locations`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `locations` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `ShortName` longtext COLLATE utf8mb4_swedish_ci, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `Net_Address_v4` varchar(50) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Cidr` tinyint(4) DEFAULT NULL, - `Net_Address_v6` varchar(200) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Cidr_v6` tinyint(4) DEFAULT NULL, - `CarrierConnectionId` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `City_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Region_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `ProfileGroup_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - PRIMARY KEY (`Id`), - KEY `IX_City_CityId` (`City_Id`), - KEY `IX_Region_RegionId` (`Region_Id`), - KEY `fk_locations_profilegroups1_idx` (`ProfileGroup_Id`), - CONSTRAINT `FK_City_CityId` FOREIGN KEY (`City_Id`) REFERENCES `cities` (`Id`), - CONSTRAINT `FK_Region_RegionId` FOREIGN KEY (`Region_Id`) REFERENCES `regions` (`Id`), - CONSTRAINT `fk_locations_profilegroups1` FOREIGN KEY (`ProfileGroup_Id`) REFERENCES `profilegroups` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `locations` --- - -LOCK TABLES `locations` WRITE; -/*!40000 ALTER TABLE `locations` DISABLE KEYS */; -INSERT INTO `locations` VALUES ('0A10C58F-EF64-455D-B907-3C1273FAF6C1','Office Department 1','Office1',NULL,'121.19.127.192',28,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:49:53','9588E6AE-01C6-49ED-9DF5-8AAF57D8DDFD','015d0eea-83d0-457e-b931-3f40fb38d0c8','632a109c-6365-4e92-bbeb-bf876a321905'),('1FCA4F89-C062-42CB-B4ED-2D4451164312','Arena Fotboll','ArenaF',NULL,'134.25.24.96',28,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:41:47','F614CA9A-B8DD-4CFE-8855-1988C8DDBB38','7cd0bca7-fe2e-4a75-a8da-74a13e770d5a','72c94c45-d876-4209-a361-20612289fd32'),('5F22E14A-793D-4B5F-91B5-B57C3B99F599','Company A','CmpyA',NULL,'211.15.0.0',16,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:51:01','9588e6ae-01c6-49ed-9df5-8aaf57d8ddfd','a1132218-3e57-4471-93a3-0122fbcf8793','60d7b004-762f-4580-a027-852d660d8aaf'),('67E2541A-7870-4CF9-A4F1-6E97B951168A','Deep forest','forest',NULL,'77.220.0.0',16,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:51:38',NULL,'11173c20-a2ee-4fc2-89a5-017e7a2b2b77','E530AD41-72E5-479C-8E47-9BAF9176A2B4'),('79672557-6CBA-471C-82DB-E16AD5EA1D59','Office Department 2','Office2',NULL,'11.230.110.0',24,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:50:32','F614CA9A-B8DD-4CFE-8855-1988C8DDBB38','c930ab2b-545f-4760-8891-1c8d56933084','632a109c-6365-4e92-bbeb-bf876a321905'),('88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','Unspecified','?',NULL,'0.0.0.0',0,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:35:34',NULL,'5f91805d-8841-4d28-b02e-9c5fa3eab450','E530AD41-72E5-479C-8E47-9BAF9176A2B4'); -/*!40000 ALTER TABLE `locations` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `logs` --- - -DROP TABLE IF EXISTS `logs`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `logs` ( - `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `Date` datetime(6) DEFAULT NULL, - `Level` varchar(50) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `LevelValue` int(11) DEFAULT NULL, - `Message` longtext COLLATE utf8mb4_swedish_ci, - `Callsite` varchar(512) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Exception` varchar(512) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Application` varchar(64) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `ActivityId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `logs` --- - -LOCK TABLES `logs` WRITE; -/*!40000 ALTER TABLE `logs` DISABLE KEYS */; -/*!40000 ALTER TABLE `logs` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `metatypes` --- - -DROP TABLE IF EXISTS `metatypes`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `metatypes` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `PropertyName` longtext COLLATE utf8mb4_swedish_ci, - `Type` longtext COLLATE utf8mb4_swedish_ci, - `FullPropertyName` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `metatypes` --- - -LOCK TABLES `metatypes` WRITE; -/*!40000 ALTER TABLE `metatypes` DISABLE KEYS */; -INSERT INTO `metatypes` VALUES ('0A524DB7-041E-405D-AB07-55F97E67B9E6','ShortLocation','ShortName','CCM.Data.Entities.Location','Location.ShortName','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('49D336F1-222F-42B9-8893-66A64B711730','Owner','Name','CCM.Data.Entities.Owner','User.Owner.Name','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('6965B48F-33A0-435C-A3F0-DE033822AAF7','IPAddress','IP','CCM.Data.Entities.RegisteredSip','IP','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('69CA75B3-EFBC-4C66-94D2-8B8E0BA79FFE','Location','Name','CCM.Data.Entities.Location','Location.Name','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('77E9D7A9-0161-4A64-954D-DDD4B131F09D','UserAgentHeader','UserAgentHead','CCM.Data.Entities.RegisteredSip','UserAgentHead','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'); -/*!40000 ALTER TABLE `metatypes` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `owners` --- - -DROP TABLE IF EXISTS `owners`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `owners` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `owners` --- - -LOCK TABLES `owners` WRITE; -/*!40000 ALTER TABLE `owners` DISABLE KEYS */; -INSERT INTO `owners` VALUES ('58790BE0-5607-44A7-9D9F-D763A67891BB','Company','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('F26D4889-11AF-4242-BE87-59034E6A575F','Development','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'); -/*!40000 ALTER TABLE `owners` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `profilegroupprofileorders` --- - -DROP TABLE IF EXISTS `profilegroupprofileorders`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `profilegroupprofileorders` ( - `Profile_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ProfileGroup_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SortIndex` int(11) NOT NULL, - PRIMARY KEY (`Profile_Id`,`ProfileGroup_Id`), - KEY `fk_ProfileGroupProfileOrders_profilegroups1_idx` (`ProfileGroup_Id`), - KEY `fk_ProfileGroupProfileOrders_profile_idx` (`Profile_Id`), - CONSTRAINT `fk_ProfileGroupProfileOrders_profilegroups1` FOREIGN KEY (`ProfileGroup_Id`) REFERENCES `profilegroups` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION, - CONSTRAINT `fk_ProfileGroupProfileOrders_profiles1` FOREIGN KEY (`Profile_Id`) REFERENCES `profiles` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `profilegroupprofileorders` --- - -LOCK TABLES `profilegroupprofileorders` WRITE; -/*!40000 ALTER TABLE `profilegroupprofileorders` DISABLE KEYS */; -INSERT INTO `profilegroupprofileorders` VALUES ('1D765BF5-8FD6-49AE-8D76-5E00564B7552','60d7b004-762f-4580-a027-852d660d8aaf',6),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','632a109c-6365-4e92-bbeb-bf876a321905',6),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','714b88fc-2fc2-467e-a013-4f0d0aa47757',1),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','72c94c45-d876-4209-a361-20612289fd32',6),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','7d842c78-6d8c-4cc5-912f-9ed51c828090',5),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','822928b9-8c47-46d2-8ca7-3e7e7b352933',5),('348A6B99-1201-46CE-98E8-E84553EF0493','60d7b004-762f-4580-a027-852d660d8aaf',7),('348A6B99-1201-46CE-98E8-E84553EF0493','632a109c-6365-4e92-bbeb-bf876a321905',7),('348A6B99-1201-46CE-98E8-E84553EF0493','714b88fc-2fc2-467e-a013-4f0d0aa47757',0),('348A6B99-1201-46CE-98E8-E84553EF0493','72c94c45-d876-4209-a361-20612289fd32',7),('348A6B99-1201-46CE-98E8-E84553EF0493','7d842c78-6d8c-4cc5-912f-9ed51c828090',6),('348A6B99-1201-46CE-98E8-E84553EF0493','822928b9-8c47-46d2-8ca7-3e7e7b352933',6),('348a6b99-1201-46ce-98e8-e84553ef0493','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',1),('3f80bd4b-25c2-436e-a801-e2d30da0f775','632a109c-6365-4e92-bbeb-bf876a321905',9),('3f80bd4b-25c2-436e-a801-e2d30da0f775','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',0),('48A00ADD-4561-49C8-819F-199EFAB11AAB','28c44bae-296f-40b4-affb-277796494567',0),('48A00ADD-4561-49C8-819F-199EFAB11AAB','60d7b004-762f-4580-a027-852d660d8aaf',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','632a109c-6365-4e92-bbeb-bf876a321905',3),('48A00ADD-4561-49C8-819F-199EFAB11AAB','714b88fc-2fc2-467e-a013-4f0d0aa47757',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','72c94c45-d876-4209-a361-20612289fd32',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','7d842c78-6d8c-4cc5-912f-9ed51c828090',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','822928b9-8c47-46d2-8ca7-3e7e7b352933',3),('48a00add-4561-49c8-819f-199efab11aab','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','E530AD41-72E5-479C-8E47-9BAF9176A2B4',1),('706937C9-300F-46EB-A629-DF7A8293FDEE','632a109c-6365-4e92-bbeb-bf876a321905',0),('85A43515-4F55-4503-9697-A2A553EB4B49','28c44bae-296f-40b4-affb-277796494567',1),('85A43515-4F55-4503-9697-A2A553EB4B49','60d7b004-762f-4580-a027-852d660d8aaf',3),('85A43515-4F55-4503-9697-A2A553EB4B49','632a109c-6365-4e92-bbeb-bf876a321905',2),('85A43515-4F55-4503-9697-A2A553EB4B49','72c94c45-d876-4209-a361-20612289fd32',3),('85A43515-4F55-4503-9697-A2A553EB4B49','7d842c78-6d8c-4cc5-912f-9ed51c828090',1),('85a43515-4f55-4503-9697-a2a553eb4b49','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',3),('85A43515-4F55-4503-9697-A2A553EB4B49','E530AD41-72E5-479C-8E47-9BAF9176A2B4',2),('aad8aefd-afc6-4a03-ac5e-d8ae77e857b9','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',6),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','28c44bae-296f-40b4-affb-277796494567',3),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','60d7b004-762f-4580-a027-852d660d8aaf',9),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','632a109c-6365-4e92-bbeb-bf876a321905',8),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','714b88fc-2fc2-467e-a013-4f0d0aa47757',6),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','72c94c45-d876-4209-a361-20612289fd32',9),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','7d842c78-6d8c-4cc5-912f-9ed51c828090',8),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','822928b9-8c47-46d2-8ca7-3e7e7b352933',7),('b2dad012-5746-47fc-a1c9-768a83d7d3ff','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',4),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','E530AD41-72E5-479C-8E47-9BAF9176A2B4',4),('d54f1365-67a9-40bc-a69d-da6b59ce8723','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',5),('F4E80C17-D198-4B74-832E-B08F893C6A76','60d7b004-762f-4580-a027-852d660d8aaf',1),('F4E80C17-D198-4B74-832E-B08F893C6A76','632a109c-6365-4e92-bbeb-bf876a321905',1),('F4E80C17-D198-4B74-832E-B08F893C6A76','72c94c45-d876-4209-a361-20612289fd32',1),('F4E80C17-D198-4B74-832E-B08F893C6A76','7d842c78-6d8c-4cc5-912f-9ed51c828090',0); -/*!40000 ALTER TABLE `profilegroupprofileorders` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `profilegroups` --- - -DROP TABLE IF EXISTS `profilegroups`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `profilegroups` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` varchar(64) COLLATE utf8mb4_swedish_ci NOT NULL, - `Description` longtext COLLATE utf8mb4_swedish_ci, - `GroupSortWeight` int(11) NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime(3) NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime(3) NOT NULL, - PRIMARY KEY (`Id`), - KEY `fk_ProfileGroup_Id_idx` (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `profilegroups` --- - -LOCK TABLES `profilegroups` WRITE; -/*!40000 ALTER TABLE `profilegroups` DISABLE KEYS */; -INSERT INTO `profilegroups` VALUES ('28c44bae-296f-40b4-affb-277796494567','Wi-Fi',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('60d7b004-762f-4580-a027-852d660d8aaf','Local Office',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('632a109c-6365-4e92-bbeb-bf876a321905','Studio',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('714b88fc-2fc2-467e-a013-4f0d0aa47757','Satellite ',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('72c94c45-d876-4209-a361-20612289fd32','Sport',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('7d842c78-6d8c-4cc5-912f-9ed51c828090','Unspecified internal',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('822928b9-8c47-46d2-8ca7-3e7e7b352933','Portable',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c','Backpack',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'), -('E530AD41-72E5-479C-8E47-9BAF9176A2B4','Unspecified',NULL,NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'); -/*!40000 ALTER TABLE `profilegroups` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `profiles` --- - -DROP TABLE IF EXISTS `profiles`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `profiles` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` varchar(64) COLLATE utf8mb4_swedish_ci NOT NULL, - `Description` longtext COLLATE utf8mb4_swedish_ci, - `Sdp` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `SortIndex` int(11) NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `profiles` --- - -LOCK TABLES `profiles` WRITE; -/*!40000 ALTER TABLE `profiles` DISABLE KEYS */; -INSERT INTO `profiles` VALUES ('1D765BF5-8FD6-49AE-8D76-5E00564B7552','Vehicle SAT Stereo','ENH APTx, 24 bit, 576 kbps stereo, FEC 1/6 - original','v=0\no=dev-02 3599992693 3599992693 IN IP4 example.com\ns=Fordon Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96 97\na=rtpmap:96 aptx/48000/2\na=fmtp:96 variant=enhanced; bitresolution=24\na=rtpmap:97 parityfec/32000\na=fmtp:97 5006 IN IP4 203.0.113.12\na=sendrecv\na=ptime:10\na=ebuacip:protp 97 ratio=6\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 90\na=ebuacip:plength 96 10','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',3),('348A6B99-1201-46CE-98E8-E84553EF0493','Vehicle SAT Mono','ENH APTx, 24 bit, 192 kbps mono, FEC 1/6 - original','v=0\no=dev-02 3599993974 3599993974 IN IP4 example.com\ns=Vehicle\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96 97\na=rtpmap:96 aptx/32000/1\na=fmtp:96 variant=enhanced; bitresolution=24\na=rtpmap:97 parityfec/32000\na=fmtp:97 5006 IN IP4 203.0.113.12\na=sendrecv\na=ptime:17\na=ebuacip:protp 97 ratio=6\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 80\na=ebuacip:plength 96 17','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',2),('3F80BD4B-25C2-436E-A801-E2D30DA0F775','Backpack Stereo','OPUS 128 kbps CBR - original','v=0\no=dev-02 3599993476 3599993476 IN IP4 example.com\ns=Portable Mono\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 maxaveragebitrate=64000;stereo=1;sprop-stereo=1;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 220\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',18),('4693a5f6-fe27-4b28-a609-0a04db05bdc8','Fordon SAT Stereo','OPUS 288 kbps CBR - original','v=0\no=dev-02 3599993476 3599993476 IN IP4 example.com\ns=Vehicle Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=1; sprop-stereo=1;maxaveragebitrate=288000;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 150\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',21),('48A00ADD-4561-49C8-819F-199EFAB11AAB','Internet Mono','OPUS 64 kbps mono, FEC inband - original','v=0\r\no=mtu-02 3599993476 3599993476 IN IP4 example.com\r\ns=Internet Mono\r\nc=IN IP4 203.0.113.12\r\nt=0 0\r\nm=audio 5004 RTP/AVP 96\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=64000;cbr=1;useinbandfec=1\r\na=sendrecv\r\na=ptime:20\r\na=ebuacip:jb 0\r\na=ebuacip:jbdef 0 fixed 350\r\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',4),('4D5F1210-7073-48AC-8248-AEA3F48A64C3','Linkbox Stereo','APTX 384 kbps','v=0\no=dev-02 3599993476 3599993476 IN IP4 example.com\ns=Portable Mono\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 maxaveragebitrate=128000;stereo=1;sprop-stereo=1;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 220\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',20),('706937C9-300F-46EB-A629-DF7A8293FDEE','Studio','PCM 24/48 stereo - original','v=0\r\no=default 3599993476 3599993476 IN IP4 example.com\r\ns=Studio\r\nc=IN IP4 203.0.113.12\r\nt=0 0\r\nm=audio 5004 RTP/AVP 96\r\na=rtpmap:96 L24/48000/2\r\na=sendrecv\r\na=ptime:5\r\na=ebuacip:jb 0\r\na=ebuacip:jbdef 0 fixed 6\r\na=ebuacip:plength 96 5','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',0),('85A43515-4F55-4503-9697-A2A553EB4B49','Internet Stereo','OPUS 256 kbps stereo, FEC inband - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Internet Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 maxaveragebitrate=256000;cbr=1;stereo=1;sprop-stereo=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 400\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',19),('AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9','Abroad Stereo','OPUS 192kbps Stereo CBR - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Outside Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=1; sprop-stereo=1;maxaveragebitrate=128000;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 220\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',17),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','Telephone','OPUS 64 kbps mono, G.722, G.711 - original','v=0\no=default 3599993974 3599993974 IN IP4 example.com\ns=Phone\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96 9 8\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=64000;cbr=1;useinbandfec=1\na=rtpmap:9 G722/8000\na=rtpmap:8 PCMA/8000\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 40\na=ebuacip:plength 96 20\na=ebuacip:plength 9 20\na=ebuacip:plength 8 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',6),('c7bf4633-04e9-4030-bbf6-15ac3b9d780d','Fordon SAT Mono','OPUS 144 kbps CBR - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Vehicle Mono Opus\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=144000;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 100\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',22),('d54f1365-67a9-40bc-a69d-da6b59ce8723','Abroad Mono','OPUS 48kbps Mono - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Internet Mono\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=48000;cbr=1;useinbandfec=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 300\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',23),('F4E80C17-D198-4B74-832E-B08F893C6A76','Arenas','ENH APTx, 24 bit, 576 kbps stereo - original','v=0\no=default 3599992693 3599992693 IN IP4 example.com\ns=Sport\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 aptx/48000/2\na=fmtp:96 variant=enhanced; bitresolution=24\na=ptime:10\na=sendrecv\na=ebuacip:plength 96 10\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 80','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',1); -/*!40000 ALTER TABLE `profiles` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `regions` --- - -DROP TABLE IF EXISTS `regions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `regions` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `regions` --- - -LOCK TABLES `regions` WRITE; -/*!40000 ALTER TABLE `regions` DISABLE KEYS */; -INSERT INTO `regions` VALUES ('015D0EEA-83D0-457E-B931-3F40FB38D0C8','Russia','root','2019-02-06 01:27:57','root','2019-04-17 13:34:57'),('11173C20-A2EE-4FC2-89A5-017E7A2B2B77','Europe','root','2019-02-06 01:27:57','root','2019-04-17 13:34:51'),('13F5CE95-7D35-4246-BED6-3961560C23A8','Warszawa','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('214822FF-8D90-45F3-A6B8-789FF87707D1','Unspecified','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('5B3B1DEF-85CC-464B-B64C-11C7D4DF4466','Amsterdam','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('5F91805D-8841-4D28-B02E-9C5FA3EAB450','Other','root','2019-02-06 01:27:57','root','2019-04-17 13:35:05'),('7cd0bca7-fe2e-4a75-a8da-74a13e770d5a','Frankfurt','root','2019-02-06 01:27:57','root','2019-04-17 13:36:00'),('A0282620-3262-464B-80E6-95535A38E858','Stockholm','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('A1132218-3E57-4471-93A3-0122FBCF8793','Milano','root','2019-02-06 01:27:57','root','2019-04-17 13:35:23'),('BD2A7668-E4DF-4515-9D36-6A30D7273764','Istanbul','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('C930AB2B-545F-4760-8891-1C8D56933084','Kairo','root','2019-02-06 01:27:57','root','2019-04-17 13:35:14'),('CBF5F7B9-9784-44E5-92BD-C073CF402543','Madrid','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('CF611ACA-B941-4736-AA07-D459A65A473E','International','root','2019-02-06 01:27:57','root','2019-04-17 13:34:41'),('CFC7C231-5D80-48E6-8B92-95FC8EDF53D1','Geneve','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('F5E3B1BD-44F6-4875-8E7E-479A418D2923','Prag','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'); -/*!40000 ALTER TABLE `regions` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `registeredsips` --- - -DROP TABLE IF EXISTS `registeredsips`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `registeredsips` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SIP` varchar(128) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserAgentHead` longtext COLLATE utf8mb4_swedish_ci, - `Username` longtext COLLATE utf8mb4_swedish_ci, - `DisplayName` longtext COLLATE utf8mb4_swedish_ci, - `Registrar` longtext COLLATE utf8mb4_swedish_ci, - `IP` longtext COLLATE utf8mb4_swedish_ci, - `Port` int(11) NOT NULL, - `RegistrationType` tinyint(4) NOT NULL DEFAULT '0', - `ServerTimeStamp` bigint(20) DEFAULT NULL, - `Updated` datetime NOT NULL, - `Expires` int(11) NOT NULL, - `IsActive` tinyint(4) NOT NULL DEFAULT '0', - `UserAgentId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Location_LocationId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `User_UserId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IX_UserAgentId` (`UserAgentId`), - KEY `IX_Location_LocationId` (`Location_LocationId`), - KEY `IX_User_UserId` (`User_UserId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `registeredsips` --- - -LOCK TABLES `registeredsips` WRITE; -/*!40000 ALTER TABLE `registeredsips` DISABLE KEYS */; -INSERT INTO `registeredsips` VALUES ('02fc8613-6946-4235-bf5a-22477a8b3ef7','pbx@sipdomain.com','Asterisk PBX 11.13.1','pbx@sipdomain.com','PBX Service','registrar1','10.121.194.213',5080,0,1647565332,'2020-01-20 15:15:49',97,0,'391f4e31-9f6e-41c5-a787-1cb0f63035ef','88e3d0de-9cce-4bd4-b7af-7ec20e7ef429','01217de1-9f81-4e67-bfee-97df400c7fa1'),('0324949f-42ed-499e-af3c-8dc1b9697ef1','studio-pool-001@sipdomain.com','Nerea/h2.2.6','studio-pool-001@sipdomain.com','Studio pool 1','registrar1','11.15.154.86',5060,0,1842805239,'2020-01-20 15:15:49',58,0,'4e53c5be-748e-4fd0-9f4b-3461379cf1b4','5f22e14a-793d-4b5f-91b5-b57c3b99f599','01814726-0A9E-4071-8B26-D05DB331EAA9'),('136D9F77-CA80-49D3-BC27-02B77EE3B644','john.doe@sipdomain.com','Blink Pro 4.5.1 (MacOSX)','john.doe@sipdomain.com','John Doe','registrar1','211.15.160.52',5090,0,1505200163,'2020-01-20 15:15:49',124,0,'28C8D173-67EE-40A4-8850-A28133A388C2','5F22E14A-793D-4B5F-91B5-B57C3B99F599','01DA6EF7-FE8B-4D59-9B45-8DAF843F45AA'),('21ABB1AD-38B6-4211-9098-7F6906752F5E','ob-portable-001@sipdomain.com','Quantum/3.5.0a','ob-portable-001@sipdomain.com','OB Portable 1','registrar1','138.128.94.34',5060,0,1460636422,'2020-01-20 15:15:49',0,0,'6FE0FD55-CAFB-4D57-8818-8A289511C4B5','5F22E14A-793D-4B5F-91B5-B57C3B99F599','042b9cd3-e2fe-4055-846f-4ea8df1f9a61'),('27CD88DC-5FBC-439F-B470-BFEEE91852F3','studio-pool-002@sipdomain.com','QuantumST/3.5.0a','studio-pool-002@sipdomain.com','Studio pool 2','registrar1','121.19.127.234',5060,0,1458657572,'2020-01-20 15:15:49',0,0,'834EA3A6-1F25-4F4B-961F-97ECFE351BB8','0A10C58F-EF64-455D-B907-3C1273FAF6C1','05F57AD6-16D0-421B-9618-36A1CC799EC3'),('4DDBDBEB-89E7-4232-BEA4-748B4D5E7B37','dev-001@sipdomain.com','ProntoNetLCv6.8.4','dev-001@sipdomain.com','DEV 001','registrar1','159.203.47.235',1148,0,1457544803,'2020-01-20 15:15:49',0,0,'4444026F-3854-4AAB-95DF-E182D5EB5B36','88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','063F5B48-6A59-4632-8CF8-0BC93EB44FFA'),('4e6f8ed4-1d22-46f4-a81a-d6dbc8f581ac','pis.rartsiger@sipdomain.com','snom710/8.7.5.35','pis.rartsiger@sipdomain.com','Pis Rartsiger','registrar1','11.230.110.132',32768,0,1545220316,'2020-01-20 15:15:49',124,0,'ba5b9883-ed3e-46c5-b34b-9f6fb5edcc63','79672557-6cba-471c-82db-e16ad5ea1d59','0758335C-9F9F-46DA-A227-2FEE087D73EC'),('6821859E-53AC-4A3A-A14D-C63495F56655','facility-001@sipdomain.com','ME-UMAC-C/5.18','facility-001@sipdomain.com','Facility 1','registrar1','121.15.24.106',5060,0,1498030497,'2020-01-20 15:15:49',60,0,'C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','1FCA4F89-C062-42CB-B4ED-2D4451164312','083d21ec-9fdd-434c-9e7b-4611f7ec9e6b'),('6d19425f-6a23-404f-9854-3f9dc55bde3b','backpack-001@sipdomain.com','baresip v0.5.10 (arm6/linux)','backpack-001@sipdomain.com','Backpack 1','registrar1','11.29.194.136',5060,0,1547565332,'2020-01-20 15:15:49',58,0,'a3e19e66-736b-4a49-86a7-6985ba997b43','5f22e14a-793d-4b5f-91b5-b57c3b99f599','09375200-7204-421f-9d12-eca29d75e166'),('7722B5B4-2089-4A0F-9BE9-57B6C89F5312','block-line@sipdomain.com','AETA/ScoopTeam aoip-v2.00.0012','block-line@sipdomain.com','Block Connection','registrar1','8.30.194.202',19914,0,1496056496,'2020-01-20 15:15:49',88,0,NULL,'88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0A420FD3-13D9-4001-8F2F-B605F966FF70'),('86c2eb72-2094-4741-9b32-28c03d66181c','traffic-report@sipdomain.com','Bria 4 release 4.7.0 stamp 83078','traffic-report@sipdomain.com','Traffic report','registrar1','50.23.161.172',55720,0,1527604307,'2020-01-20 15:15:49',124,0,'f310f519-08c7-499a-a102-c02b7a35485c','5f22e14a-793d-4b5f-91b5-b57c3b99f599','0a6d003c-fb20-4422-8ed7-af292a7100ef'),('974A8AA1-DA5F-4148-BAB0-FBC2BD70B868','tim.johnsson@@sipdomain.com','tSIP 0.01.41.00','tim.johnsson@sipdomain.com','Tim Johnsson','registrar1','123.5.65.190',61664,0,1459004730,'2020-01-20 15:15:49',-1,0,NULL,'88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0AB7C5E2-8AAA-4BFE-B20B-B812BB5F9439'),('9ec856fa-cc47-4031-8882-9a897fb2770c','local-department@sipdomain.com','ME-UMAC2-M/1.38','local-department@sipdomain.com','Local Department','registrar1','209.45.255.122',49483,0,1547130528,'2020-01-20 15:15:49',25,0,'ee394836-e09b-4cc5-91a6-0589befc61cf','88e3d0de-9cce-4bd4-b7af-7ec20e7ef429','0ACC8882-E7A2-4712-ADF0-8D50D8E99609'),('A4F083D7-327F-4490-A19D-474845E06946','lisa.fredriksen@sipdomain.com','LUCI Live SR_3.1.11_iPhone8.1_(iOS_10.3)','lisa.fredriksen@sipdomain.com','Lisa Fredriksen','registrar1','77.220.40.116',31369,0,1491570054,'2020-01-20 15:15:49',0,0,'F4950560-BF03-4C01-81C5-435C53587238','67E2541A-7870-4CF9-A4F1-6E97B951168A','0B387A2B-3767-4829-9458-7B1FDA6E4210'),('AE3EE31E-9B5C-49F2-9624-F90EB41CDD8B','mike.golden@sipdomain.com','MicroSIP/3.15.1','mike.golden@sipdomain.com','Mike Golden','registrar1','130.101.32.162',62471,0,1491029728,'2020-01-20 15:15:49',0,0,NULL,'88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0D7F7ED5-2C04-451D-821D-24532995CD99'),('BDEB2094-A9B1-49CB-8722-5557C89AFC1C','miranda.stewart@sipdomain.com','Comrex SIP','miranda.stewart@sipdomain.com','Miranda Stewart','registrar1','129.77.137.161',5060,0,1459519384,'2020-01-20 15:15:49',0,0,'A2118E5F-B0E1-4B31-BB43-02379801F0E0','88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0dc9a4e1-4487-4392-b4d7-f96053b82f3a'),('D029EAD8-2D71-4545-90A0-7CEE5F85E46A','yang.weng@sipdomain.com','Linphone/3.9.1 (belle-sip/1.4.2)','yang.weng@sipdomain.com','Yang Weng','registrar1','82.65.161.37',5060,0,1484752648,'2020-01-20 15:15:49',0,0,'18B9E420-7918-44B9-B7E2-B4698E6035BD','5F22E14A-793D-4B5F-91B5-B57C3B99F599','0e55a76e-ca12-4455-9327-31c9761a6f96'); -/*!40000 ALTER TABLE `registeredsips` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `roles` --- - -DROP TABLE IF EXISTS `roles`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `roles` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `roles` --- - -LOCK TABLES `roles` WRITE; -/*!40000 ALTER TABLE `roles` DISABLE KEYS */; -INSERT INTO `roles` VALUES ('0C5F9098-A09A-44B1-8603-2DEC46E8E7EF','Remote','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('88783AD0-F83F-40F0-AB46-F12938DFE68A','AccountManager','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('93F8370B-3321-42CB-A7BF-856AA8E6446E','Admin','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'); -/*!40000 ALTER TABLE `roles` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `settings` --- - -DROP TABLE IF EXISTS `settings`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `settings` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `Value` longtext COLLATE utf8mb4_swedish_ci, - `Description` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `settings` --- - -LOCK TABLES `settings` WRITE; -/*!40000 ALTER TABLE `settings` DISABLE KEYS */; -INSERT INTO `settings` VALUES ('3EF6CC4F-4343-4CD9-9FF3-04447118AC65','CodecControlActive','true','Codec control on/off ','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('A2570519-60D4-49B8-A32A-4FDC7B194BB1','SIPDomain','sipdomain.com','The SIP domain','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('C2413728-20F1-4443-B13F-9F26D7DCE25D','UseSipEvent','true','Recieve Kamailio-messages in JSON-format','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('D676D91D-B1CF-4F48-B983-1BD9112962D0','MaxRegistrationAge','130','Time in seconds before SIP registration is obsolete','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('EFF88C41-3DDB-4434-A76F-C2BAD39811B0','LatestCallCount','30','Number of closed calls to show','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('F21A6278-4A7C-4FE2-8871-D5BE6FFD7358','UseOldKamailioEvent','false','Recieve Kamailio-messages in old format','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'); -/*!40000 ALTER TABLE `settings` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `sipaccounts` --- - -DROP TABLE IF EXISTS `sipaccounts`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `sipaccounts` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserName` longtext COLLATE utf8mb4_swedish_ci, - `DisplayName` longtext COLLATE utf8mb4_swedish_ci, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `ExtensionNumber` longtext COLLATE utf8mb4_swedish_ci, - `AccountType` int(11) NOT NULL DEFAULT '0', - `IsPoolCodec` tinyint(4) NOT NULL DEFAULT '0', - `AccountLocked` tinyint(4) NOT NULL DEFAULT '0', - `Password` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `CodecType_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Owner_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Region_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IX_SipAccounts_CodecTypeId` (`CodecType_Id`), - KEY `IX_SipAccounts_OwnerId` (`Owner_Id`), - KEY `IX_SipAccounts_RegionId` (`Region_Id`), - CONSTRAINT `FK_SipAccounts_CodecTypeId` FOREIGN KEY (`CodecType_Id`) REFERENCES `codectypes` (`Id`), - CONSTRAINT `FK_SipAccounts_OwnerId` FOREIGN KEY (`Owner_Id`) REFERENCES `owners` (`Id`), - CONSTRAINT `FK_SipAccounts_RegionId` FOREIGN KEY (`Region_Id`) REFERENCES `regions` (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `sipaccounts` --- - -LOCK TABLES `sipaccounts` WRITE; -/*!40000 ALTER TABLE `sipaccounts` DISABLE KEYS */; -INSERT INTO `sipaccounts` VALUES ('01217de1-9f81-4e67-bfee-97df400c7fa1','pbx@sipdomain.com','PBX Service',NULL,NULL,0,0,0,'t3aC1yJ9PJY9Rms','root','2018-03-13 15:05:57','root','2019-04-17 13:29:44','2fdb03e3-5e28-4640-a609-1b2098c8819c','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('01814726-0A9E-4071-8B26-D05DB331EAA9','studio-pool-001@sipdomain.com','Studio pool 1',NULL,NULL,0,1,0,'y5x%!nH7Zb!kObY','root','2016-04-29 07:43:14','root','2019-04-17 13:31:20','531c49af-4ed1-4e32-851f-482748b1259f','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('01DA6EF7-FE8B-4D59-9B45-8DAF843F45AA','john.doe@sipdomain.com','John Doe',NULL,NULL,0,0,0,'hUh3g1Zexqw62o2','root','1900-01-01 00:00:00','root','2019-04-17 13:29:05','9fbe2aa7-0080-45a4-9b50-07a12c12ed8a','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('042b9cd3-e2fe-4055-846f-4ea8df1f9a61','ob-portable-001@sipdomain.com','OB Portable 1',NULL,NULL,0,0,0,'QpysXRPhO8a931F','root','2018-01-22 12:14:44','root','2019-04-17 13:29:30','f50604d9-3442-452a-b600-28d8d1e2f056','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('05F57AD6-16D0-421B-9618-36A1CC799EC3','studio-pool-002@sipdomain.com','Studio pool 2',NULL,NULL,0,1,0,'fzph3i8sgrMIdth','root','2015-09-21 13:01:58','root','2019-04-17 13:31:23','531C49AF-4ED1-4E32-851F-482748B1259F','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('063F5B48-6A59-4632-8CF8-0BC93EB44FFA','dev-001@sipdomain.com','DEV 001',NULL,NULL,0,0,0,'GZSkL1yw6v7q#yj','root','2015-09-25 08:26:15','root','2019-04-17 13:31:13','63a48bac-1c58-4e84-9bc3-6dd8494b45d5','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0758335C-9F9F-46DA-A227-2FEE087D73EC','pis.rartsiger@sipdomain.com','Pis Rartsiger',NULL,NULL,0,0,0,'US!Ew4qPjqSIcVr','root','2015-06-01 10:28:25','root','2019-04-17 13:31:16','9FBE2AA7-0080-45A4-9B50-07A12C12ED8A','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('083d21ec-9fdd-434c-9e7b-4611f7ec9e6b','facility-001@sipdomain.com','Facility 1',NULL,NULL,0,0,0,'yd9VrmhQ7lsjbfV','root','2018-04-25 07:14:50','root','2019-04-17 13:28:59','176b09ed-38ee-49ad-9fcd-922ac93ca71d','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('09375200-7204-421f-9d12-eca29d75e166','backpack-001@sipdomain.com','Backpack 1',NULL,NULL,0,0,0,'ziHP18M7cIEzjNZ','root','2018-08-10 09:00:29','root','2019-04-17 13:30:57','63a48bac-1c58-4e84-9bc3-6dd8494b45d5','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('0A420FD3-13D9-4001-8F2F-B605F966FF70','block-line@sipdomain.com','Block Connection',NULL,NULL,0,0,0,'6p!zOgPQpEXETHz','root','2017-07-28 08:55:28','root','2019-04-17 13:31:09','531c49af-4ed1-4e32-851f-482748b1259f','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0a6d003c-fb20-4422-8ed7-af292a7100ef','traffic-report@sipdomain.com','Traffic report',NULL,NULL,0,0,0,'iebn1H2bU3!4Sgd','root','2018-06-14 09:39:07','root','2019-04-17 13:31:26','2fdb03e3-5e28-4640-a609-1b2098c8819c','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('0AB7C5E2-8AAA-4BFE-B20B-B812BB5F9439','tim.johnsson@sipdomain.com','Tim Johnsson',NULL,NULL,0,0,0,'t7X86fOV7cm#z6g','root','2014-09-30 13:42:14','root','2019-04-17 13:41:09','9FBE2AA7-0080-45A4-9B50-07A12C12ED8A','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0ACC8882-E7A2-4712-ADF0-8D50D8E99609','local-department@sipdomain.com','Local Department',NULL,NULL,0,0,0,'7RosQgKbbtc37c3','root','2017-08-10 14:05:14','root','2019-04-17 13:30:53','176b09ed-38ee-49ad-9fcd-922ac93ca71d','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0B387A2B-3767-4829-9458-7B1FDA6E4210','lisa.fredriksen@sipdomain.com','Lisa Fredriksen',NULL,NULL,0,0,0,'SqDPGP1CyyU7FOS','root','2015-05-21 13:13:36','root','2019-04-17 13:31:00','F50604D9-3442-452A-B600-28D8D1E2F056','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0D7F7ED5-2C04-451D-821D-24532995CD99','mike.golden@sipdomain.com','Mike Golden',NULL,NULL,0,0,0,'KVc4RgYz6I6Xf36','root','2016-01-19 13:11:29','root','2019-04-17 13:29:13','9fbe2aa7-0080-45a4-9b50-07a12c12ed8a','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0dc9a4e1-4487-4392-b4d7-f96053b82f3a','miranda.stewart@sipdomain.com','Miranda Stewart',NULL,NULL,0,0,0,'nCPwOqCId08%ab2','root','2018-04-23 11:39:53','root','2019-04-17 13:29:33','9ea80a94-c092-4fbd-8858-9b5da446f0ed','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('0e55a76e-ca12-4455-9327-31c9761a6f96','yang.weng@sipdomain.com','Yang Weng',NULL,NULL,0,0,0,'f8HD!oqqAr0yogx','root','2018-04-25 07:14:50','root','2019-04-17 13:29:26','f50604d9-3442-452a-b600-28d8d1e2f056','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('c5d987a6-d18d-4c01-aeba-24c728a4ed9b','rogsantestaliasusername@sipdomain.sr.se','Roger Test',NULL,NULL,0,0,0,'Nm4w%L5H%AF99Qh','root','2019-02-04 22:13:09','root','2019-04-17 13:29:51','531c49af-4ed1-4e32-851f-482748b1259f','58790BE0-5607-44A7-9D9F-D763A67891BB','11173c20-a2ee-4fc2-89a5-017e7a2b2b77'); -/*!40000 ALTER TABLE `sipaccounts` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `studios` --- - -DROP TABLE IF EXISTS `studios`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `studios` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `CodecSipAddress` longtext COLLATE utf8mb4_swedish_ci, - `CameraAddress` longtext COLLATE utf8mb4_swedish_ci, - `CameraActive` tinyint(4) NOT NULL, - `CameraUsername` longtext COLLATE utf8mb4_swedish_ci, - `CameraPassword` longtext COLLATE utf8mb4_swedish_ci, - `CameraVideoUrl` longtext COLLATE utf8mb4_swedish_ci, - `CameraImageUrl` longtext COLLATE utf8mb4_swedish_ci, - `CameraPlayAudioUrl` longtext COLLATE utf8mb4_swedish_ci, - `AudioClipNames` longtext COLLATE utf8mb4_swedish_ci, - `InfoText` longtext COLLATE utf8mb4_swedish_ci, - `MoreInfoUrl` longtext COLLATE utf8mb4_swedish_ci, - `NrOfAudioInputs` int(11) NOT NULL, - `AudioInputNames` longtext COLLATE utf8mb4_swedish_ci, - `AudioInputDefaultGain` int(11) NOT NULL, - `NrOfGpos` int(11) NOT NULL, - `GpoNames` longtext COLLATE utf8mb4_swedish_ci, - `InactivityTimeout` int(11) NOT NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `studios` --- - -LOCK TABLES `studios` WRITE; -/*!40000 ALTER TABLE `studios` DISABLE KEYS */; -INSERT INTO `studios` VALUES ('2DF5686C-7097-4DBD-8BD6-1D0D5B428FA7','Studio Test','studio-entrance-sthlm@sipdomain.sr.se','kamera.mycompany.se',0,NULL,NULL,'/mjpg/video.mjpg?camera=1&resolution=640x480&fps=25&compression=30','/axis-cgi/jpg/image.cgi?camera=1','/axis-cgi/playclip.cgi','Welcome instructions, Ask them to call','To see the camera use Chrome or Firefox. Always read the manual before first use.\r\n','http://www.mycompany.se/manual.pdf',3,'Red, Blue, Yellow',-30,1,'Green light',15,'root','2017-02-12 21:30:31','root','2019-02-06 01:53:56'); -/*!40000 ALTER TABLE `studios` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `useragentprofileorders` --- - -DROP TABLE IF EXISTS `useragentprofileorders`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `useragentprofileorders` ( - `UserAgentId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ProfileId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SortIndex` int(11) NOT NULL, - PRIMARY KEY (`UserAgentId`,`ProfileId`), - KEY `IX_ProfileId` (`ProfileId`), - KEY `IX_UserAgentId` (`UserAgentId`), - CONSTRAINT `FK_dbo.UserAgentProfileOrders_dbo.Profiles_ProfileId` FOREIGN KEY (`ProfileId`) REFERENCES `profiles` (`Id`) ON DELETE CASCADE, - CONSTRAINT `FK_dbo.UserAgentProfileOrders_dbo.UserAgents_UserAgentId` FOREIGN KEY (`UserAgentId`) REFERENCES `useragents` (`Id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `useragentprofileorders` --- - -LOCK TABLES `useragentprofileorders` WRITE; -/*!40000 ALTER TABLE `useragentprofileorders` DISABLE KEYS */; -INSERT INTO `useragentprofileorders` VALUES ('12c6d8c1-0ac0-46f3-b6fd-53ded04ab388','48a00add-4561-49c8-819f-199efab11aab',0),('12c6d8c1-0ac0-46f3-b6fd-53ded04ab388','b2dad012-5746-47fc-a1c9-768a83d7d3ff',1),('18B9E420-7918-44B9-B7E2-B4698E6035BD','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('18B9E420-7918-44B9-B7E2-B4698E6035BD','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',1),('1973A2C9-F7F2-43B3-A4F4-795502ADEDAF','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('2576E6D7-F490-4712-B07D-871DFC140A66','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('2576E6D7-F490-4712-B07D-871DFC140A66','348A6B99-1201-46CE-98E8-E84553EF0493',2),('2576E6D7-F490-4712-B07D-871DFC140A66','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('2576E6D7-F490-4712-B07D-871DFC140A66','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('2576E6D7-F490-4712-B07D-871DFC140A66','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('2576E6D7-F490-4712-B07D-871DFC140A66','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('28C8D173-67EE-40A4-8850-A28133A388C2','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('311dfec3-e460-4a45-84a8-26e866b04101','48a00add-4561-49c8-819f-199efab11aab',0),('311dfec3-e460-4a45-84a8-26e866b04101','b2dad012-5746-47fc-a1c9-768a83d7d3ff',1),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','348A6B99-1201-46CE-98E8-E84553EF0493',3),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','48A00ADD-4561-49C8-819F-199EFAB11AAB',5),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','4D5F1210-7073-48AC-8248-AEA3F48A64C3',14),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','706937C9-300F-46EB-A629-DF7A8293FDEE',1),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','85A43515-4F55-4503-9697-A2A553EB4B49',13),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',12),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',7),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','F4E80C17-D198-4B74-832E-B08F893C6A76',2),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','348A6B99-1201-46CE-98E8-E84553EF0493',1),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('391F4E31-9F6E-41C5-A787-1CB0F63035EF','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('4444026F-3854-4AAB-95DF-E182D5EB5B36','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('4444026F-3854-4AAB-95DF-E182D5EB5B36','348A6B99-1201-46CE-98E8-E84553EF0493',2),('4444026F-3854-4AAB-95DF-E182D5EB5B36','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('4444026F-3854-4AAB-95DF-E182D5EB5B36','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','348A6B99-1201-46CE-98E8-E84553EF0493',2),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','4D5F1210-7073-48AC-8248-AEA3F48A64C3',12),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','85A43515-4F55-4503-9697-A2A553EB4B49',9),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',10),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',11),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','348A6B99-1201-46CE-98E8-E84553EF0493',3),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','3F80BD4B-25C2-436E-A801-E2D30DA0F775',13),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','48A00ADD-4561-49C8-819F-199EFAB11AAB',5),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('4e53c5be-748e-4fd0-9f4b-3461379cf1b4','85a43515-4f55-4503-9697-a2a553eb4b49',2),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',7),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('50fd3e73-a4fd-48e7-9613-88369aeb866f','1d765bf5-8fd6-49ae-8d76-5e00564b7552',3),('50fd3e73-a4fd-48e7-9613-88369aeb866f','348a6b99-1201-46ce-98e8-e84553ef0493',2),('50fd3e73-a4fd-48e7-9613-88369aeb866f','3f80bd4b-25c2-436e-a801-e2d30da0f775',13),('50fd3e73-a4fd-48e7-9613-88369aeb866f','4693a5f6-fe27-4b28-a609-0a04db05bdc8',16),('50fd3e73-a4fd-48e7-9613-88369aeb866f','48a00add-4561-49c8-819f-199efab11aab',4),('50fd3e73-a4fd-48e7-9613-88369aeb866f','4d5f1210-7073-48ac-8248-aea3f48a64c3',15),('50fd3e73-a4fd-48e7-9613-88369aeb866f','706937c9-300f-46eb-a629-df7a8293fdee',0),('50fd3e73-a4fd-48e7-9613-88369aeb866f','85a43515-4f55-4503-9697-a2a553eb4b49',14),('50fd3e73-a4fd-48e7-9613-88369aeb866f','aad8aefd-afc6-4a03-ac5e-d8ae77e857b9',12),('50fd3e73-a4fd-48e7-9613-88369aeb866f','b2dad012-5746-47fc-a1c9-768a83d7d3ff',6),('50fd3e73-a4fd-48e7-9613-88369aeb866f','c7bf4633-04e9-4030-bbf6-15ac3b9d780d',17),('50fd3e73-a4fd-48e7-9613-88369aeb866f','d54f1365-67a9-40bc-a69d-da6b59ce8723',18),('50fd3e73-a4fd-48e7-9613-88369aeb866f','f4e80c17-d198-4b74-832e-b08f893c6a76',1),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','348A6B99-1201-46CE-98E8-E84553EF0493',6),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','3F80BD4B-25C2-436E-A801-E2D30DA0F775',14),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','48A00ADD-4561-49C8-819F-199EFAB11AAB',8),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',2),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',9),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('7A3AD9E5-0A73-4CC2-8AD0-D32DC8728E35','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','348A6B99-1201-46CE-98E8-E84553EF0493',1),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','3F80BD4B-25C2-436E-A801-E2D30DA0F775',12),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','4D5F1210-7073-48AC-8248-AEA3F48A64C3',13),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('839C9288-A16A-4F23-A177-B9A7B206CEE7','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('839C9288-A16A-4F23-A177-B9A7B206CEE7','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',1),('897C5865-15C8-4D6C-99C2-FD017910BA8B','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('975384BD-049E-43AB-BE18-B035D9F0AAA9','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','706937C9-300F-46EB-A629-DF7A8293FDEE',1),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',2),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('A2118E5F-B0E1-4B31-BB43-02379801F0E0','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('a3e19e66-736b-4a49-86a7-6985ba997b43','3f80bd4b-25c2-436e-a801-e2d30da0f775',0),('A3E19E66-736B-4A49-86A7-6985BA997B43','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','348A6B99-1201-46CE-98E8-E84553EF0493',2),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','48A00ADD-4561-49C8-819F-199EFAB11AAB',5),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','348A6B99-1201-46CE-98E8-E84553EF0493',3),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','706937C9-300F-46EB-A629-DF7A8293FDEE',1),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','F4E80C17-D198-4B74-832E-B08F893C6A76',2),('BAD688AF-A272-41F8-965D-C0D461DB1ACE','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','85A43515-4F55-4503-9697-A2A553EB4B49',0),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',2),('C185DC38-40EF-4C8F-8739-8230150E6785','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('C185DC38-40EF-4C8F-8739-8230150E6785','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',2),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','3F80BD4B-25C2-436E-A801-E2D30DA0F775',3),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','348A6B99-1201-46CE-98E8-E84553EF0493',1),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('d620f852-4b36-410a-a3a1-69f463767619','48a00add-4561-49c8-819f-199efab11aab',0),('d620f852-4b36-410a-a3a1-69f463767619','85a43515-4f55-4503-9697-a2a553eb4b49',2),('d620f852-4b36-410a-a3a1-69f463767619','b2dad012-5746-47fc-a1c9-768a83d7d3ff',1),('D974D577-1921-4410-BE22-D2C7E7663B06','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('D974D577-1921-4410-BE22-D2C7E7663B06','348A6B99-1201-46CE-98E8-E84553EF0493',2),('D974D577-1921-4410-BE22-D2C7E7663B06','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('D974D577-1921-4410-BE22-D2C7E7663B06','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('D974D577-1921-4410-BE22-D2C7E7663B06','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('D974D577-1921-4410-BE22-D2C7E7663B06','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('e7b19bd0-4646-4c6a-af04-4cf085ac576f','48a00add-4561-49c8-819f-199efab11aab',1),('e7b19bd0-4646-4c6a-af04-4cf085ac576f','85a43515-4f55-4503-9697-a2a553eb4b49',0),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','348A6B99-1201-46CE-98E8-E84553EF0493',5),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','3F80BD4B-25C2-436E-A801-E2D30DA0F775',14),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','48A00ADD-4561-49C8-819F-199EFAB11AAB',8),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','4D5F1210-7073-48AC-8248-AEA3F48A64C3',15),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','85A43515-4F55-4503-9697-A2A553EB4B49',7),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',13),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',9),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('F310F519-08C7-499A-A102-C02B7A35485C','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('F310F519-08C7-499A-A102-C02B7A35485C','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',1),('F4950560-BF03-4C01-81C5-435C53587238','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('F4950560-BF03-4C01-81C5-435C53587238','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('FB74B158-4C1A-4653-8253-3107C8B38ADD','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','348A6B99-1201-46CE-98E8-E84553EF0493',1),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','F4E80C17-D198-4B74-832E-B08F893C6A76',0); -/*!40000 ALTER TABLE `useragentprofileorders` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `useragents` --- - -DROP TABLE IF EXISTS `useragents`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `useragents` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `Identifier` longtext COLLATE utf8mb4_swedish_ci, - `MatchType` int(11) NOT NULL, - `Image` longtext COLLATE utf8mb4_swedish_ci, - `UserInterfaceLink` longtext COLLATE utf8mb4_swedish_ci, - `Ax` tinyint(4) NOT NULL, - `Width` int(11) NOT NULL, - `Height` int(11) NOT NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `Api` longtext COLLATE utf8mb4_swedish_ci, - `Lines` int(11) NOT NULL, - `Inputs` int(11) NOT NULL, - `NrOfGpos` int(11) NOT NULL DEFAULT '0', - `MaxInputDb` int(11) NOT NULL, - `MinInputDb` int(11) NOT NULL, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `InputGainStep` int(11) NOT NULL, - `GpoNames` longtext COLLATE utf8mb4_swedish_ci, - `UserInterfaceIsOpen` tinyint(4) NOT NULL, - `UseScrollbars` tinyint(4) NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `useragents` --- - -LOCK TABLES `useragents` WRITE; -/*!40000 ALTER TABLE `useragents` DISABLE KEYS */; -INSERT INTO `useragents` VALUES ('12c6d8c1-0ac0-46f3-b6fd-53ded04ab388','Janus WebRTC','Janus',0,'telefonare.png','http://[host]/',0,0,0,'root','2017-12-19 10:08:15','root','2018-03-28 14:23:56',NULL,0,0,0,0,0,'',3,NULL,1,0),('18B9E420-7918-44B9-B7E2-B4698E6035BD','Linphone','Linphone',0,'linphone-icon.png',NULL,0,0,0,'root','2014-09-29 12:29:49','root','2015-09-08 08:55:25',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('1973A2C9-F7F2-43B3-A4F4-795502ADEDAF','BareSip Client v0.4.14','baresip v0.4.14',1,'baresip-s-icon.png','http://[host]/',0,0,0,'root','2015-09-09 11:52:39','root','2016-01-19 13:44:45',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('2576E6D7-F490-4712-B07D-871DFC140A66','Quntum ST W3','QuantumW3/02.1.3',1,'icon-prodys-quantum_ST.png',NULL,1,0,0,'root','2017-03-14 16:11:13','root','2017-07-12 08:11:42','IkusNet',2,2,0,0,0,NULL,3,NULL,0,0),('28C8D173-67EE-40A4-8850-A28133A388C2','Blink','Blink',0,'blink-logo-text@2x.png',NULL,0,0,0,'root','2017-07-25 09:06:54','root','2017-07-25 09:08:17',NULL,0,0,0,0,0,'',3,NULL,0,0),('311dfec3-e460-4a45-84a8-26e866b04101','Zoiper','Z 5',0,'zoiper-logo_thumb.png',NULL,0,0,0,'root','2018-01-22 10:11:27','root','2018-01-22 10:13:06',NULL,0,0,0,0,0,'',3,NULL,0,0),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','UMAC2-C','ME-UMAC2-C',1,'UMAC-CII.png',NULL,0,0,0,'root','2016-04-11 09:31:01','root','2017-12-15 12:48:00','Umac',0,0,0,0,0,NULL,3,NULL,0,0),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','Nomada','Nomada',0,'Nomada-icon.png','http://[host]/',1,620,1000,'root','2014-09-29 12:32:58','root','2014-09-29 12:32:58',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('391F4E31-9F6E-41C5-A787-1CB0F63035EF','Asterisk PBX','Asterisk PBX',0,'asteriskpbx-icon.png',NULL,0,0,0,'root','2014-09-29 12:27:09','root','2014-09-29 12:27:09',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('4444026F-3854-4AAB-95DF-E182D5EB5B36','ProntoNet','ProntoNet',0,'Prontonet-icon.png','http://[host]/',1,620,1000,'root','2014-09-29 12:35:04','root','2017-03-02 11:50:08',NULL,0,0,0,0,0,'',0,NULL,0,0),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','Quantum ST+','QuantumST+',1,'icon-prodys-quantum_ST_Plus.png','http://[host]',0,494,287,'root','2017-06-20 12:27:04','root','2018-03-15 12:45:13',NULL,0,0,0,0,0,NULL,3,NULL,0,1),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','QuantumOne','Nerea/',0,'icon-prodys-quantum.png','http://[host]/',0,550,350,'root','2017-05-30 11:40:12','root','2018-10-30 14:55:34','IkusNet',2,0,0,0,0,NULL,3,NULL,0,0),('50fd3e73-a4fd-48e7-9613-88369aeb866f','MicroSIP','MicroSIP',1,NULL,NULL,0,0,0,'root','2018-03-19 13:39:15','root','2018-03-19 13:39:15',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','Quantum','Quantum/3',1,'icon-prodys-quantum.png','http://[host]/',1,494,287,'root','2014-09-29 12:36:07','root','2018-10-30 10:26:24','IkusNet',2,5,2,0,-100,NULL,0,'Ut 0, Ut 1, Ut 2, Ut 3',0,0),('7A3AD9E5-0A73-4CC2-8AD0-D32DC8728E35','WebRTC','webrtc',0,'webrtc-icon-90x15.png','',0,0,0,'root','2014-09-29 12:40:41','root','2016-09-08 12:04:10','',0,0,0,0,0,'',0,'',0,0),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','Quantum ST','QuantumST/',1,'QuantumST_Transp.png','http://[host]/',1,494,287,'root','2014-09-29 12:36:49','root','2018-09-21 13:04:31','IkusNet',1,1,0,0,-100,NULL,0,NULL,0,0),('839C9288-A16A-4F23-A177-B9A7B206CEE7','Acrobits','Acrobits',0,NULL,NULL,0,0,0,'root','2017-07-05 09:12:32','root','2017-07-05 09:13:02',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('897C5865-15C8-4D6C-99C2-FD017910BA8B','Baresip Client v0.4.17','baresip v0.4.17',0,'baresip-s-icon.png','http://[host]/',0,0,0,'root','2016-04-20 08:45:09','root','2016-04-28 10:57:01',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('975384BD-049E-43AB-BE18-B035D9F0AAA9','Baresip Client v0.4.15','baresip v0.4.15',0,'baresip-s-icon.png','http://[host]/',0,0,0,'root','2015-10-16 10:55:02','root','2016-01-19 13:44:34',NULL,0,0,0,0,0,NULL,3,NULL,1,1),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','Mayah','MAYAH',0,'mayah-icon.png',NULL,0,0,0,'root','2014-09-29 12:30:35','root','2015-06-15 17:20:16',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('A2118E5F-B0E1-4B31-BB43-02379801F0E0','Comrex','Comrex',0,'comrex-icon.png',NULL,0,0,0,'root','2014-09-29 12:29:26','root','2014-09-29 12:29:26',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('A3E19E66-736B-4A49-86A7-6985BA997B43','BareSip Client v0.5.10','baresip v0.5.10',1,'Aloe-Project-Logo.png','http://[host]/',0,850,500,'root','2016-10-17 13:05:40','root','2018-11-21 13:33:19','BaresipRest',0,1,0,100,0,NULL,3,NULL,1,0),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','UMAC','ME-UMAC-M/',1,'me-umac-m-icon.png',NULL,0,0,0,'root','2014-09-29 12:38:23','root','2017-06-12 15:52:11','Umac',0,0,0,0,0,NULL,0,NULL,0,0),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','Snom','snom',0,'snom-icon.png','http://[host]/',0,0,0,'root','2014-09-29 12:37:28','root','2015-06-03 07:13:17',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('BAD688AF-A272-41F8-965D-C0D461DB1ACE','Mayah Mobi','Mobi',0,'mobi-icon.png',NULL,0,0,0,'root','2014-09-29 12:31:08','root','2014-09-29 12:41:47',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','UMAC-C','ME-UMAC-C/',0,'me-umac-c-icon.png',NULL,0,0,0,'root','2014-09-29 12:39:03','root','2017-06-13 14:35:44','Umac',0,0,0,0,0,NULL,0,NULL,0,0),('C185DC38-40EF-4C8F-8739-8230150E6785','PCNet','PCNet',0,'prodys-pcnet-icon-2.png',NULL,0,0,0,'root','2014-09-29 12:34:13','root','2014-10-01 13:52:43',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('C65FC719-238B-46B0-B5EA-4692E96453FD','IP-hybrid','IP-hybrid',0,'iphybridalfa.png','http://[host]/',0,0,0,'root','2017-08-10 16:29:40','root','2017-08-14 10:39:32',NULL,0,0,0,0,0,'',3,NULL,0,0),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','Baresip Client','baresip',1,'baresip-s-icon.png','http://[host]/',0,850,460,'root','2015-03-03 13:37:31','root','2018-03-29 19:12:28','BaresipRest',0,1,0,100,0,NULL,3,NULL,1,0),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','Uppgradera firmware','Nomada IP XL v6.6.8',0,'uppgraderafw-icon-95x10.gif',NULL,0,0,0,'root','2014-09-29 12:39:47','root','2014-09-29 12:40:09',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('d620f852-4b36-410a-a3a1-69f463767619','Luci Live MAC ','LuciLiveClient_2.5.9_MAC',0,'LuciLive-logo.png',NULL,0,0,0,'root','2018-01-31 13:52:58','root','2018-01-31 13:53:29',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('D974D577-1921-4410-BE22-D2C7E7663B06','ME-UMAC2 - C','ME-UMAC2-C/1.3',1,'UMAC-CII.png',NULL,0,0,0,'root','2016-04-21 17:50:16','root','2016-11-08 12:00:17','Umac',0,0,0,0,0,NULL,3,NULL,0,0),('e7b19bd0-4646-4c6a-af04-4cf085ac576f','Luci Live Windows','LuciLiveClient',0,'LuciLive-logo.png',NULL,0,0,0,'root','2018-03-19 13:28:51','root','2018-03-19 14:42:18',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','UmacMK2','ME-UMAC2-M',1,'me-umac-m2-icon.png',NULL,0,0,0,'root','2015-05-20 10:06:45','root','2017-12-15 09:00:20','Umac',0,0,0,0,0,NULL,3,NULL,0,0),('F310F519-08C7-499A-A102-C02B7A35485C','Bria','Bria',0,'bria.png','http://[host]/',0,0,0,'root','2014-09-29 12:29:02','root','2018-03-07 14:20:33',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('F4950560-BF03-4C01-81C5-435C53587238','LuciLive','LUCI',0,'LuciLive-logo.png',NULL,0,0,0,'root','2014-09-29 12:30:08','root','2018-01-31 13:48:35',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('FB74B158-4C1A-4653-8253-3107C8B38ADD','Media5-fone','Media5-fone',0,'media5-icon.png',NULL,0,0,0,'root','2014-09-29 12:31:33','root','2014-09-29 12:41:57',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','Nereus','Nereus',0,'Nereus-icon.png','http://[host]/',1,620,1000,'root','2014-09-29 12:32:05','root','2017-07-06 12:29:55',NULL,0,0,0,0,0,NULL,0,NULL,0,0); -/*!40000 ALTER TABLE `useragents` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2019-04-17 16:32:18 diff --git a/CCM.Data/Database/ExampleData/Dump20190417.sql b/CCM.Data/Database/ExampleData/Dump20190417.sql deleted file mode 100644 index 13ac82fa..00000000 --- a/CCM.Data/Database/ExampleData/Dump20190417.sql +++ /dev/null @@ -1,826 +0,0 @@ --- MySQL dump 10.13 Distrib 8.0.13, for Win64 (x86_64) --- --- Host: localhost Database: ccm --- ------------------------------------------------------ --- Server version 5.7.23-log - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; - SET NAMES utf8 ; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `callhistories` --- - -DROP TABLE IF EXISTS `callhistories`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `callhistories` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `CallId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SipCallId` longtext COLLATE utf8mb4_swedish_ci, - `Started` datetime NOT NULL, - `Ended` datetime NOT NULL, - `DlgHashId` longtext COLLATE utf8mb4_swedish_ci, - `DlgHashEnt` longtext COLLATE utf8mb4_swedish_ci, - `ToTag` longtext COLLATE utf8mb4_swedish_ci, - `FromTag` longtext COLLATE utf8mb4_swedish_ci, - `FromId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromSip` longtext COLLATE utf8mb4_swedish_ci, - `FromUsername` longtext COLLATE utf8mb4_swedish_ci, - `FromDisplayName` longtext COLLATE utf8mb4_swedish_ci, - `FromComment` longtext COLLATE utf8mb4_swedish_ci, - `FromLocationId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromLocationName` longtext COLLATE utf8mb4_swedish_ci, - `FromLocationComment` longtext COLLATE utf8mb4_swedish_ci, - `FromLocationShortName` longtext COLLATE utf8mb4_swedish_ci, - `FromCodecTypeId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromCodecTypeName` longtext COLLATE utf8mb4_swedish_ci, - `FromCodecTypeColor` longtext COLLATE utf8mb4_swedish_ci, - `FromOwnerId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromOwnerName` longtext COLLATE utf8mb4_swedish_ci, - `FromRegionId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromRegionName` longtext COLLATE utf8mb4_swedish_ci, - `FromUserAgentHead` longtext COLLATE utf8mb4_swedish_ci, - `ToId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToSip` longtext COLLATE utf8mb4_swedish_ci, - `ToUsername` longtext COLLATE utf8mb4_swedish_ci, - `ToDisplayName` longtext COLLATE utf8mb4_swedish_ci, - `ToComment` longtext COLLATE utf8mb4_swedish_ci, - `ToLocationId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToLocationName` longtext COLLATE utf8mb4_swedish_ci, - `ToLocationComment` longtext COLLATE utf8mb4_swedish_ci, - `ToLocationShortName` longtext COLLATE utf8mb4_swedish_ci, - `ToCodecTypeId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToCodecTypeName` longtext COLLATE utf8mb4_swedish_ci, - `ToCodecTypeColor` longtext COLLATE utf8mb4_swedish_ci, - `ToOwnerId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToOwnerName` longtext COLLATE utf8mb4_swedish_ci, - `ToRegionId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToRegionName` longtext COLLATE utf8mb4_swedish_ci, - `ToUserAgentHead` longtext COLLATE utf8mb4_swedish_ci, - `IsPhoneCall` tinyint(4) NOT NULL, - PRIMARY KEY (`Id`), - KEY `CIX_CallHistories_Ended` (`Ended`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `callhistories` --- - -LOCK TABLES `callhistories` WRITE; -/*!40000 ALTER TABLE `callhistories` DISABLE KEYS */; -/*!40000 ALTER TABLE `callhistories` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `calls` --- - -DROP TABLE IF EXISTS `calls`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `calls` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SipCallID` longtext COLLATE utf8mb4_swedish_ci, - `DlgHashId` longtext COLLATE utf8mb4_swedish_ci, - `DlgHashEnt` longtext COLLATE utf8mb4_swedish_ci, - `FromId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `FromUsername` longtext COLLATE utf8mb4_swedish_ci, - `FromDisplayName` varchar(200) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `ToId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ToUsername` longtext COLLATE utf8mb4_swedish_ci, - `ToDisplayName` varchar(200) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Started` datetime NOT NULL, - `Updated` datetime NOT NULL, - `Closed` tinyint(4) NOT NULL, - `State` int(11) DEFAULT NULL, - `ToTag` longtext COLLATE utf8mb4_swedish_ci, - `FromTag` longtext COLLATE utf8mb4_swedish_ci, - `IsPhoneCall` tinyint(4) NOT NULL, - PRIMARY KEY (`Id`), - KEY `IX_Closed` (`Closed`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `calls` --- - -LOCK TABLES `calls` WRITE; -/*!40000 ALTER TABLE `calls` DISABLE KEYS */; -INSERT INTO `calls` VALUES ('01563703-f728-427c-ad19-3e12afd006c4','98MToIWW3kETbtg3sHDibPM1mPjLSuWT','1060','2446','0324949f-42ed-499e-af3c-8dc1b9697ef1','studio-pool-001@sipdomain.com','Studio pool 1','136D9F77-CA80-49D3-BC27-02B77EE3B644','john.doe@sipdomain.com','John Doe','2019-02-11 17:06:59','2019-02-11 17:06:59',0,0,'','.jEnQGVuZTiH1spqxqwodXt3SwutsC84',0),('11d55837-0942-4032-ad9e-4ac56355b63d','HoAUpjWKlZqFOOq23Ap2T5fk.lqPGUQt','4376','1631','21ABB1AD-38B6-4211-9098-7F6906752F5E','ob-portable-001@sipdomain.com','OB Portable 1','27CD88DC-5FBC-439F-B470-BFEEE91852F3','studio-pool-002@sipdomain.com','Studio pool 2','2019-03-11 17:06:59','2019-03-11 17:06:59',0,0,'i51TTgEN5Hk9jThG-bnQmpj.5ld5ONg3','1L6vjZliAiaBP7m.vfh4BElhjL7jJZlW',0),('194c74fe-99ae-416d-a072-d294ba094588','-I.lzsaUUEVtZqTPAxLxFtBUTRiPlRDL','7318','2393','4DDBDBEB-89E7-4232-BEA4-748B4D5E7B37','dev-001@sipdomain.com','DEV 001','4e6f8ed4-1d22-46f4-a81a-d6dbc8f581ac','pis.rartsiger@sipdomain.com','Pis Rartsiger','2019-03-11 16:06:59','2019-03-11 16:06:59',0,0,'','ZDNREt36Jw8rprr0obdLW4szC5M2b7pO',0),('7cc8324f-9076-4e88-b873-c9d944b1193c','Rp0h9faDDxap1oWiQuM2Zdp9R88DNZj-','1240','3796','6821859E-53AC-4A3A-A14D-C63495F56655','facility-001@sipdomain.com','Facility 1','00000000-0000-0000-0000-000000000000','020304050','020304050','2019-03-15 12:06:59','2019-03-15 12:06:59',0,0,'as168fd8f7','XJX.vbm5ugNEFD13tj.IgqQN.3L5gVJH',1),('bce5624d-d8cf-486b-b85a-08e08254b0a4','Rp0h9faDDxap1oWiQuM2Zdp9R88DNZj-','1240','3796','7722B5B4-2089-4A0F-9BE9-57B6C89F5312','block-line@sipdomain.com','Block Connection','00000000-0000-0000-0000-000000000000','0700128752','0700128752','2019-03-15 12:06:59','2019-03-15 12:06:59',0,0,'','XJX.vbm5ugNEFD13tj.IgqQN.3L5gVJH',1),('c5d01b65-11df-4ec2-84c1-19e354ef4342','scXSCBr.GhjASSXHi7zWfFMpKkhBMLwI','3327','2341','9ec856fa-cc47-4031-8882-9a897fb2770c','local-department@sipdomain.com','Local Department','00000000-0000-0000-0000-000000000000','08562712312','08562712312','2019-02-15 12:06:59','2019-02-15 12:06:59',0,0,'','RxpfiYjMVhKpTuPh-N8qgdz0E4FWsh6c',1),('f49990ad-10a2-4bae-b85b-fced14f33123','Wb6lOHdCvSPXVbaiurX9gRueKSCbqZpo','2727','1581','6d19425f-6a23-404f-9854-3f9dc55bde3b','backpack-001@sipdomain.com','Backpack 1','974A8AA1-DA5F-4148-BAB0-FBC2BD70B868','tim.johnsson@@sipdomain.com','Tim Johnsson','2019-03-10 10:06:59','2019-03-10 10:06:59',0,0,'fx4wJKrbA55vQsz2Qs4hLdmGO1cLjq2U','kfelgXH.pZfrckItICHNwlxJPQqEmL2B',0),('fa04bfc1-5c16-46e4-8988-150f0d22049d','q58NoXa20zcXzxHBEEHV0Vy','699','3157','A4F083D7-327F-4490-A19D-474845E06946','lisa.fredriksen@sipdomain.com','Lisa Fredriksen','AE3EE31E-9B5C-49F2-9624-F90EB41CDD8B','mike.golden@sipdomain.com','Mike Golden','2019-03-12 10:06:59','2019-03-12 10:06:59',0,0,'OM7WgnlKBhfSHWFynXp3RPltIsLTAw7w','4mX3Hec79H22j',0),('ff1d5bf6-e1dc-404c-b90a-bdd26b941e21','3wAjka3YFcY0qsHF0s3oHE6hKJ3vDICd','2249','971','BDEB2094-A9B1-49CB-8722-5557C89AFC1C','miranda.stewart@sipdomain.com','Miranda Stewart','D029EAD8-2D71-4545-90A0-7CEE5F85E46A','yang.weng@sipdomain.com','Yang Weng','2019-02-12 10:06:59','2019-02-12 10:06:59',0,0,'','V9iCZFAOUOdDNX-zRJ.DN0WV5yQ0LBvm',0); -/*!40000 ALTER TABLE `calls` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `ccmusers` --- - -DROP TABLE IF EXISTS `ccmusers`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `ccmusers` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserName` longtext COLLATE utf8mb4_swedish_ci, - `FirstName` longtext COLLATE utf8mb4_swedish_ci, - `LastName` longtext COLLATE utf8mb4_swedish_ci, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `PasswordHash` longtext COLLATE utf8mb4_swedish_ci, - `Salt` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `Role_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IX_CcmUsers_Role_RoleId` (`Role_Id`), - CONSTRAINT `FK_CcmUsers_Roles_RoleId` FOREIGN KEY (`Role_Id`) REFERENCES `roles` (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `ccmusers` --- - -LOCK TABLES `ccmusers` WRITE; -/*!40000 ALTER TABLE `ccmusers` DISABLE KEYS */; -INSERT INTO `ccmusers` VALUES ('318c0f75-81dc-4455-8808-de53fca5fb34','discovery','Discovery','Test','Access account','kq+3HYdWGXLlrKVtb3Jprg==','CyIGvYj4S+cKfBV3PakHKP9zYaQ=','root','2019-04-15 15:51:44','root','2019-02-03 21:00:54',NULL),('C0E480FC-BD0C-4779-8324-85DD709B7FBE','root','root','Administrator',NULL,'kq+3HYdWGXLlrKVtb3Jprg==','NSVoZlkkdSFnclFCZEhzZyMmXiQ=','root','2019-04-15 15:51:44','root','2018-04-25 07:10:09','93F8370B-3321-42CB-A7BF-856AA8E6446E'); -/*!40000 ALTER TABLE `ccmusers` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `cities` --- - -DROP TABLE IF EXISTS `cities`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `cities` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `cities` --- - -LOCK TABLES `cities` WRITE; -/*!40000 ALTER TABLE `cities` DISABLE KEYS */; -INSERT INTO `cities` VALUES ('03C9DD9D-1A55-4CB4-861A-C837EBDAC859','Berlin','root','2015-04-29 21:57:28','root','2015-12-17 12:58:12'),('15C2F344-551D-4621-B5F0-C6F74F99D35D','Paris','root','2017-06-14 13:15:26','root','2017-06-14 13:15:26'),('91CB9B00-E4B7-4C5B-9603-51792B2623B0','Oslo','root','2015-04-28 12:17:24','root','2015-11-12 14:28:58'),('9588E6AE-01C6-49ED-9DF5-8AAF57D8DDFD','Stockholm','root','2014-11-19 12:54:41','root','2015-05-05 10:45:42'),('C999C4A4-F848-497D-8024-9AFD0CF87352','Helsinki','root','2014-10-22 11:14:12','root','2014-10-22 11:14:12'),('D1DF8E13-86BE-4950-A169-B36A3F16D7E9','New York','root','2015-04-01 19:53:06','root','2015-04-01 19:53:06'),('F614CA9A-B8DD-4CFE-8855-1988C8DDBB38','Los Angeles','root','2015-07-08 14:25:26','root','2016-02-08 09:08:14'); -/*!40000 ALTER TABLE `cities` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `codecpresets` --- - -DROP TABLE IF EXISTS `codecpresets`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `codecpresets` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `codecpresets` --- - -LOCK TABLES `codecpresets` WRITE; -/*!40000 ALTER TABLE `codecpresets` DISABLE KEYS */; -INSERT INTO `codecpresets` VALUES ('076F058C-11BF-416C-84C0-90E43C6F9B6B','Preset 1','root','2015-04-29 08:59:11','root','2015-04-29 08:59:11'),('2789E7A3-CBF6-4434-A1C5-7EF72D718B0A','Preset 7','root','2016-09-22 17:33:43','root','2016-09-22 17:33:43'),('6A6D3983-665C-4E87-BD98-2FBF24C953A0','Preset 6','root','2016-09-22 17:33:38','root','2016-09-22 17:33:38'),('82B6D5C3-79A9-4CD7-B3C7-EE96D9CA1922','Preset 4','root','2016-09-22 17:33:30','root','2016-09-22 17:33:30'),('9B098C2E-06AC-4546-9CBE-377BB3A30555','Preset 5','root','2016-09-22 17:33:35','root','2016-09-22 17:33:35'),('C3B8AD85-0E26-41A9-8125-4448A77431B6','Preset 2','root','2015-04-29 08:59:15','root','2015-04-29 08:59:15'),('D8C7DC2F-79AB-434C-BE03-F2F3830D0717','Preset 3','root','2016-09-22 17:33:18','root','2016-09-22 17:33:18'),('F225F656-3DFA-4A7A-A876-9B35C60F177B','Preset 8','root','2016-09-22 17:33:55','root','2016-09-22 17:33:55'); -/*!40000 ALTER TABLE `codecpresets` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `codecpresetuseragents` --- - -DROP TABLE IF EXISTS `codecpresetuseragents`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `codecpresetuseragents` ( - `CodecPreset_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserAgent_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - PRIMARY KEY (`CodecPreset_Id`,`UserAgent_Id`), - KEY `IX_CodecPreset_CodecPresetId` (`CodecPreset_Id`), - KEY `IX_UserAgent_UserAgentId` (`UserAgent_Id`), - CONSTRAINT `FK_CodecPresetUserAgents_CodecPresetId` FOREIGN KEY (`CodecPreset_Id`) REFERENCES `codecpresets` (`Id`) ON DELETE CASCADE, - CONSTRAINT `FK_CodecPresetUserAgents_UserAgentId` FOREIGN KEY (`UserAgent_Id`) REFERENCES `useragents` (`Id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `codecpresetuseragents` --- - -LOCK TABLES `codecpresetuseragents` WRITE; -/*!40000 ALTER TABLE `codecpresetuseragents` DISABLE KEYS */; -INSERT INTO `codecpresetuseragents` VALUES ('076F058C-11BF-416C-84C0-90E43C6F9B6B','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('076F058C-11BF-416C-84C0-90E43C6F9B6B','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('2789E7A3-CBF6-4434-A1C5-7EF72D718B0A','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('2789E7A3-CBF6-4434-A1C5-7EF72D718B0A','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('6A6D3983-665C-4E87-BD98-2FBF24C953A0','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('6A6D3983-665C-4E87-BD98-2FBF24C953A0','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('82B6D5C3-79A9-4CD7-B3C7-EE96D9CA1922','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('82B6D5C3-79A9-4CD7-B3C7-EE96D9CA1922','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('9B098C2E-06AC-4546-9CBE-377BB3A30555','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('9B098C2E-06AC-4546-9CBE-377BB3A30555','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('C3B8AD85-0E26-41A9-8125-4448A77431B6','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('C3B8AD85-0E26-41A9-8125-4448A77431B6','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('D8C7DC2F-79AB-434C-BE03-F2F3830D0717','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('D8C7DC2F-79AB-434C-BE03-F2F3830D0717','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'),('F225F656-3DFA-4A7A-A876-9B35C60F177B','6FE0FD55-CAFB-4D57-8818-8A289511C4B5'),('F225F656-3DFA-4A7A-A876-9B35C60F177B','834EA3A6-1F25-4F4B-961F-97ECFE351BB8'); -/*!40000 ALTER TABLE `codecpresetuseragents` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `codectypes` --- - -DROP TABLE IF EXISTS `codectypes`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `codectypes` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `Color` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `codectypes` --- - -LOCK TABLES `codectypes` WRITE; -/*!40000 ALTER TABLE `codectypes` DISABLE KEYS */; -INSERT INTO `codectypes` VALUES ('1488C1A6-B6C2-498E-9E85-8F80CFE4DD0C','Backpack','#854f4f','root','2015-07-09 07:20:37','root','2017-01-31 14:36:09'),('176B09ED-38EE-49AD-9FCD-922AC93CA71D','External','#ffc700','root','2014-09-16 12:12:10','root','2014-11-19 09:11:53'),('2FDB03E3-5E28-4640-A609-1B2098C8819C','Virtual','#a73cd9','root','2017-07-28 09:04:04','root','2017-07-28 09:04:04'),('531C49AF-4ED1-4E32-851F-482748B1259F','Studio','#00abff','root','2014-09-16 12:11:38','root','2017-01-31 14:34:02'),('63A48BAC-1C58-4E84-9BC3-6DD8494B45D5','Development','#e74c3c','root','2014-09-16 12:12:51','root','2014-11-19 09:12:38'),('675EBEC4-2F0A-46CE-880C-FD0B50BC7CA3','Pool-codecs','#d1a229','root','2017-07-28 09:08:33','root','2017-07-28 09:08:33'),('794B9AE5-FEF6-4232-BF85-DBB9DAD23F96','National service','#000000','root','2017-03-09 12:30:42','root','2017-03-09 12:40:45'),('7AE664E7-551D-4ED5-A394-BD9BBB3CC33F','Trucks','#e53ce7','root','2014-10-22 06:47:35','root','2014-11-19 09:12:03'),('96b76f87-2216-4561-9b74-609554b4deaf','Correspondents','#565656','root','2017-11-09 09:12:47','root','2017-11-09 09:13:06'),('9EA80A94-C092-4FBD-8858-9B5DA446F0ED','Phones','#9685b3','root','2017-08-10 11:54:07','root','2017-08-10 11:54:07'),('9FBE2AA7-0080-45A4-9B50-07A12C12ED8A','Personal','#ffff00','root','2014-09-16 12:12:33','root','2014-09-16 12:12:33'),('a4f254a9-1c6f-4c30-b0dc-6f4179693206','Intercom','#b27810','root','2018-01-22 12:11:24','root','2018-01-22 12:11:37'),('F50604D9-3442-452A-B600-28D8D1E2F056','Portable','#00ff75','root','2014-09-16 12:10:07','root','2017-01-31 14:35:55'); -/*!40000 ALTER TABLE `codectypes` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `filters` --- - -DROP TABLE IF EXISTS `filters`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `filters` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `PropertyName` longtext COLLATE utf8mb4_swedish_ci, - `Type` longtext COLLATE utf8mb4_swedish_ci, - `FilteringName` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `filters` --- - -LOCK TABLES `filters` WRITE; -/*!40000 ALTER TABLE `filters` DISABLE KEYS */; -INSERT INTO `filters` VALUES ('26B43F3C-47B4-40C1-AFEE-0853DADDF557','Codec type','Name','CodecTypes','CodecTypeName','root','2015-11-24 14:42:38','root','2019-02-06 01:55:28'),('ED60C2B3-50B8-419F-83A9-5E91EB366F79','Region','Name','Regions','RegionName','root','2014-09-16 12:25:24','root','2019-12-16 12:24:33'); -/*!40000 ALTER TABLE `filters` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `locations` --- - -DROP TABLE IF EXISTS `locations`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `locations` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `ShortName` longtext COLLATE utf8mb4_swedish_ci, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `Net_Address_v4` varchar(50) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Cidr` tinyint(4) DEFAULT NULL, - `Net_Address_v6` varchar(200) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Cidr_v6` tinyint(4) DEFAULT NULL, - `CarrierConnectionId` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `City_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Region_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `ProfileGroup_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - PRIMARY KEY (`Id`), - KEY `IX_City_CityId` (`City_Id`), - KEY `IX_Region_RegionId` (`Region_Id`), - KEY `fk_locations_profilegroups1_idx` (`ProfileGroup_Id`), - CONSTRAINT `FK_City_CityId` FOREIGN KEY (`City_Id`) REFERENCES `cities` (`Id`), - CONSTRAINT `FK_Region_RegionId` FOREIGN KEY (`Region_Id`) REFERENCES `regions` (`Id`), - CONSTRAINT `fk_locations_profilegroups1` FOREIGN KEY (`ProfileGroup_Id`) REFERENCES `profilegroups` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `locations` --- - -LOCK TABLES `locations` WRITE; -/*!40000 ALTER TABLE `locations` DISABLE KEYS */; -INSERT INTO `locations` VALUES ('0A10C58F-EF64-455D-B907-3C1273FAF6C1','Office Department 1','Office1',NULL,'121.19.127.192',28,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:49:53','9588E6AE-01C6-49ED-9DF5-8AAF57D8DDFD','015d0eea-83d0-457e-b931-3f40fb38d0c8','632a109c-6365-4e92-bbeb-bf876a321905'),('1FCA4F89-C062-42CB-B4ED-2D4451164312','Arena Fotboll','ArenaF',NULL,'134.25.24.96',28,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:41:47','F614CA9A-B8DD-4CFE-8855-1988C8DDBB38','7cd0bca7-fe2e-4a75-a8da-74a13e770d5a','72c94c45-d876-4209-a361-20612289fd32'),('5F22E14A-793D-4B5F-91B5-B57C3B99F599','Company A','CmpyA',NULL,'211.15.0.0',16,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:51:01','9588e6ae-01c6-49ed-9df5-8aaf57d8ddfd','a1132218-3e57-4471-93a3-0122fbcf8793','60d7b004-762f-4580-a027-852d660d8aaf'),('67E2541A-7870-4CF9-A4F1-6E97B951168A','Deep forest','forest',NULL,'77.220.0.0',16,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:51:38',NULL,'11173c20-a2ee-4fc2-89a5-017e7a2b2b77','E530AD41-72E5-479C-8E47-9BAF9176A2B4'),('79672557-6CBA-471C-82DB-E16AD5EA1D59','Office Department 2','Office2',NULL,'11.230.110.0',24,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:50:32','F614CA9A-B8DD-4CFE-8855-1988C8DDBB38','c930ab2b-545f-4760-8891-1c8d56933084','632a109c-6365-4e92-bbeb-bf876a321905'),('88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','Unspecified','?',NULL,'0.0.0.0',0,NULL,NULL,NULL,'root','2019-01-06 09:49:53','root','2019-02-06 01:35:34',NULL,'5f91805d-8841-4d28-b02e-9c5fa3eab450','E530AD41-72E5-479C-8E47-9BAF9176A2B4'); -/*!40000 ALTER TABLE `locations` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `logs` --- - -DROP TABLE IF EXISTS `logs`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `logs` ( - `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `Date` datetime(6) DEFAULT NULL, - `Level` varchar(50) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `LevelValue` int(11) DEFAULT NULL, - `Message` longtext COLLATE utf8mb4_swedish_ci, - `Callsite` varchar(512) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Exception` varchar(512) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Application` varchar(64) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `ActivityId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `logs` --- - -LOCK TABLES `logs` WRITE; -/*!40000 ALTER TABLE `logs` DISABLE KEYS */; -/*!40000 ALTER TABLE `logs` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `metatypes` --- - -DROP TABLE IF EXISTS `metatypes`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `metatypes` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `PropertyName` longtext COLLATE utf8mb4_swedish_ci, - `Type` longtext COLLATE utf8mb4_swedish_ci, - `FullPropertyName` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `metatypes` --- - -LOCK TABLES `metatypes` WRITE; -/*!40000 ALTER TABLE `metatypes` DISABLE KEYS */; -INSERT INTO `metatypes` VALUES ('0A524DB7-041E-405D-AB07-55F97E67B9E6','ShortLocation','ShortName','CCM.Data.Entities.Location','Location.ShortName','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('49D336F1-222F-42B9-8893-66A64B711730','Owner','Name','CCM.Data.Entities.Owner','User.Owner.Name','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('6965B48F-33A0-435C-A3F0-DE033822AAF7','IPAddress','IP','CCM.Data.Entities.RegisteredSip','IP','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('69CA75B3-EFBC-4C66-94D2-8B8E0BA79FFE','Location','Name','CCM.Data.Entities.Location','Location.Name','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('77E9D7A9-0161-4A64-954D-DDD4B131F09D','UserAgentHeader','UserAgentHead','CCM.Data.Entities.RegisteredSip','UserAgentHead','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'); -/*!40000 ALTER TABLE `metatypes` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `owners` --- - -DROP TABLE IF EXISTS `owners`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `owners` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `owners` --- - -LOCK TABLES `owners` WRITE; -/*!40000 ALTER TABLE `owners` DISABLE KEYS */; -INSERT INTO `owners` VALUES ('58790BE0-5607-44A7-9D9F-D763A67891BB','Company','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'),('F26D4889-11AF-4242-BE87-59034E6A575F','Development','root','2019-03-04 10:17:47','root','2019-03-04 10:17:47'); -/*!40000 ALTER TABLE `owners` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `profilegroupprofileorders` --- - -DROP TABLE IF EXISTS `profilegroupprofileorders`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `profilegroupprofileorders` ( - `Profile_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ProfileGroup_Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SortIndex` int(11) NOT NULL, - PRIMARY KEY (`Profile_Id`,`ProfileGroup_Id`), - KEY `fk_ProfileGroupProfileOrders_profilegroups1_idx` (`ProfileGroup_Id`), - KEY `fk_ProfileGroupProfileOrders_profile_idx` (`Profile_Id`), - CONSTRAINT `fk_ProfileGroupProfileOrders_profilegroups1` FOREIGN KEY (`ProfileGroup_Id`) REFERENCES `profilegroups` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION, - CONSTRAINT `fk_ProfileGroupProfileOrders_profiles1` FOREIGN KEY (`Profile_Id`) REFERENCES `profiles` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `profilegroupprofileorders` --- - -LOCK TABLES `profilegroupprofileorders` WRITE; -/*!40000 ALTER TABLE `profilegroupprofileorders` DISABLE KEYS */; -INSERT INTO `profilegroupprofileorders` VALUES ('1D765BF5-8FD6-49AE-8D76-5E00564B7552','60d7b004-762f-4580-a027-852d660d8aaf',6),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','632a109c-6365-4e92-bbeb-bf876a321905',6),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','714b88fc-2fc2-467e-a013-4f0d0aa47757',1),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','72c94c45-d876-4209-a361-20612289fd32',6),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','7d842c78-6d8c-4cc5-912f-9ed51c828090',5),('1D765BF5-8FD6-49AE-8D76-5E00564B7552','822928b9-8c47-46d2-8ca7-3e7e7b352933',5),('348A6B99-1201-46CE-98E8-E84553EF0493','60d7b004-762f-4580-a027-852d660d8aaf',7),('348A6B99-1201-46CE-98E8-E84553EF0493','632a109c-6365-4e92-bbeb-bf876a321905',7),('348A6B99-1201-46CE-98E8-E84553EF0493','714b88fc-2fc2-467e-a013-4f0d0aa47757',0),('348A6B99-1201-46CE-98E8-E84553EF0493','72c94c45-d876-4209-a361-20612289fd32',7),('348A6B99-1201-46CE-98E8-E84553EF0493','7d842c78-6d8c-4cc5-912f-9ed51c828090',6),('348A6B99-1201-46CE-98E8-E84553EF0493','822928b9-8c47-46d2-8ca7-3e7e7b352933',6),('348a6b99-1201-46ce-98e8-e84553ef0493','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',1),('3f80bd4b-25c2-436e-a801-e2d30da0f775','632a109c-6365-4e92-bbeb-bf876a321905',9),('3f80bd4b-25c2-436e-a801-e2d30da0f775','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',0),('48A00ADD-4561-49C8-819F-199EFAB11AAB','28c44bae-296f-40b4-affb-277796494567',0),('48A00ADD-4561-49C8-819F-199EFAB11AAB','60d7b004-762f-4580-a027-852d660d8aaf',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','632a109c-6365-4e92-bbeb-bf876a321905',3),('48A00ADD-4561-49C8-819F-199EFAB11AAB','714b88fc-2fc2-467e-a013-4f0d0aa47757',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','72c94c45-d876-4209-a361-20612289fd32',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','7d842c78-6d8c-4cc5-912f-9ed51c828090',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','822928b9-8c47-46d2-8ca7-3e7e7b352933',3),('48a00add-4561-49c8-819f-199efab11aab','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',2),('48A00ADD-4561-49C8-819F-199EFAB11AAB','E530AD41-72E5-479C-8E47-9BAF9176A2B4',1),('706937C9-300F-46EB-A629-DF7A8293FDEE','632a109c-6365-4e92-bbeb-bf876a321905',0),('85A43515-4F55-4503-9697-A2A553EB4B49','28c44bae-296f-40b4-affb-277796494567',1),('85A43515-4F55-4503-9697-A2A553EB4B49','60d7b004-762f-4580-a027-852d660d8aaf',3),('85A43515-4F55-4503-9697-A2A553EB4B49','632a109c-6365-4e92-bbeb-bf876a321905',2),('85A43515-4F55-4503-9697-A2A553EB4B49','72c94c45-d876-4209-a361-20612289fd32',3),('85A43515-4F55-4503-9697-A2A553EB4B49','7d842c78-6d8c-4cc5-912f-9ed51c828090',1),('85a43515-4f55-4503-9697-a2a553eb4b49','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',3),('85A43515-4F55-4503-9697-A2A553EB4B49','E530AD41-72E5-479C-8E47-9BAF9176A2B4',2),('aad8aefd-afc6-4a03-ac5e-d8ae77e857b9','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',6),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','28c44bae-296f-40b4-affb-277796494567',3),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','60d7b004-762f-4580-a027-852d660d8aaf',9),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','632a109c-6365-4e92-bbeb-bf876a321905',8),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','714b88fc-2fc2-467e-a013-4f0d0aa47757',6),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','72c94c45-d876-4209-a361-20612289fd32',9),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','7d842c78-6d8c-4cc5-912f-9ed51c828090',8),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','822928b9-8c47-46d2-8ca7-3e7e7b352933',7),('b2dad012-5746-47fc-a1c9-768a83d7d3ff','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',4),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','E530AD41-72E5-479C-8E47-9BAF9176A2B4',4),('d54f1365-67a9-40bc-a69d-da6b59ce8723','d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c',5),('F4E80C17-D198-4B74-832E-B08F893C6A76','60d7b004-762f-4580-a027-852d660d8aaf',1),('F4E80C17-D198-4B74-832E-B08F893C6A76','632a109c-6365-4e92-bbeb-bf876a321905',1),('F4E80C17-D198-4B74-832E-B08F893C6A76','72c94c45-d876-4209-a361-20612289fd32',1),('F4E80C17-D198-4B74-832E-B08F893C6A76','7d842c78-6d8c-4cc5-912f-9ed51c828090',0); -/*!40000 ALTER TABLE `profilegroupprofileorders` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `profilegroups` --- - -DROP TABLE IF EXISTS `profilegroups`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `profilegroups` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` varchar(64) COLLATE utf8mb4_swedish_ci NOT NULL, - `Description` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime(3) NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime(3) NOT NULL, - PRIMARY KEY (`Id`), - KEY `fk_ProfileGroup_Id_idx` (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `profilegroups` --- - -LOCK TABLES `profilegroups` WRITE; -/*!40000 ALTER TABLE `profilegroups` DISABLE KEYS */; -INSERT INTO `profilegroups` VALUES ('28c44bae-296f-40b4-affb-277796494567','Wi-Fi',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('60d7b004-762f-4580-a027-852d660d8aaf','Local Office',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('632a109c-6365-4e92-bbeb-bf876a321905','Studio',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('714b88fc-2fc2-467e-a013-4f0d0aa47757','Satellite ',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('72c94c45-d876-4209-a361-20612289fd32','Sport',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('7d842c78-6d8c-4cc5-912f-9ed51c828090','Unspecified internal',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('822928b9-8c47-46d2-8ca7-3e7e7b352933','Portable',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('d97c4db1-095e-4dc9-96b6-45dd2d6a7e0c','Backpack',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'),('E530AD41-72E5-479C-8E47-9BAF9176A2B4','Unspecified',NULL,'root','2019-03-04 10:17:47.000','root','2019-03-04 10:17:47.000'); -/*!40000 ALTER TABLE `profilegroups` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `profiles` --- - -DROP TABLE IF EXISTS `profiles`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `profiles` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` varchar(64) COLLATE utf8mb4_swedish_ci NOT NULL, - `Description` longtext COLLATE utf8mb4_swedish_ci, - `Sdp` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `SortIndex` int(11) NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `profiles` --- - -LOCK TABLES `profiles` WRITE; -/*!40000 ALTER TABLE `profiles` DISABLE KEYS */; -INSERT INTO `profiles` VALUES ('1D765BF5-8FD6-49AE-8D76-5E00564B7552','Vehicle SAT Stereo','ENH APTx, 24 bit, 576 kbps stereo, FEC 1/6 - original','v=0\no=dev-02 3599992693 3599992693 IN IP4 example.com\ns=Fordon Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96 97\na=rtpmap:96 aptx/48000/2\na=fmtp:96 variant=enhanced; bitresolution=24\na=rtpmap:97 parityfec/32000\na=fmtp:97 5006 IN IP4 203.0.113.12\na=sendrecv\na=ptime:10\na=ebuacip:protp 97 ratio=6\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 90\na=ebuacip:plength 96 10','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',3),('348A6B99-1201-46CE-98E8-E84553EF0493','Vehicle SAT Mono','ENH APTx, 24 bit, 192 kbps mono, FEC 1/6 - original','v=0\no=dev-02 3599993974 3599993974 IN IP4 example.com\ns=Vehicle\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96 97\na=rtpmap:96 aptx/32000/1\na=fmtp:96 variant=enhanced; bitresolution=24\na=rtpmap:97 parityfec/32000\na=fmtp:97 5006 IN IP4 203.0.113.12\na=sendrecv\na=ptime:17\na=ebuacip:protp 97 ratio=6\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 80\na=ebuacip:plength 96 17','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',2),('3F80BD4B-25C2-436E-A801-E2D30DA0F775','Backpack Stereo','OPUS 128 kbps CBR - original','v=0\no=dev-02 3599993476 3599993476 IN IP4 example.com\ns=Portable Mono\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 maxaveragebitrate=64000;stereo=1;sprop-stereo=1;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 220\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',18),('4693a5f6-fe27-4b28-a609-0a04db05bdc8','Fordon SAT Stereo','OPUS 288 kbps CBR - original','v=0\no=dev-02 3599993476 3599993476 IN IP4 example.com\ns=Vehicle Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=1; sprop-stereo=1;maxaveragebitrate=288000;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 150\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',21),('48A00ADD-4561-49C8-819F-199EFAB11AAB','Internet Mono','OPUS 64 kbps mono, FEC inband - original','v=0\r\no=mtu-02 3599993476 3599993476 IN IP4 example.com\r\ns=Internet Mono\r\nc=IN IP4 203.0.113.12\r\nt=0 0\r\nm=audio 5004 RTP/AVP 96\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=64000;cbr=1;useinbandfec=1\r\na=sendrecv\r\na=ptime:20\r\na=ebuacip:jb 0\r\na=ebuacip:jbdef 0 fixed 350\r\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',4),('4D5F1210-7073-48AC-8248-AEA3F48A64C3','Linkbox Stereo','APTX 384 kbps','v=0\no=dev-02 3599993476 3599993476 IN IP4 example.com\ns=Portable Mono\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 maxaveragebitrate=128000;stereo=1;sprop-stereo=1;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 220\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',20),('706937C9-300F-46EB-A629-DF7A8293FDEE','Studio','PCM 24/48 stereo - original','v=0\r\no=default 3599993476 3599993476 IN IP4 example.com\r\ns=Studio\r\nc=IN IP4 203.0.113.12\r\nt=0 0\r\nm=audio 5004 RTP/AVP 96\r\na=rtpmap:96 L24/48000/2\r\na=sendrecv\r\na=ptime:5\r\na=ebuacip:jb 0\r\na=ebuacip:jbdef 0 fixed 6\r\na=ebuacip:plength 96 5','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',0),('85A43515-4F55-4503-9697-A2A553EB4B49','Internet Stereo','OPUS 256 kbps stereo, FEC inband - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Internet Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 maxaveragebitrate=256000;cbr=1;stereo=1;sprop-stereo=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 400\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',19),('AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9','Abroad Stereo','OPUS 192kbps Stereo CBR - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Outside Stereo\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=1; sprop-stereo=1;maxaveragebitrate=128000;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 220\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',17),('B2DAD012-5746-47FC-A1C9-768A83D7D3FF','Telephone','OPUS 64 kbps mono, G.722, G.711 - original','v=0\no=default 3599993974 3599993974 IN IP4 example.com\ns=Phone\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96 9 8\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=64000;cbr=1;useinbandfec=1\na=rtpmap:9 G722/8000\na=rtpmap:8 PCMA/8000\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 40\na=ebuacip:plength 96 20\na=ebuacip:plength 9 20\na=ebuacip:plength 8 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',6),('c7bf4633-04e9-4030-bbf6-15ac3b9d780d','Fordon SAT Mono','OPUS 144 kbps CBR - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Vehicle Mono Opus\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=144000;cbr=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 100\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',22),('d54f1365-67a9-40bc-a69d-da6b59ce8723','Abroad Mono','OPUS 48kbps Mono - original','v=0\no=default 3599993476 3599993476 IN IP4 example.com\ns=Internet Mono\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 opus/48000/2\na=fmtp:96 stereo=0; sprop-stereo=0;maxaveragebitrate=48000;cbr=1;useinbandfec=1\na=sendrecv\na=ptime:20\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 300\na=ebuacip:plength 96 20','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',23),('F4E80C17-D198-4B74-832E-B08F893C6A76','Arenas','ENH APTx, 24 bit, 576 kbps stereo - original','v=0\no=default 3599992693 3599992693 IN IP4 example.com\ns=Sport\nc=IN IP4 203.0.113.12\nt=0 0\nm=audio 5004 RTP/AVP 96\na=rtpmap:96 aptx/48000/2\na=fmtp:96 variant=enhanced; bitresolution=24\na=ptime:10\na=sendrecv\na=ebuacip:plength 96 10\na=ebuacip:jb 0\na=ebuacip:jbdef 0 fixed 80','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57',1); -/*!40000 ALTER TABLE `profiles` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `regions` --- - -DROP TABLE IF EXISTS `regions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `regions` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `regions` --- - -LOCK TABLES `regions` WRITE; -/*!40000 ALTER TABLE `regions` DISABLE KEYS */; -INSERT INTO `regions` VALUES ('015D0EEA-83D0-457E-B931-3F40FB38D0C8','Russia','root','2019-02-06 01:27:57','root','2019-04-17 13:34:57'),('11173C20-A2EE-4FC2-89A5-017E7A2B2B77','Europe','root','2019-02-06 01:27:57','root','2019-04-17 13:34:51'),('13F5CE95-7D35-4246-BED6-3961560C23A8','Warszawa','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('214822FF-8D90-45F3-A6B8-789FF87707D1','Unspecified','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('5B3B1DEF-85CC-464B-B64C-11C7D4DF4466','Amsterdam','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('5F91805D-8841-4D28-B02E-9C5FA3EAB450','Other','root','2019-02-06 01:27:57','root','2019-04-17 13:35:05'),('7cd0bca7-fe2e-4a75-a8da-74a13e770d5a','Frankfurt','root','2019-02-06 01:27:57','root','2019-04-17 13:36:00'),('A0282620-3262-464B-80E6-95535A38E858','Stockholm','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('A1132218-3E57-4471-93A3-0122FBCF8793','Milano','root','2019-02-06 01:27:57','root','2019-04-17 13:35:23'),('BD2A7668-E4DF-4515-9D36-6A30D7273764','Istanbul','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('C930AB2B-545F-4760-8891-1C8D56933084','Kairo','root','2019-02-06 01:27:57','root','2019-04-17 13:35:14'),('CBF5F7B9-9784-44E5-92BD-C073CF402543','Madrid','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('CF611ACA-B941-4736-AA07-D459A65A473E','International','root','2019-02-06 01:27:57','root','2019-04-17 13:34:41'),('CFC7C231-5D80-48E6-8B92-95FC8EDF53D1','Geneve','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'),('F5E3B1BD-44F6-4875-8E7E-479A418D2923','Prag','root','2019-02-06 01:27:57','root','2019-02-06 01:27:57'); -/*!40000 ALTER TABLE `regions` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `registeredsips` --- - -DROP TABLE IF EXISTS `registeredsips`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `registeredsips` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SIP` varchar(128) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserAgentHead` longtext COLLATE utf8mb4_swedish_ci, - `Username` longtext COLLATE utf8mb4_swedish_ci, - `DisplayName` longtext COLLATE utf8mb4_swedish_ci, - `IP` longtext COLLATE utf8mb4_swedish_ci, - `Port` int(11) NOT NULL, - `RegistrationType` tinyint(4) NOT NULL DEFAULT '0', - `ServerTimeStamp` bigint(20) DEFAULT NULL, - `Updated` datetime NOT NULL, - `Expires` int(11) NOT NULL, - `IsActive` tinyint(4) NOT NULL DEFAULT '0', - `UserAgentId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Location_LocationId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `User_UserId` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IX_UserAgentId` (`UserAgentId`), - KEY `IX_Location_LocationId` (`Location_LocationId`), - KEY `IX_User_UserId` (`User_UserId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `registeredsips` --- - -LOCK TABLES `registeredsips` WRITE; -/*!40000 ALTER TABLE `registeredsips` DISABLE KEYS */; -INSERT INTO `registeredsips` VALUES ('02fc8613-6946-4235-bf5a-22477a8b3ef7','pbx@sipdomain.com','Asterisk PBX 11.13.1','pbx@sipdomain.com','PBX Service','10.121.194.213',5080,0,1647565332,'2020-01-20 15:15:49',97,0,'391f4e31-9f6e-41c5-a787-1cb0f63035ef','88e3d0de-9cce-4bd4-b7af-7ec20e7ef429','01217de1-9f81-4e67-bfee-97df400c7fa1'),('0324949f-42ed-499e-af3c-8dc1b9697ef1','studio-pool-001@sipdomain.com','Nerea/h2.2.6','studio-pool-001@sipdomain.com','Studio pool 1','11.15.154.86',5060,0,1842805239,'2020-01-20 15:15:49',58,0,'4e53c5be-748e-4fd0-9f4b-3461379cf1b4','5f22e14a-793d-4b5f-91b5-b57c3b99f599','01814726-0A9E-4071-8B26-D05DB331EAA9'),('136D9F77-CA80-49D3-BC27-02B77EE3B644','john.doe@sipdomain.com','Blink Pro 4.5.1 (MacOSX)','john.doe@sipdomain.com','John Doe','211.15.160.52',5090,0,1505200163,'2020-01-20 15:15:49',124,0,'28C8D173-67EE-40A4-8850-A28133A388C2','5F22E14A-793D-4B5F-91B5-B57C3B99F599','01DA6EF7-FE8B-4D59-9B45-8DAF843F45AA'),('21ABB1AD-38B6-4211-9098-7F6906752F5E','ob-portable-001@sipdomain.com','Quantum/3.5.0a','ob-portable-001@sipdomain.com','OB Portable 1','138.128.94.34',5060,0,1460636422,'2020-01-20 15:15:49',0,0,'6FE0FD55-CAFB-4D57-8818-8A289511C4B5','5F22E14A-793D-4B5F-91B5-B57C3B99F599','042b9cd3-e2fe-4055-846f-4ea8df1f9a61'),('27CD88DC-5FBC-439F-B470-BFEEE91852F3','studio-pool-002@sipdomain.com','QuantumST/3.5.0a','studio-pool-002@sipdomain.com','Studio pool 2','121.19.127.234',5060,0,1458657572,'2020-01-20 15:15:49',0,0,'834EA3A6-1F25-4F4B-961F-97ECFE351BB8','0A10C58F-EF64-455D-B907-3C1273FAF6C1','05F57AD6-16D0-421B-9618-36A1CC799EC3'),('4DDBDBEB-89E7-4232-BEA4-748B4D5E7B37','dev-001@sipdomain.com','ProntoNetLCv6.8.4','dev-001@sipdomain.com','DEV 001','159.203.47.235',1148,0,1457544803,'2020-01-20 15:15:49',0,0,'4444026F-3854-4AAB-95DF-E182D5EB5B36','88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','063F5B48-6A59-4632-8CF8-0BC93EB44FFA'),('4e6f8ed4-1d22-46f4-a81a-d6dbc8f581ac','pis.rartsiger@sipdomain.com','snom710/8.7.5.35','pis.rartsiger@sipdomain.com','Pis Rartsiger','11.230.110.132',32768,0,1545220316,'2020-01-20 15:15:49',124,0,'ba5b9883-ed3e-46c5-b34b-9f6fb5edcc63','79672557-6cba-471c-82db-e16ad5ea1d59','0758335C-9F9F-46DA-A227-2FEE087D73EC'),('6821859E-53AC-4A3A-A14D-C63495F56655','facility-001@sipdomain.com','ME-UMAC-C/5.18','facility-001@sipdomain.com','Facility 1','121.15.24.106',5060,0,1498030497,'2020-01-20 15:15:49',60,0,'C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','1FCA4F89-C062-42CB-B4ED-2D4451164312','083d21ec-9fdd-434c-9e7b-4611f7ec9e6b'),('6d19425f-6a23-404f-9854-3f9dc55bde3b','backpack-001@sipdomain.com','baresip v0.5.10 (arm6/linux)','backpack-001@sipdomain.com','Backpack 1','11.29.194.136',5060,0,1547565332,'2020-01-20 15:15:49',58,0,'a3e19e66-736b-4a49-86a7-6985ba997b43','5f22e14a-793d-4b5f-91b5-b57c3b99f599','09375200-7204-421f-9d12-eca29d75e166'),('7722B5B4-2089-4A0F-9BE9-57B6C89F5312','block-line@sipdomain.com','AETA/ScoopTeam aoip-v2.00.0012','block-line@sipdomain.com','Block Connection','8.30.194.202',19914,0,1496056496,'2020-01-20 15:15:49',88,0,NULL,'88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0A420FD3-13D9-4001-8F2F-B605F966FF70'),('86c2eb72-2094-4741-9b32-28c03d66181c','traffic-report@sipdomain.com','Bria 4 release 4.7.0 stamp 83078','traffic-report@sipdomain.com','Traffic report','50.23.161.172',55720,0,1527604307,'2020-01-20 15:15:49',124,0,'f310f519-08c7-499a-a102-c02b7a35485c','5f22e14a-793d-4b5f-91b5-b57c3b99f599','0a6d003c-fb20-4422-8ed7-af292a7100ef'),('974A8AA1-DA5F-4148-BAB0-FBC2BD70B868','tim.johnsson@@sipdomain.com','tSIP 0.01.41.00','tim.johnsson@sipdomain.com','Tim Johnsson','123.5.65.190',61664,0,1459004730,'2020-01-20 15:15:49',-1,0,NULL,'88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0AB7C5E2-8AAA-4BFE-B20B-B812BB5F9439'),('9ec856fa-cc47-4031-8882-9a897fb2770c','local-department@sipdomain.com','ME-UMAC2-M/1.38','local-department@sipdomain.com','Local Department','209.45.255.122',49483,0,1547130528,'2020-01-20 15:15:49',25,0,'ee394836-e09b-4cc5-91a6-0589befc61cf','88e3d0de-9cce-4bd4-b7af-7ec20e7ef429','0ACC8882-E7A2-4712-ADF0-8D50D8E99609'),('A4F083D7-327F-4490-A19D-474845E06946','lisa.fredriksen@sipdomain.com','LUCI Live SR_3.1.11_iPhone8.1_(iOS_10.3)','lisa.fredriksen@sipdomain.com','Lisa Fredriksen','77.220.40.116',31369,0,1491570054,'2020-01-20 15:15:49',0,0,'F4950560-BF03-4C01-81C5-435C53587238','67E2541A-7870-4CF9-A4F1-6E97B951168A','0B387A2B-3767-4829-9458-7B1FDA6E4210'),('AE3EE31E-9B5C-49F2-9624-F90EB41CDD8B','mike.golden@sipdomain.com','MicroSIP/3.15.1','mike.golden@sipdomain.com','Mike Golden','130.101.32.162',62471,0,1491029728,'2020-01-20 15:15:49',0,0,NULL,'88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0D7F7ED5-2C04-451D-821D-24532995CD99'),('BDEB2094-A9B1-49CB-8722-5557C89AFC1C','miranda.stewart@sipdomain.com','Comrex SIP','miranda.stewart@sipdomain.com','Miranda Stewart','129.77.137.161',5060,0,1459519384,'2020-01-20 15:15:49',0,0,'A2118E5F-B0E1-4B31-BB43-02379801F0E0','88E3D0DE-9CCE-4BD4-B7AF-7EC20E7EF429','0dc9a4e1-4487-4392-b4d7-f96053b82f3a'),('D029EAD8-2D71-4545-90A0-7CEE5F85E46A','yang.weng@sipdomain.com','Linphone/3.9.1 (belle-sip/1.4.2)','yang.weng@sipdomain.com','Yang Weng','82.65.161.37',5060,0,1484752648,'2020-01-20 15:15:49',0,0,'18B9E420-7918-44B9-B7E2-B4698E6035BD','5F22E14A-793D-4B5F-91B5-B57C3B99F599','0e55a76e-ca12-4455-9327-31c9761a6f96'); -/*!40000 ALTER TABLE `registeredsips` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `roles` --- - -DROP TABLE IF EXISTS `roles`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `roles` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `roles` --- - -LOCK TABLES `roles` WRITE; -/*!40000 ALTER TABLE `roles` DISABLE KEYS */; -INSERT INTO `roles` VALUES ('0C5F9098-A09A-44B1-8603-2DEC46E8E7EF','Remote','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('88783AD0-F83F-40F0-AB46-F12938DFE68A','AccountManager','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('93F8370B-3321-42CB-A7BF-856AA8E6446E','Admin','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'); -/*!40000 ALTER TABLE `roles` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `settings` --- - -DROP TABLE IF EXISTS `settings`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `settings` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `Value` longtext COLLATE utf8mb4_swedish_ci, - `Description` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `settings` --- - -LOCK TABLES `settings` WRITE; -/*!40000 ALTER TABLE `settings` DISABLE KEYS */; -INSERT INTO `settings` VALUES ('3EF6CC4F-4343-4CD9-9FF3-04447118AC65','CodecControlActive','true','Codec control on/off ','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('A2570519-60D4-49B8-A32A-4FDC7B194BB1','SIPDomain','sipdomain.com','The SIP domain','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('C2413728-20F1-4443-B13F-9F26D7DCE25D','UseSipEvent','true','Recieve Kamailio-messages in JSON-format','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('D676D91D-B1CF-4F48-B983-1BD9112962D0','MaxRegistrationAge','130','Time in seconds before SIP registration is obsolete','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('EFF88C41-3DDB-4434-A76F-C2BAD39811B0','LatestCallCount','30','Number of closed calls to show','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'),('F21A6278-4A7C-4FE2-8871-D5BE6FFD7358','UseOldKamailioEvent','false','Recieve Kamailio-messages in old format','root','2019-02-13 16:50:00','root','2019-02-13 16:50:00'); -/*!40000 ALTER TABLE `settings` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `sipaccounts` --- - -DROP TABLE IF EXISTS `sipaccounts`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `sipaccounts` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `UserName` longtext COLLATE utf8mb4_swedish_ci, - `DisplayName` longtext COLLATE utf8mb4_swedish_ci, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `ExtensionNumber` longtext COLLATE utf8mb4_swedish_ci, - `AccountType` int(11) NOT NULL DEFAULT '0', - `IsPoolCodec` tinyint(4) NOT NULL DEFAULT '0', - `AccountLocked` tinyint(4) NOT NULL DEFAULT '0', - `Password` longtext COLLATE utf8mb4_swedish_ci, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `CodecType_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Owner_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - `Region_Id` char(36) COLLATE utf8mb4_swedish_ci DEFAULT NULL, - PRIMARY KEY (`Id`), - KEY `IX_SipAccounts_CodecTypeId` (`CodecType_Id`), - KEY `IX_SipAccounts_OwnerId` (`Owner_Id`), - KEY `IX_SipAccounts_RegionId` (`Region_Id`), - CONSTRAINT `FK_SipAccounts_CodecTypeId` FOREIGN KEY (`CodecType_Id`) REFERENCES `codectypes` (`Id`), - CONSTRAINT `FK_SipAccounts_OwnerId` FOREIGN KEY (`Owner_Id`) REFERENCES `owners` (`Id`), - CONSTRAINT `FK_SipAccounts_RegionId` FOREIGN KEY (`Region_Id`) REFERENCES `regions` (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `sipaccounts` --- - -LOCK TABLES `sipaccounts` WRITE; -/*!40000 ALTER TABLE `sipaccounts` DISABLE KEYS */; -INSERT INTO `sipaccounts` VALUES ('01217de1-9f81-4e67-bfee-97df400c7fa1','pbx@sipdomain.com','PBX Service',NULL,NULL,0,0,0,'t3aC1yJ9PJY9Rms','root','2018-03-13 15:05:57','root','2019-04-17 13:29:44','2fdb03e3-5e28-4640-a609-1b2098c8819c','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('01814726-0A9E-4071-8B26-D05DB331EAA9','studio-pool-001@sipdomain.com','Studio pool 1',NULL,NULL,0,1,0,'y5x%!nH7Zb!kObY','root','2016-04-29 07:43:14','root','2019-04-17 13:31:20','531c49af-4ed1-4e32-851f-482748b1259f','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('01DA6EF7-FE8B-4D59-9B45-8DAF843F45AA','john.doe@sipdomain.com','John Doe',NULL,NULL,0,0,0,'hUh3g1Zexqw62o2','root','1900-01-01 00:00:00','root','2019-04-17 13:29:05','9fbe2aa7-0080-45a4-9b50-07a12c12ed8a','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('042b9cd3-e2fe-4055-846f-4ea8df1f9a61','ob-portable-001@sipdomain.com','OB Portable 1',NULL,NULL,0,0,0,'QpysXRPhO8a931F','root','2018-01-22 12:14:44','root','2019-04-17 13:29:30','f50604d9-3442-452a-b600-28d8d1e2f056','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('05F57AD6-16D0-421B-9618-36A1CC799EC3','studio-pool-002@sipdomain.com','Studio pool 2',NULL,NULL,0,1,0,'fzph3i8sgrMIdth','root','2015-09-21 13:01:58','root','2019-04-17 13:31:23','531C49AF-4ED1-4E32-851F-482748B1259F','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('063F5B48-6A59-4632-8CF8-0BC93EB44FFA','dev-001@sipdomain.com','DEV 001',NULL,NULL,0,0,0,'GZSkL1yw6v7q#yj','root','2015-09-25 08:26:15','root','2019-04-17 13:31:13','63a48bac-1c58-4e84-9bc3-6dd8494b45d5','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0758335C-9F9F-46DA-A227-2FEE087D73EC','pis.rartsiger@sipdomain.com','Pis Rartsiger',NULL,NULL,0,0,0,'US!Ew4qPjqSIcVr','root','2015-06-01 10:28:25','root','2019-04-17 13:31:16','9FBE2AA7-0080-45A4-9B50-07A12C12ED8A','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('083d21ec-9fdd-434c-9e7b-4611f7ec9e6b','facility-001@sipdomain.com','Facility 1',NULL,NULL,0,0,0,'yd9VrmhQ7lsjbfV','root','2018-04-25 07:14:50','root','2019-04-17 13:28:59','176b09ed-38ee-49ad-9fcd-922ac93ca71d','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('09375200-7204-421f-9d12-eca29d75e166','backpack-001@sipdomain.com','Backpack 1',NULL,NULL,0,0,0,'ziHP18M7cIEzjNZ','root','2018-08-10 09:00:29','root','2019-04-17 13:30:57','63a48bac-1c58-4e84-9bc3-6dd8494b45d5','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('0A420FD3-13D9-4001-8F2F-B605F966FF70','block-line@sipdomain.com','Block Connection',NULL,NULL,0,0,0,'6p!zOgPQpEXETHz','root','2017-07-28 08:55:28','root','2019-04-17 13:31:09','531c49af-4ed1-4e32-851f-482748b1259f','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0a6d003c-fb20-4422-8ed7-af292a7100ef','traffic-report@sipdomain.com','Traffic report',NULL,NULL,0,0,0,'iebn1H2bU3!4Sgd','root','2018-06-14 09:39:07','root','2019-04-17 13:31:26','2fdb03e3-5e28-4640-a609-1b2098c8819c','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('0AB7C5E2-8AAA-4BFE-B20B-B812BB5F9439','tim.johnsson@sipdomain.com','Tim Johnsson',NULL,NULL,0,0,0,'t7X86fOV7cm#z6g','root','2014-09-30 13:42:14','root','2019-04-17 13:41:09','9FBE2AA7-0080-45A4-9B50-07A12C12ED8A','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0ACC8882-E7A2-4712-ADF0-8D50D8E99609','local-department@sipdomain.com','Local Department',NULL,NULL,0,0,0,'7RosQgKbbtc37c3','root','2017-08-10 14:05:14','root','2019-04-17 13:30:53','176b09ed-38ee-49ad-9fcd-922ac93ca71d','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0B387A2B-3767-4829-9458-7B1FDA6E4210','lisa.fredriksen@sipdomain.com','Lisa Fredriksen',NULL,NULL,0,0,0,'SqDPGP1CyyU7FOS','root','2015-05-21 13:13:36','root','2019-04-17 13:31:00','F50604D9-3442-452A-B600-28D8D1E2F056','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0D7F7ED5-2C04-451D-821D-24532995CD99','mike.golden@sipdomain.com','Mike Golden',NULL,NULL,0,0,0,'KVc4RgYz6I6Xf36','root','2016-01-19 13:11:29','root','2019-04-17 13:29:13','9fbe2aa7-0080-45a4-9b50-07a12c12ed8a','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('0dc9a4e1-4487-4392-b4d7-f96053b82f3a','miranda.stewart@sipdomain.com','Miranda Stewart',NULL,NULL,0,0,0,'nCPwOqCId08%ab2','root','2018-04-23 11:39:53','root','2019-04-17 13:29:33','9ea80a94-c092-4fbd-8858-9b5da446f0ed','58790be0-5607-44a7-9d9f-d763a67891bb',NULL),('0e55a76e-ca12-4455-9327-31c9761a6f96','yang.weng@sipdomain.com','Yang Weng',NULL,NULL,0,0,0,'f8HD!oqqAr0yogx','root','2018-04-25 07:14:50','root','2019-04-17 13:29:26','f50604d9-3442-452a-b600-28d8d1e2f056','58790BE0-5607-44A7-9D9F-D763A67891BB',NULL),('c5d987a6-d18d-4c01-aeba-24c728a4ed9b','rogsantestaliasusername@sipdomain.sr.se','Roger Test',NULL,NULL,0,0,0,'Nm4w%L5H%AF99Qh','root','2019-02-04 22:13:09','root','2019-04-17 13:29:51','531c49af-4ed1-4e32-851f-482748b1259f','58790BE0-5607-44A7-9D9F-D763A67891BB','11173c20-a2ee-4fc2-89a5-017e7a2b2b77'); -/*!40000 ALTER TABLE `sipaccounts` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `studios` --- - -DROP TABLE IF EXISTS `studios`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `studios` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `CodecSipAddress` longtext COLLATE utf8mb4_swedish_ci, - `CameraAddress` longtext COLLATE utf8mb4_swedish_ci, - `CameraActive` tinyint(4) NOT NULL, - `CameraUsername` longtext COLLATE utf8mb4_swedish_ci, - `CameraPassword` longtext COLLATE utf8mb4_swedish_ci, - `CameraVideoUrl` longtext COLLATE utf8mb4_swedish_ci, - `CameraImageUrl` longtext COLLATE utf8mb4_swedish_ci, - `CameraPlayAudioUrl` longtext COLLATE utf8mb4_swedish_ci, - `AudioClipNames` longtext COLLATE utf8mb4_swedish_ci, - `InfoText` longtext COLLATE utf8mb4_swedish_ci, - `MoreInfoUrl` longtext COLLATE utf8mb4_swedish_ci, - `NrOfAudioInputs` int(11) NOT NULL, - `AudioInputNames` longtext COLLATE utf8mb4_swedish_ci, - `AudioInputDefaultGain` int(11) NOT NULL, - `NrOfGpos` int(11) NOT NULL, - `GpoNames` longtext COLLATE utf8mb4_swedish_ci, - `InactivityTimeout` int(11) NOT NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci NOT NULL, - `UpdatedOn` datetime NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `studios` --- - -LOCK TABLES `studios` WRITE; -/*!40000 ALTER TABLE `studios` DISABLE KEYS */; -INSERT INTO `studios` VALUES ('2DF5686C-7097-4DBD-8BD6-1D0D5B428FA7','Studio Test','studio-entrance-sthlm@sipdomain.sr.se','kamera.mycompany.se',0,NULL,NULL,'/mjpg/video.mjpg?camera=1&resolution=640x480&fps=25&compression=30','/axis-cgi/jpg/image.cgi?camera=1','/axis-cgi/playclip.cgi','Welcome instructions, Ask them to call','To see the camera use Chrome or Firefox. Always read the manual before first use.\r\n','http://www.mycompany.se/manual.pdf',3,'Red, Blue, Yellow',-30,1,'Green light',15,'root','2017-02-12 21:30:31','root','2019-02-06 01:53:56'); -/*!40000 ALTER TABLE `studios` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `useragentprofileorders` --- - -DROP TABLE IF EXISTS `useragentprofileorders`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `useragentprofileorders` ( - `UserAgentId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `ProfileId` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `SortIndex` int(11) NOT NULL, - PRIMARY KEY (`UserAgentId`,`ProfileId`), - KEY `IX_ProfileId` (`ProfileId`), - KEY `IX_UserAgentId` (`UserAgentId`), - CONSTRAINT `FK_dbo.UserAgentProfileOrders_dbo.Profiles_ProfileId` FOREIGN KEY (`ProfileId`) REFERENCES `profiles` (`Id`) ON DELETE CASCADE, - CONSTRAINT `FK_dbo.UserAgentProfileOrders_dbo.UserAgents_UserAgentId` FOREIGN KEY (`UserAgentId`) REFERENCES `useragents` (`Id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `useragentprofileorders` --- - -LOCK TABLES `useragentprofileorders` WRITE; -/*!40000 ALTER TABLE `useragentprofileorders` DISABLE KEYS */; -INSERT INTO `useragentprofileorders` VALUES ('12c6d8c1-0ac0-46f3-b6fd-53ded04ab388','48a00add-4561-49c8-819f-199efab11aab',0),('12c6d8c1-0ac0-46f3-b6fd-53ded04ab388','b2dad012-5746-47fc-a1c9-768a83d7d3ff',1),('18B9E420-7918-44B9-B7E2-B4698E6035BD','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('18B9E420-7918-44B9-B7E2-B4698E6035BD','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',1),('1973A2C9-F7F2-43B3-A4F4-795502ADEDAF','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('2576E6D7-F490-4712-B07D-871DFC140A66','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('2576E6D7-F490-4712-B07D-871DFC140A66','348A6B99-1201-46CE-98E8-E84553EF0493',2),('2576E6D7-F490-4712-B07D-871DFC140A66','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('2576E6D7-F490-4712-B07D-871DFC140A66','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('2576E6D7-F490-4712-B07D-871DFC140A66','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('2576E6D7-F490-4712-B07D-871DFC140A66','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('28C8D173-67EE-40A4-8850-A28133A388C2','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('311dfec3-e460-4a45-84a8-26e866b04101','48a00add-4561-49c8-819f-199efab11aab',0),('311dfec3-e460-4a45-84a8-26e866b04101','b2dad012-5746-47fc-a1c9-768a83d7d3ff',1),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','348A6B99-1201-46CE-98E8-E84553EF0493',3),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','48A00ADD-4561-49C8-819F-199EFAB11AAB',5),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','4D5F1210-7073-48AC-8248-AEA3F48A64C3',14),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','706937C9-300F-46EB-A629-DF7A8293FDEE',1),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','85A43515-4F55-4503-9697-A2A553EB4B49',13),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',12),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',7),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','F4E80C17-D198-4B74-832E-B08F893C6A76',2),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','348A6B99-1201-46CE-98E8-E84553EF0493',1),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('391F4E31-9F6E-41C5-A787-1CB0F63035EF','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('4444026F-3854-4AAB-95DF-E182D5EB5B36','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('4444026F-3854-4AAB-95DF-E182D5EB5B36','348A6B99-1201-46CE-98E8-E84553EF0493',2),('4444026F-3854-4AAB-95DF-E182D5EB5B36','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('4444026F-3854-4AAB-95DF-E182D5EB5B36','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','348A6B99-1201-46CE-98E8-E84553EF0493',2),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','4D5F1210-7073-48AC-8248-AEA3F48A64C3',12),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','85A43515-4F55-4503-9697-A2A553EB4B49',9),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',10),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',11),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','348A6B99-1201-46CE-98E8-E84553EF0493',3),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','3F80BD4B-25C2-436E-A801-E2D30DA0F775',13),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','48A00ADD-4561-49C8-819F-199EFAB11AAB',5),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('4e53c5be-748e-4fd0-9f4b-3461379cf1b4','85a43515-4f55-4503-9697-a2a553eb4b49',2),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',7),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('50fd3e73-a4fd-48e7-9613-88369aeb866f','1d765bf5-8fd6-49ae-8d76-5e00564b7552',3),('50fd3e73-a4fd-48e7-9613-88369aeb866f','348a6b99-1201-46ce-98e8-e84553ef0493',2),('50fd3e73-a4fd-48e7-9613-88369aeb866f','3f80bd4b-25c2-436e-a801-e2d30da0f775',13),('50fd3e73-a4fd-48e7-9613-88369aeb866f','4693a5f6-fe27-4b28-a609-0a04db05bdc8',16),('50fd3e73-a4fd-48e7-9613-88369aeb866f','48a00add-4561-49c8-819f-199efab11aab',4),('50fd3e73-a4fd-48e7-9613-88369aeb866f','4d5f1210-7073-48ac-8248-aea3f48a64c3',15),('50fd3e73-a4fd-48e7-9613-88369aeb866f','706937c9-300f-46eb-a629-df7a8293fdee',0),('50fd3e73-a4fd-48e7-9613-88369aeb866f','85a43515-4f55-4503-9697-a2a553eb4b49',14),('50fd3e73-a4fd-48e7-9613-88369aeb866f','aad8aefd-afc6-4a03-ac5e-d8ae77e857b9',12),('50fd3e73-a4fd-48e7-9613-88369aeb866f','b2dad012-5746-47fc-a1c9-768a83d7d3ff',6),('50fd3e73-a4fd-48e7-9613-88369aeb866f','c7bf4633-04e9-4030-bbf6-15ac3b9d780d',17),('50fd3e73-a4fd-48e7-9613-88369aeb866f','d54f1365-67a9-40bc-a69d-da6b59ce8723',18),('50fd3e73-a4fd-48e7-9613-88369aeb866f','f4e80c17-d198-4b74-832e-b08f893c6a76',1),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','348A6B99-1201-46CE-98E8-E84553EF0493',6),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','3F80BD4B-25C2-436E-A801-E2D30DA0F775',14),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','48A00ADD-4561-49C8-819F-199EFAB11AAB',8),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',2),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',9),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('7A3AD9E5-0A73-4CC2-8AD0-D32DC8728E35','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','348A6B99-1201-46CE-98E8-E84553EF0493',1),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','3F80BD4B-25C2-436E-A801-E2D30DA0F775',12),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','4D5F1210-7073-48AC-8248-AEA3F48A64C3',13),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('839C9288-A16A-4F23-A177-B9A7B206CEE7','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('839C9288-A16A-4F23-A177-B9A7B206CEE7','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',1),('897C5865-15C8-4D6C-99C2-FD017910BA8B','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('975384BD-049E-43AB-BE18-B035D9F0AAA9','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','706937C9-300F-46EB-A629-DF7A8293FDEE',1),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',2),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('A2118E5F-B0E1-4B31-BB43-02379801F0E0','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('a3e19e66-736b-4a49-86a7-6985ba997b43','3f80bd4b-25c2-436e-a801-e2d30da0f775',0),('A3E19E66-736B-4A49-86A7-6985BA997B43','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','348A6B99-1201-46CE-98E8-E84553EF0493',2),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','48A00ADD-4561-49C8-819F-199EFAB11AAB',5),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','348A6B99-1201-46CE-98E8-E84553EF0493',3),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','706937C9-300F-46EB-A629-DF7A8293FDEE',1),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','F4E80C17-D198-4B74-832E-B08F893C6A76',2),('BAD688AF-A272-41F8-965D-C0D461DB1ACE','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','85A43515-4F55-4503-9697-A2A553EB4B49',0),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',2),('C185DC38-40EF-4C8F-8739-8230150E6785','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('C185DC38-40EF-4C8F-8739-8230150E6785','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',2),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','3F80BD4B-25C2-436E-A801-E2D30DA0F775',3),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','348A6B99-1201-46CE-98E8-E84553EF0493',1),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','F4E80C17-D198-4B74-832E-B08F893C6A76',0),('d620f852-4b36-410a-a3a1-69f463767619','48a00add-4561-49c8-819f-199efab11aab',0),('d620f852-4b36-410a-a3a1-69f463767619','85a43515-4f55-4503-9697-a2a553eb4b49',2),('d620f852-4b36-410a-a3a1-69f463767619','b2dad012-5746-47fc-a1c9-768a83d7d3ff',1),('D974D577-1921-4410-BE22-D2C7E7663B06','1D765BF5-8FD6-49AE-8D76-5E00564B7552',3),('D974D577-1921-4410-BE22-D2C7E7663B06','348A6B99-1201-46CE-98E8-E84553EF0493',2),('D974D577-1921-4410-BE22-D2C7E7663B06','48A00ADD-4561-49C8-819F-199EFAB11AAB',4),('D974D577-1921-4410-BE22-D2C7E7663B06','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('D974D577-1921-4410-BE22-D2C7E7663B06','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',6),('D974D577-1921-4410-BE22-D2C7E7663B06','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('e7b19bd0-4646-4c6a-af04-4cf085ac576f','48a00add-4561-49c8-819f-199efab11aab',1),('e7b19bd0-4646-4c6a-af04-4cf085ac576f','85a43515-4f55-4503-9697-a2a553eb4b49',0),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','1D765BF5-8FD6-49AE-8D76-5E00564B7552',4),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','348A6B99-1201-46CE-98E8-E84553EF0493',5),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','3F80BD4B-25C2-436E-A801-E2D30DA0F775',14),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','48A00ADD-4561-49C8-819F-199EFAB11AAB',8),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','4D5F1210-7073-48AC-8248-AEA3F48A64C3',15),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','706937C9-300F-46EB-A629-DF7A8293FDEE',0),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','85A43515-4F55-4503-9697-A2A553EB4B49',7),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','AAD8AEFD-AFC6-4A03-AC5E-D8AE77E857B9',13),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',9),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','F4E80C17-D198-4B74-832E-B08F893C6A76',1),('F310F519-08C7-499A-A102-C02B7A35485C','48A00ADD-4561-49C8-819F-199EFAB11AAB',0),('F310F519-08C7-499A-A102-C02B7A35485C','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',1),('F4950560-BF03-4C01-81C5-435C53587238','48A00ADD-4561-49C8-819F-199EFAB11AAB',1),('F4950560-BF03-4C01-81C5-435C53587238','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('FB74B158-4C1A-4653-8253-3107C8B38ADD','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',0),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','1D765BF5-8FD6-49AE-8D76-5E00564B7552',2),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','348A6B99-1201-46CE-98E8-E84553EF0493',1),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','706937C9-300F-46EB-A629-DF7A8293FDEE',3),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','B2DAD012-5746-47FC-A1C9-768A83D7D3FF',4),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','F4E80C17-D198-4B74-832E-B08F893C6A76',0); -/*!40000 ALTER TABLE `useragentprofileorders` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `useragents` --- - -DROP TABLE IF EXISTS `useragents`; -/*!40101 SET @saved_cs_client = @@character_set_client */; - SET character_set_client = utf8mb4 ; -CREATE TABLE `useragents` ( - `Id` char(36) COLLATE utf8mb4_swedish_ci NOT NULL, - `Name` longtext COLLATE utf8mb4_swedish_ci, - `Identifier` longtext COLLATE utf8mb4_swedish_ci, - `MatchType` int(11) NOT NULL, - `Image` longtext COLLATE utf8mb4_swedish_ci, - `UserInterfaceLink` longtext COLLATE utf8mb4_swedish_ci, - `Ax` tinyint(4) NOT NULL, - `Width` int(11) NOT NULL, - `Height` int(11) NOT NULL, - `CreatedBy` longtext COLLATE utf8mb4_swedish_ci, - `CreatedOn` datetime NOT NULL, - `UpdatedBy` longtext COLLATE utf8mb4_swedish_ci, - `UpdatedOn` datetime NOT NULL, - `Api` longtext COLLATE utf8mb4_swedish_ci, - `Lines` int(11) NOT NULL, - `Inputs` int(11) NOT NULL, - `NrOfGpos` int(11) NOT NULL DEFAULT '0', - `MaxInputDb` int(11) NOT NULL, - `MinInputDb` int(11) NOT NULL, - `Comment` longtext COLLATE utf8mb4_swedish_ci, - `InputGainStep` int(11) NOT NULL, - `GpoNames` longtext COLLATE utf8mb4_swedish_ci, - `UserInterfaceIsOpen` tinyint(4) NOT NULL, - `UseScrollbars` tinyint(4) NOT NULL, - PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_swedish_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `useragents` --- - -LOCK TABLES `useragents` WRITE; -/*!40000 ALTER TABLE `useragents` DISABLE KEYS */; -INSERT INTO `useragents` VALUES ('12c6d8c1-0ac0-46f3-b6fd-53ded04ab388','Janus WebRTC','Janus',0,'telefonare.png','http://[host]/',0,0,0,'root','2017-12-19 10:08:15','root','2018-03-28 14:23:56',NULL,0,0,0,0,0,'',3,NULL,1,0),('18B9E420-7918-44B9-B7E2-B4698E6035BD','Linphone','Linphone',0,'linphone-icon.png',NULL,0,0,0,'root','2014-09-29 12:29:49','root','2015-09-08 08:55:25',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('1973A2C9-F7F2-43B3-A4F4-795502ADEDAF','BareSip Client v0.4.14','baresip v0.4.14',1,'baresip-s-icon.png','http://[host]/',0,0,0,'root','2015-09-09 11:52:39','root','2016-01-19 13:44:45',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('2576E6D7-F490-4712-B07D-871DFC140A66','Quntum ST W3','QuantumW3/02.1.3',1,'icon-prodys-quantum_ST.png',NULL,1,0,0,'root','2017-03-14 16:11:13','root','2017-07-12 08:11:42','IkusNet',2,2,0,0,0,NULL,3,NULL,0,0),('28C8D173-67EE-40A4-8850-A28133A388C2','Blink','Blink',0,'blink-logo-text@2x.png',NULL,0,0,0,'root','2017-07-25 09:06:54','root','2017-07-25 09:08:17',NULL,0,0,0,0,0,'',3,NULL,0,0),('311dfec3-e460-4a45-84a8-26e866b04101','Zoiper','Z 5',0,'zoiper-logo_thumb.png',NULL,0,0,0,'root','2018-01-22 10:11:27','root','2018-01-22 10:13:06',NULL,0,0,0,0,0,'',3,NULL,0,0),('312B9589-10F4-4BDB-92EF-B3623A70A8B8','UMAC2-C','ME-UMAC2-C',1,'UMAC-CII.png',NULL,0,0,0,'root','2016-04-11 09:31:01','root','2017-12-15 12:48:00','Umac',0,0,0,0,0,NULL,3,NULL,0,0),('33D9F8EA-A1B7-4A98-9BE7-8655CCF7AED7','Nomada','Nomada',0,'Nomada-icon.png','http://[host]/',1,620,1000,'root','2014-09-29 12:32:58','root','2014-09-29 12:32:58',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('391F4E31-9F6E-41C5-A787-1CB0F63035EF','Asterisk PBX','Asterisk PBX',0,'asteriskpbx-icon.png',NULL,0,0,0,'root','2014-09-29 12:27:09','root','2014-09-29 12:27:09',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('4444026F-3854-4AAB-95DF-E182D5EB5B36','ProntoNet','ProntoNet',0,'Prontonet-icon.png','http://[host]/',1,620,1000,'root','2014-09-29 12:35:04','root','2017-03-02 11:50:08',NULL,0,0,0,0,0,'',0,NULL,0,0),('4982FD0A-21CB-4BE0-A96F-A6CB3CC7F3D7','Quantum ST+','QuantumST+',1,'icon-prodys-quantum_ST_Plus.png','http://[host]',0,494,287,'root','2017-06-20 12:27:04','root','2018-03-15 12:45:13',NULL,0,0,0,0,0,NULL,3,NULL,0,1),('4E53C5BE-748E-4FD0-9F4B-3461379CF1B4','QuantumOne','Nerea/',0,'icon-prodys-quantum.png','http://[host]/',0,550,350,'root','2017-05-30 11:40:12','root','2018-10-30 14:55:34','IkusNet',2,0,0,0,0,NULL,3,NULL,0,0),('50fd3e73-a4fd-48e7-9613-88369aeb866f','MicroSIP','MicroSIP',1,NULL,NULL,0,0,0,'root','2018-03-19 13:39:15','root','2018-03-19 13:39:15',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('6FE0FD55-CAFB-4D57-8818-8A289511C4B5','Quantum','Quantum/3',1,'icon-prodys-quantum.png','http://[host]/',1,494,287,'root','2014-09-29 12:36:07','root','2018-10-30 10:26:24','IkusNet',2,5,2,0,-100,NULL,0,'Ut 0, Ut 1, Ut 2, Ut 3',0,0),('7A3AD9E5-0A73-4CC2-8AD0-D32DC8728E35','WebRTC','webrtc',0,'webrtc-icon-90x15.png','',0,0,0,'root','2014-09-29 12:40:41','root','2016-09-08 12:04:10','',0,0,0,0,0,'',0,'',0,0),('834EA3A6-1F25-4F4B-961F-97ECFE351BB8','Quantum ST','QuantumST/',1,'QuantumST_Transp.png','http://[host]/',1,494,287,'root','2014-09-29 12:36:49','root','2018-09-21 13:04:31','IkusNet',1,1,0,0,-100,NULL,0,NULL,0,0),('839C9288-A16A-4F23-A177-B9A7B206CEE7','Acrobits','Acrobits',0,NULL,NULL,0,0,0,'root','2017-07-05 09:12:32','root','2017-07-05 09:13:02',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('897C5865-15C8-4D6C-99C2-FD017910BA8B','Baresip Client v0.4.17','baresip v0.4.17',0,'baresip-s-icon.png','http://[host]/',0,0,0,'root','2016-04-20 08:45:09','root','2016-04-28 10:57:01',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('975384BD-049E-43AB-BE18-B035D9F0AAA9','Baresip Client v0.4.15','baresip v0.4.15',0,'baresip-s-icon.png','http://[host]/',0,0,0,'root','2015-10-16 10:55:02','root','2016-01-19 13:44:34',NULL,0,0,0,0,0,NULL,3,NULL,1,1),('9A41CFD4-6410-4EE5-B301-2647AEFDBBF9','Mayah','MAYAH',0,'mayah-icon.png',NULL,0,0,0,'root','2014-09-29 12:30:35','root','2015-06-15 17:20:16',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('A2118E5F-B0E1-4B31-BB43-02379801F0E0','Comrex','Comrex',0,'comrex-icon.png',NULL,0,0,0,'root','2014-09-29 12:29:26','root','2014-09-29 12:29:26',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('A3E19E66-736B-4A49-86A7-6985BA997B43','BareSip Client v0.5.10','baresip v0.5.10',1,'Aloe-Project-Logo.png','http://[host]/',0,850,500,'root','2016-10-17 13:05:40','root','2018-11-21 13:33:19','BaresipRest',0,1,0,100,0,NULL,3,NULL,1,0),('AE689972-DE5E-4D70-B6A3-84D2C72043C2','UMAC','ME-UMAC-M/',1,'me-umac-m-icon.png',NULL,0,0,0,'root','2014-09-29 12:38:23','root','2017-06-12 15:52:11','Umac',0,0,0,0,0,NULL,0,NULL,0,0),('BA5B9883-ED3E-46C5-B34B-9F6FB5EDCC63','Snom','snom',0,'snom-icon.png','http://[host]/',0,0,0,'root','2014-09-29 12:37:28','root','2015-06-03 07:13:17',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('BAD688AF-A272-41F8-965D-C0D461DB1ACE','Mayah Mobi','Mobi',0,'mobi-icon.png',NULL,0,0,0,'root','2014-09-29 12:31:08','root','2014-09-29 12:41:47',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('C086F4A5-EBE9-46FC-AF6A-78ADF0389F26','UMAC-C','ME-UMAC-C/',0,'me-umac-c-icon.png',NULL,0,0,0,'root','2014-09-29 12:39:03','root','2017-06-13 14:35:44','Umac',0,0,0,0,0,NULL,0,NULL,0,0),('C185DC38-40EF-4C8F-8739-8230150E6785','PCNet','PCNet',0,'prodys-pcnet-icon-2.png',NULL,0,0,0,'root','2014-09-29 12:34:13','root','2014-10-01 13:52:43',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('C65FC719-238B-46B0-B5EA-4692E96453FD','IP-hybrid','IP-hybrid',0,'iphybridalfa.png','http://[host]/',0,0,0,'root','2017-08-10 16:29:40','root','2017-08-14 10:39:32',NULL,0,0,0,0,0,'',3,NULL,0,0),('C91415F0-0F2F-41C3-8FB1-976FA5C0A08A','Baresip Client','baresip',1,'baresip-s-icon.png','http://[host]/',0,850,460,'root','2015-03-03 13:37:31','root','2018-03-29 19:12:28','BaresipRest',0,1,0,100,0,NULL,3,NULL,1,0),('D1A93E03-1B04-482D-B24A-F7BEB09C0090','Uppgradera firmware','Nomada IP XL v6.6.8',0,'uppgraderafw-icon-95x10.gif',NULL,0,0,0,'root','2014-09-29 12:39:47','root','2014-09-29 12:40:09',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('d620f852-4b36-410a-a3a1-69f463767619','Luci Live MAC ','LuciLiveClient_2.5.9_MAC',0,'LuciLive-logo.png',NULL,0,0,0,'root','2018-01-31 13:52:58','root','2018-01-31 13:53:29',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('D974D577-1921-4410-BE22-D2C7E7663B06','ME-UMAC2 - C','ME-UMAC2-C/1.3',1,'UMAC-CII.png',NULL,0,0,0,'root','2016-04-21 17:50:16','root','2016-11-08 12:00:17','Umac',0,0,0,0,0,NULL,3,NULL,0,0),('e7b19bd0-4646-4c6a-af04-4cf085ac576f','Luci Live Windows','LuciLiveClient',0,'LuciLive-logo.png',NULL,0,0,0,'root','2018-03-19 13:28:51','root','2018-03-19 14:42:18',NULL,0,0,0,0,0,NULL,3,NULL,0,0),('EE394836-E09B-4CC5-91A6-0589BEFC61CF','UmacMK2','ME-UMAC2-M',1,'me-umac-m2-icon.png',NULL,0,0,0,'root','2015-05-20 10:06:45','root','2017-12-15 09:00:20','Umac',0,0,0,0,0,NULL,3,NULL,0,0),('F310F519-08C7-499A-A102-C02B7A35485C','Bria','Bria',0,'bria.png','http://[host]/',0,0,0,'root','2014-09-29 12:29:02','root','2018-03-07 14:20:33',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('F4950560-BF03-4C01-81C5-435C53587238','LuciLive','LUCI',0,'LuciLive-logo.png',NULL,0,0,0,'root','2014-09-29 12:30:08','root','2018-01-31 13:48:35',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('FB74B158-4C1A-4653-8253-3107C8B38ADD','Media5-fone','Media5-fone',0,'media5-icon.png',NULL,0,0,0,'root','2014-09-29 12:31:33','root','2014-09-29 12:41:57',NULL,0,0,0,0,0,NULL,0,NULL,0,0),('FDF667DF-38EA-48FD-98AB-01DC0D1AECCA','Nereus','Nereus',0,'Nereus-icon.png','http://[host]/',1,620,1000,'root','2014-09-29 12:32:05','root','2017-07-06 12:29:55',NULL,0,0,0,0,0,NULL,0,NULL,0,0); -/*!40000 ALTER TABLE `useragents` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2019-04-17 16:32:18 diff --git a/CCM.Data/Entities/CallEntity.cs b/CCM.Data/Entities/CallEntity.cs index 7e66bad6..82ba6dbf 100644 --- a/CCM.Data/Entities/CallEntity.cs +++ b/CCM.Data/Entities/CallEntity.cs @@ -24,10 +24,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using CCM.Core.Enums; using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using CCM.Core.Enums; namespace CCM.Data.Entities { @@ -36,28 +36,34 @@ public class CallEntity { [Key] public Guid Id { get; set; } - public string SipCallID { get; set; } public DateTime Started { get; set; } public DateTime Updated { get; set; } - public SipCallState? State { get; set; } + public SipCallState? State { get; set; } // TODO: maybe remove this column, in use? public bool Closed { get; set; } - public bool IsPhoneCall { get; set; } + public bool IsPhoneCall { get; set; } // TODO Enum and change name? + public string SDP { get; set; } - public string DlgHashId { get; set; } - public string DlgHashEnt { get; set; } + [Column("SipCallID")] + public string DialogCallId { get; set; } // TODO: Rename Column... + [Column("DlgHashId")] + public string DialogHashId { get; set; } + [Column("DlgHashEnt")] + public string DialogHashEnt { get; set; } public Guid? FromId { get; set; } [ForeignKey("FromId")] - public virtual RegisteredSipEntity FromSip { get; set; } + public virtual RegisteredCodecEntity FromCodec { get; set; } // TODO: Rename "FromUserAgent" public string FromUsername { get; set; } public string FromDisplayName { get; set; } - public string FromTag { get; set; } // Not in use? + public string FromTag { get; set; } // TODO: Not in use? + public string FromCategory { get; set; } public Guid? ToId { get; set; } [ForeignKey("ToId")] - public virtual RegisteredSipEntity ToSip { get; set; } + public virtual RegisteredCodecEntity ToCodec { get; set; } // TODO: Rename "ToUserAgent" public string ToUsername { get; set; } public string ToDisplayName { get; set; } - public string ToTag { get; set; } // Not in use? + public string ToTag { get; set; } // TODO: Not in use? + public string ToCategory { get; set; } } } diff --git a/CCM.Data/Entities/CallHistoryEntity.cs b/CCM.Data/Entities/CallHistoryEntity.cs index a27f934f..9c692845 100644 --- a/CCM.Data/Entities/CallHistoryEntity.cs +++ b/CCM.Data/Entities/CallHistoryEntity.cs @@ -36,14 +36,19 @@ public class CallHistoryEntity [Key] public Guid Id { get; set; } public Guid CallId { get; set; } - public string SipCallId { get; set; } public DateTime Started { get; set; } public DateTime Ended { get; set; } - public string DlgHashId { get; set; } - public string DlgHashEnt { get; set; } - public string ToTag { get; set; } - public string FromTag { get; set; } + public bool IsPhoneCall { get; set; } + + [Column("SipCallId")] + public string DialogCallId { get; set; } + [Column("DlgHashId")] + public string DialogHashId { get; set; } + [Column("DlgHashEnt")] + public string DialogHashEnt { get; set; } + public Guid FromId { get; set; } + public string FromTag { get; set; } public string FromSip { get; set; } public string FromUsername { get; set; } public string FromDisplayName { get; set; } @@ -52,15 +57,22 @@ public class CallHistoryEntity public string FromLocationName { get; set; } public string FromLocationComment { get; set; } public string FromLocationShortName { get; set; } + [Column("FromLocCat")] + public string FromLocationCategory { get; set; } public Guid FromCodecTypeId { get; set; } public string FromCodecTypeName { get; set; } public string FromCodecTypeColor { get; set; } + [Column("FromTypeCat")] + public string FromCodecTypeCategory { get; set; } public Guid FromOwnerId { get; set; } public string FromOwnerName { get; set; } public Guid FromRegionId { get; set; } public string FromRegionName { get; set; } - public string FromUserAgentHead { get; set; } + [Column("FromUserAgentHead")] + public string FromUserAgentHeader { get; set; } + public Guid ToId { get; set; } + public string ToTag { get; set; } public string ToSip { get; set; } public string ToUsername { get; set; } public string ToDisplayName { get; set; } @@ -69,15 +81,18 @@ public class CallHistoryEntity public string ToLocationName { get; set; } public string ToLocationComment { get; set; } public string ToLocationShortName { get; set; } + [Column("ToLocCat")] + public string ToLocationCategory { get; set; } public Guid ToCodecTypeId { get; set; } public string ToCodecTypeName { get; set; } public string ToCodecTypeColor { get; set; } + [Column("ToTypeCat")] + public string ToCodecTypeCategory { get; set; } public Guid ToOwnerId { get; set; } public string ToOwnerName { get; set; } public Guid ToRegionId { get; set; } public string ToRegionName { get; set; } - public string ToUserAgentHead { get; set; } - public bool IsPhoneCall { get; set; } - + [Column("ToUserAgentHead")] + public string ToUserAgentHeader { get; set; } } } diff --git a/CCM.Data/Entities/CodecPresetEntity.cs b/CCM.Data/Entities/CategoryEntity.cs similarity index 86% rename from CCM.Data/Entities/CodecPresetEntity.cs rename to CCM.Data/Entities/CategoryEntity.cs index 3addd86e..0d85a323 100644 --- a/CCM.Data/Entities/CodecPresetEntity.cs +++ b/CCM.Data/Entities/CategoryEntity.cs @@ -26,14 +26,20 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using CCM.Core.Attributes; +using CCM.Core.Interfaces; using CCM.Data.Entities.Base; namespace CCM.Data.Entities { - [Table("CodecPresets")] - public class CodecPresetEntity : EntityBase + [Table("Categories")] + public class CategoryEntity : EntityBase, ISipFilter { + [MetaProperty] public string Name { get; set; } + public string Description { get; set; } + + public virtual ICollection Locations { get; set; } public virtual ICollection UserAgents { get; set; } } } diff --git a/CCM.Data/Entities/CodecPresetUserAgentEntity.cs b/CCM.Data/Entities/CodecPresetUserAgentEntity.cs deleted file mode 100644 index d1d2f0af..00000000 --- a/CCM.Data/Entities/CodecPresetUserAgentEntity.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - -namespace CCM.Data.Entities -{ - [Table("CodecPresetUserAgents")] - public class CodecPresetUserAgentEntity - { - [Key, ForeignKey("CodecPreset"), Column(Order = 0)] - public Guid CodecPresetId { get; set; } - - [Key, ForeignKey("UserAgent"), Column(Order = 1)] - public Guid UserAgentId { get; set; } - - } -} diff --git a/CCM.Data/Entities/CodecTypeEntity.cs b/CCM.Data/Entities/CodecTypeEntity.cs index 7caef85f..69b75370 100644 --- a/CCM.Data/Entities/CodecTypeEntity.cs +++ b/CCM.Data/Entities/CodecTypeEntity.cs @@ -38,6 +38,7 @@ public class CodecTypeEntity : EntityBase, ISipFilter [MetaProperty] public string Name { get; set; } public string Color { get; set; } - public virtual ICollection Users { get; set; } + + public virtual ICollection SipAccounts { get; set; } } } diff --git a/CCM.Data/Entities/DocumentDb/CodecControlApiRepository.cs b/CCM.Data/Entities/DocumentDb/CodecControlApiRepository.cs deleted file mode 100644 index 0644724b..00000000 --- a/CCM.Data/Entities/DocumentDb/CodecControlApiRepository.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using CCM.Core.Entities.DocumentDb; -using CCM.Core.Interfaces.Repositories.DocumentDb; -using CCM.Data.Repositories.DocumentDb; -using LazyCache; - -namespace CCM.Data.Entities.DocumentDb -{ - /// - /// Used for JSON Document Db Storage - /// - public class CodecControlApiRepository : BaseDocumentRepository, ICodecControlApiRepository - { - public CodecControlApiRepository(IAppCache cache) : base(cache) - { - } - } -} diff --git a/CCM.Data/Entities/DocumentDb/DocumentDbEntity.cs b/CCM.Data/Entities/DocumentDb/DocumentDbEntity.cs deleted file mode 100644 index 98e7804d..00000000 --- a/CCM.Data/Entities/DocumentDb/DocumentDbEntity.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.ComponentModel.DataAnnotations.Schema; -using System.Runtime.Serialization; - -namespace CCM.Data.Entities.DocumentDb -{ - /// - /// Used for JSON Document Db Storage - /// - [DataContract] - public abstract class DocumentDbEntity - { - [DataMember] public int Id { get; set; } - [DataMember] public string JsonData { get; set; } - [DataMember] public int ContentId { get; set; } - [DataMember] public string UpdatedByUser { get; set; } - [DataMember] public DateTime UpdatedDateTime { get; set; } - } - - [Table("CodecControlApi")] - public class CodecControlApiEntity : DocumentDbEntity - { - //public string Name { get; set; } - //public string Description { get; set; } - //public string DeviceSerial { get; set; } - } -} diff --git a/CCM.Data/Entities/LocationEntity.cs b/CCM.Data/Entities/LocationEntity.cs index 32d073d7..0a36a618 100644 --- a/CCM.Data/Entities/LocationEntity.cs +++ b/CCM.Data/Entities/LocationEntity.cs @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using CCM.Core.Attributes; using CCM.Core.Interfaces; @@ -45,7 +46,7 @@ public class LocationEntity : EntityBase, ISipFilter // IP v4 public string Net_Address_v4 { get; set; } - // CIDR = Classless Inter-Domain Routing. Decides the network size. + /// CIDR = Classless Inter-Domain Routing. Decides the network size. public byte? Cidr { get; set; } // IP v6 @@ -56,15 +57,24 @@ public class LocationEntity : EntityBase, ISipFilter public string CarrierConnectionId { get; set; } [MetaType] - public virtual CityEntity City { get; set; } - - public virtual ICollection RegisteredSips { get; set; } + [ForeignKey("ProfileGroup_Id")] + public virtual ProfileGroupEntity ProfileGroup { get; set; } + public Guid? Region_Id { get; set; } [MetaType] + [ForeignKey(nameof(Region_Id))] public virtual RegionEntity Region { get; set; } + public Guid? City_Id { get; set; } [MetaType] - public virtual ProfileGroupEntity ProfileGroup { get; set; } + [ForeignKey(nameof(City_Id))] + public virtual CityEntity City { get; set; } + + public Guid? Category_Id { get; set; } + [MetaType] + [ForeignKey(nameof(Category_Id))] + public virtual CategoryEntity Category { get; set; } + public virtual ICollection RegisteredSips { get; set; } } -} \ No newline at end of file +} diff --git a/CCM.Data/Entities/OwnerEntity.cs b/CCM.Data/Entities/OwnerEntity.cs index 0da944b3..4a418088 100644 --- a/CCM.Data/Entities/OwnerEntity.cs +++ b/CCM.Data/Entities/OwnerEntity.cs @@ -38,6 +38,6 @@ public class OwnerEntity : EntityBase, ISipFilter [MetaProperty] public string Name { get; set; } - public virtual ICollection Users { get; set; } + public virtual ICollection SipAccounts { get; set; } } } diff --git a/CCM.Data/Entities/ProfileEntity.cs b/CCM.Data/Entities/ProfileCodecEntity.cs similarity index 85% rename from CCM.Data/Entities/ProfileEntity.cs rename to CCM.Data/Entities/ProfileCodecEntity.cs index 558228b4..634ef794 100644 --- a/CCM.Data/Entities/ProfileEntity.cs +++ b/CCM.Data/Entities/ProfileCodecEntity.cs @@ -31,15 +31,20 @@ namespace CCM.Data.Entities { [Table("Profiles")] - public class ProfileEntity : EntityBase + public class ProfileCodecEntity : EntityBase { public string Name { get; set; } public string Description { get; set; } + /// + /// Should contain a detailed description about the codec contents + /// + public string LongDescription { get; set; } public string Sdp { get; set; } + //[Column("SortIndex")] + //public int SortIndex { get; set; } // TODO: Remove from table in database? - [Column("SortIndex")] - public int SortIndex { get; set; } // TODO: is this one actually in use? public virtual ICollection ProfileGroups { get; set; } + public virtual ICollection UserAgents { get; set; } } } diff --git a/CCM.Data/Entities/ProfileGroupProfileOrderEntity.cs b/CCM.Data/Entities/ProfileGroupProfileOrderEntity.cs index fe1ed97d..0f3dac5e 100644 --- a/CCM.Data/Entities/ProfileGroupProfileOrderEntity.cs +++ b/CCM.Data/Entities/ProfileGroupProfileOrderEntity.cs @@ -40,10 +40,9 @@ public class ProfileGroupProfileOrdersEntity public Guid ProfileId { get; set; } public virtual ProfileGroupEntity ProfileGroup { get; set; } - public virtual ProfileEntity Profile { get; set; } + public virtual ProfileCodecEntity Profile { get; set; } [Column("SortIndex")] - public int SortIndex { get; set; } - //public int SortIndexForProfileInGroup { get; set; } // TODO: Rename this so that we know + public int SortIndexForProfileInGroup { get; set; } } } diff --git a/CCM.Data/Entities/RegisteredSipEntity.cs b/CCM.Data/Entities/RegisteredCodecEntity.cs similarity index 93% rename from CCM.Data/Entities/RegisteredSipEntity.cs rename to CCM.Data/Entities/RegisteredCodecEntity.cs index 112c8745..d9a4eb9b 100644 --- a/CCM.Data/Entities/RegisteredSipEntity.cs +++ b/CCM.Data/Entities/RegisteredCodecEntity.cs @@ -32,7 +32,7 @@ namespace CCM.Data.Entities { [Table("RegisteredSips")] - public class RegisteredSipEntity + public class RegisteredCodecEntity { [Key] public Guid Id { get; set; } @@ -64,20 +64,18 @@ public class RegisteredSipEntity public long ServerTimeStamp { get; set; } public DateTime Updated { get; set; } public int Expires { get; set; } - public Guid? Location_LocationId { get; set; } + public Guid? Location_LocationId { get; set; } [MetaType] - [ForeignKey("Location_LocationId")] + [ForeignKey(nameof(Location_LocationId))] public virtual LocationEntity Location { get; set; } public Guid? User_UserId { get; set; } - [MetaType] [ForeignKey(nameof(User_UserId))] public virtual SipAccountEntity User { get; set; } - public Guid? UserAgentId { get; set; } - + public Guid? UserAgentId { get; set; } // TODO: Redo this so it looks like everything else... [MetaType] [ForeignKey(nameof(UserAgentId))] public virtual UserAgentEntity UserAgent { get; set; } diff --git a/CCM.Data/Entities/RoleEntity.cs b/CCM.Data/Entities/RoleEntity.cs index 1d57bd14..3aaec535 100644 --- a/CCM.Data/Entities/RoleEntity.cs +++ b/CCM.Data/Entities/RoleEntity.cs @@ -30,10 +30,11 @@ namespace CCM.Data.Entities { - [Table("Roles")] + [Table("Roles")] // TODO: Roles should probably be removed from the database and specified in settings table or directly in code public class RoleEntity : EntityBase { public string Name { get; set; } + public virtual ICollection Users { get; set; } } } diff --git a/CCM.Data/Entities/SettingsEntity.cs b/CCM.Data/Entities/SettingsEntity.cs index ea39c83b..73c70be3 100644 --- a/CCM.Data/Entities/SettingsEntity.cs +++ b/CCM.Data/Entities/SettingsEntity.cs @@ -29,7 +29,7 @@ namespace CCM.Data.Entities { - [Table("Settings")] + [Table("Settings")] // TODO: make sure there is default values somewhere else if none is defined here. public class SettingEntity : EntityBase { public string Name { get; set; } diff --git a/CCM.Data/Entities/SipAccountEntity.cs b/CCM.Data/Entities/SipAccountEntity.cs index 4bc46e05..19747b85 100644 --- a/CCM.Data/Entities/SipAccountEntity.cs +++ b/CCM.Data/Entities/SipAccountEntity.cs @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using CCM.Core.Attributes; @@ -44,12 +45,24 @@ public class SipAccountEntity : EntityBase, ISipFilter public bool AccountLocked { get; set; } public string Password { get; set; } + /// Filled in on registration + public DateTime? LastUsed { get; set; } + /// Filled in on registration + public string LastUserAgent { get; set; } + /// Filled in on registration + public string LastKnownAddress { get; set; } + + /// An external reference that can be used to link accounts in other systems + public string ExternalReference { get; set; } + [MetaType] + [ForeignKey("Owner_Id")] public virtual OwnerEntity Owner { get; set; } [MetaType] + [ForeignKey("CodecType_Id")] public virtual CodecTypeEntity CodecType { get; set; } - public virtual ICollection RegisteredSips { get; set; } + public virtual ICollection RegisteredSips { get; set; } } } diff --git a/CCM.Data/Entities/StudioEntity.cs b/CCM.Data/Entities/StudioEntity.cs deleted file mode 100644 index eec3c1cd..00000000 --- a/CCM.Data/Entities/StudioEntity.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.ComponentModel.DataAnnotations.Schema; -using CCM.Data.Entities.Base; - -namespace CCM.Data.Entities -{ - [Table("Studios")] - public class StudioEntity : EntityBase - { - public string Name { get; set; } - public string CodecSipAddress { get; set; } - public string CameraAddress { get; set; } - public bool CameraActive { get; set; } - public string CameraUsername { get; set; } - public string CameraPassword { get; set; } - public string CameraVideoUrl { get; set; } - public string CameraImageUrl { get; set; } - public string CameraPlayAudioUrl { get; set; } - public string AudioClipNames { get; set; } - public string InfoText { get; set; } - public string MoreInfoUrl { get; set; } - public int NrOfAudioInputs { get; set; } - public string AudioInputNames { get; set; } - public int AudioInputDefaultGain { get; set; } - public int NrOfGpos { get; set; } - public string GpoNames { get; set; } - public int InactivityTimeout { get; set; } - } -} diff --git a/CCM.Data/Entities/UserAgentEntity.cs b/CCM.Data/Entities/UserAgentEntity.cs index c0aee8cd..6aabb00c 100644 --- a/CCM.Data/Entities/UserAgentEntity.cs +++ b/CCM.Data/Entities/UserAgentEntity.cs @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using CCM.Core.Attributes; @@ -33,39 +34,40 @@ namespace CCM.Data.Entities { - // TODO: Redo this whole object. It's way to big and seems strange that it's needed. - // Codec Model + // TODO: Redo this whole object. It's way to big and seems strange that it's needed. Maybe rename, UserAgentModels, CodecUserAgents [Table("UserAgents")] public class UserAgentEntity : EntityBase, ISipFilter { [MetaType] public string Name { get; set; } public string Identifier { get; set; } - public MatchType MatchType { get; set; } + public UserAgentPatternMatchType MatchType { get; set; } public string Image { get; set; } - // Connected to codec control + /// Codec control part public string UserInterfaceLink { get; set; } - // True if this UserAgent uses ActiveX for web interface. - // TODO: Rename this to something else + public bool Ax { get; set; } public int Width { get; set; } public int Height { get; set; } - // Shows link to codec user interface + /// Shows link to codec user interface, for all users public bool UserInterfaceIsOpen { get; set; } public bool UseScrollbars { get; set; } - public string Api { get; set; } - public int Lines { get; set; } - public int Inputs { get; set; } - public int NrOfGpos { get; set; } - public int MaxInputDb { get; set; } - public int MinInputDb { get; set; } + public string Api { get; set; } // TODO: Keep this one but link it to new table, for queries that is interested.. Maybe Guid? + //public int Lines { get; set; } // TODO: remove from db table + //public int Inputs { get; set; } // TODO: remove from db table + // public int NrOfGpos { get; set; } // TODO: remove from db table + // public int MaxInputDb { get; set; } // TODO: remove from db table + // public int MinInputDb { get; set; } // TODO: remove from db table public string Comment { get; set; } - public int InputGainStep { get; set; } - public string GpoNames { get; set; } + // public int InputGainStep { get; set; } // TODO: remove from db table + // public string GpoNames { get; set; } // TODO: remove from db table + + public Guid? Category_Id { get; set; } + [MetaType] + [ForeignKey(nameof(Category_Id))] + public virtual CategoryEntity Category { get; set; } public virtual ICollection OrderedProfiles { get; set; } - //public virtual ICollection RegisteredSips { get; set; } // TODO: ZZZ Registered sips should maybe not anymore be here?? - public virtual ICollection CodecPresets { get; set; } } } diff --git a/CCM.Data/Entities/UserAgentProfileOrderEntity.cs b/CCM.Data/Entities/UserAgentProfileOrderEntity.cs index 68061de9..0729b1b7 100644 --- a/CCM.Data/Entities/UserAgentProfileOrderEntity.cs +++ b/CCM.Data/Entities/UserAgentProfileOrderEntity.cs @@ -33,14 +33,19 @@ namespace CCM.Data.Entities [Table("UserAgentProfileOrders")] public class UserAgentProfileOrderEntity { - [Key, ForeignKey("UserAgent"), Column("UserAgentId", Order = 0)] + [ForeignKey("UserAgentId")] + public virtual UserAgentEntity UserAgent { get; set; } + + [Key, Column("UserAgentId", Order = 0)] public Guid UserAgentId { get; set; } - [Key, ForeignKey("Profile"), Column("ProfileId", Order = 1)] + [ForeignKey("ProfileId")] + public virtual ProfileCodecEntity Profile { get; set; } + + [Key, Column("ProfileId", Order = 1)] public Guid ProfileId { get; set; } - public virtual UserAgentEntity UserAgent { get; set; } - public virtual ProfileEntity Profile { get; set; } - public int SortIndex { get; set; } + [Column("SortIndex")] + public int ProfileSortIndexForUserAgent { get; set; } } } diff --git a/CCM.Data/Entities/UserEntity.cs b/CCM.Data/Entities/UserEntity.cs index af29d4e4..615cf142 100644 --- a/CCM.Data/Entities/UserEntity.cs +++ b/CCM.Data/Entities/UserEntity.cs @@ -38,6 +38,8 @@ public class UserEntity : EntityBase public string Comment { get; set; } public string PasswordHash { get; set; } public string Salt { get; set; } + + [ForeignKey("Role_Id")] public virtual RoleEntity Role { get; set; } } } diff --git a/CCM.Data/Helpers/CallDisplayNameHelper.cs b/CCM.Data/Helpers/CallDisplayNameHelper.cs index e331cff8..5fd0d39d 100644 --- a/CCM.Data/Helpers/CallDisplayNameHelper.cs +++ b/CCM.Data/Helpers/CallDisplayNameHelper.cs @@ -33,15 +33,23 @@ namespace CCM.Data.Helpers { public class CallDisplayNameHelper { - public static string GetDisplayName(RegisteredSipEntity regSip, string callDisplayName, string callUserName, string sipDomain) + /// + /// + /// + /// Registered user-agent object + /// Could be different if a user-agent is not registered + /// Could be different if a user-agent is not registered + /// + /// + public static string GetDisplayName(RegisteredCodecEntity regCodec, string callDisplayName, string callUserName, string sipDomain) { return DisplayNameHelper.GetDisplayName( - regSip != null ? regSip.DisplayName : string.Empty, - regSip != null && regSip.User != null ? regSip.User.DisplayName : string.Empty, + regCodec?.User?.DisplayName ?? string.Empty, + regCodec?.DisplayName ?? string.Empty, callDisplayName, - regSip != null ? regSip.Username : string.Empty, - regSip != null ? regSip.SIP : string.Empty, + regCodec?.SIP ?? string.Empty, callUserName, + string.Empty, sipDomain); } } diff --git a/CCM.Data/Properties/AssemblyInfo.cs b/CCM.Data/Properties/AssemblyInfo.cs deleted file mode 100644 index 1971a9fc..00000000 --- a/CCM.Data/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("CCM.Data")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Sveriges Radio AB")] -[assembly: AssemblyProduct("CCM.Data")] -[assembly: AssemblyCopyright("Copyright © Sveriges Radio AB 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f939ec4f-eb6b-491c-9744-9e6cee2fc308")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.0.0")] -[assembly: AssemblyFileVersion("0.1.0.0")] diff --git a/CCM.Data/README.md b/CCM.Data/README.md index d82dee48..9003bef7 100644 --- a/CCM.Data/README.md +++ b/CCM.Data/README.md @@ -20,6 +20,7 @@ Verify the file "Web.config" and that the "CCMDbContext" settings are present as ### Initiate new database +TODO: Remove this part.. not the way for .NET core If this is your first time running, set the Web.Config variable “Environment” to “Initiate”. Select what type of creation you prefer in the file “CCM.Data -> CCMDbContext.cs” you can select between: diff --git a/CCM.Data/Repositories/BaseRepository.cs b/CCM.Data/Repositories/BaseRepository.cs index 1adf6765..ee0ac634 100644 --- a/CCM.Data/Repositories/BaseRepository.cs +++ b/CCM.Data/Repositories/BaseRepository.cs @@ -26,12 +26,10 @@ using System; using System.Collections.Generic; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; using System.Linq.Expressions; -using System.Threading; using CCM.Core.Entities.Base; -using CCM.Core.Helpers; using CCM.Core.Interfaces.Repositories.Base; using CCM.Data.Entities.Base; using LazyCache; @@ -40,7 +38,7 @@ namespace CCM.Data.Repositories { public abstract class BaseRepository : BaseRepository, IRepository where T : CoreEntityBase, new() where TU : EntityBase { - protected BaseRepository(IAppCache cache) : base(cache) + protected BaseRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } @@ -55,26 +53,20 @@ public virtual T GetById(Guid id) public virtual T GetById(Guid id, Expression> includeExpression) { - using (var db = GetDbContext()) - { - IQueryable query = db.Set(); - query = includeExpression != null ? query.Include(includeExpression) : query; - var dbEntity = query.SingleOrDefault(g => g.Id == id); - return MapToCoreObject(dbEntity); - } + IQueryable query = _ccmDbContext.Set(); + query = includeExpression != null ? query.Include(includeExpression) : query; + var dbEntity = query.SingleOrDefault(g => g.Id == id); + return MapToCoreObject(dbEntity); } public abstract List GetAll(); protected virtual List GetAll(Expression> includeExpression) { - using (var db = GetDbContext()) - { - IQueryable query = db.Set(); - query = includeExpression != null ? query.Include(includeExpression) : query; - var dbEntities = query.ToList(); - return dbEntities.Select(MapToCoreObject).ToList(); - } + IQueryable query = _ccmDbContext.Set(); + query = includeExpression != null ? query.Include(includeExpression) : query; + var dbEntities = query.ToList(); + return dbEntities.Select(MapToCoreObject).ToList(); } protected List GetList( @@ -82,27 +74,24 @@ protected List GetList( Expression> includeExpression, Func orderbyFunction) { - using (var db = GetDbContext()) + IQueryable query = _ccmDbContext.Set(); + if (includeExpression != null) { - IQueryable query = db.Set(); - if (includeExpression != null) - { - query = query.Include(includeExpression); - } + query = query.Include(includeExpression); + } - if (whereExpression != null) - { - query = query.Where(whereExpression); - } - var dbEntities = query.ToList(); + if (whereExpression != null) + { + query = query.Where(whereExpression); + } + var dbEntities = query.ToList(); - var list = dbEntities.Select(MapToCoreObject); - if (orderbyFunction != null) - { - list = list.OrderBy(orderbyFunction); - } - return list.ToList(); + var list = dbEntities.Select(MapToCoreObject); + if (orderbyFunction != null) + { + list = list.OrderBy(orderbyFunction); } + return list.ToList(); } public abstract T MapToCoreObject(TU dbEntity); @@ -111,25 +100,12 @@ protected List GetList( public abstract class BaseRepository { private readonly IAppCache _cache; + public readonly CcmDbContext _ccmDbContext; - protected BaseRepository(IAppCache cache) + protected BaseRepository(IAppCache cache, CcmDbContext ccmDbContext) { _cache = cache; - } - - protected CcmDbContext GetDbContext() - { - return new CcmDbContext(_cache); - } - - protected bool CurrentUserIsAdmin() - { - return Thread.CurrentPrincipal.IsInRole(Roles.Admin); - } - - protected string CurrentUserName() - { - return Thread.CurrentPrincipal.Identity.Name; + _ccmDbContext = ccmDbContext; } } } diff --git a/CCM.Data/Repositories/CallHistoryRepository.cs b/CCM.Data/Repositories/CallHistoryRepository.cs index 13cc0fdc..abc4b47c 100644 --- a/CCM.Data/Repositories/CallHistoryRepository.cs +++ b/CCM.Data/Repositories/CallHistoryRepository.cs @@ -34,252 +34,259 @@ using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; +using Microsoft.EntityFrameworkCore; namespace CCM.Data.Repositories { public class CallHistoryRepository : BaseRepository, ICallHistoryRepository { - public CallHistoryRepository(IAppCache cache) : base(cache) + public CallHistoryRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public bool Save(CallHistory callHistory) { - using (var db = GetDbContext()) - { - CallHistoryEntity dbCallHistory = null; + CallHistoryEntity dbCallHistory = null; - if (callHistory.CallHistoryId != Guid.Empty) - { - dbCallHistory = db.CallHistories.SingleOrDefault(c => c.Id == callHistory.CallHistoryId); - } + if (callHistory.CallHistoryId != Guid.Empty) + { + dbCallHistory = _ccmDbContext.CallHistories.FirstOrDefault(c => c.Id == callHistory.CallHistoryId); + } - if (dbCallHistory == null) + if (dbCallHistory == null) + { + dbCallHistory = new CallHistoryEntity { - dbCallHistory = new CallHistoryEntity { Id = Guid.NewGuid() }; - callHistory.CallHistoryId = dbCallHistory.Id; - db.CallHistories.Add(dbCallHistory); - } - - dbCallHistory.CallId = callHistory.CallId; - dbCallHistory.DlgHashEnt = callHistory.DlgHashEnt; - dbCallHistory.DlgHashId = callHistory.DlgHashId; - dbCallHistory.Ended = callHistory.Ended; - dbCallHistory.FromCodecTypeColor = callHistory.FromCodecTypeColor; - dbCallHistory.FromCodecTypeId = callHistory.FromCodecTypeId; - dbCallHistory.FromCodecTypeName = callHistory.FromCodecTypeName; - dbCallHistory.FromComment = callHistory.FromComment; - dbCallHistory.FromDisplayName = callHistory.FromDisplayName; - dbCallHistory.FromId = callHistory.FromId; - dbCallHistory.FromLocationId = callHistory.FromLocationId; - dbCallHistory.FromLocationComment = callHistory.FromLocationComment; - dbCallHistory.FromLocationName = callHistory.FromLocationName; - dbCallHistory.FromLocationShortName = callHistory.FromLocationShortName; - dbCallHistory.FromOwnerId = callHistory.FromOwnerId; - dbCallHistory.FromOwnerName = callHistory.FromOwnerName; - dbCallHistory.FromRegionId = callHistory.FromRegionId; - dbCallHistory.FromRegionName = callHistory.FromRegionName; - dbCallHistory.FromSip = callHistory.FromSip; - dbCallHistory.FromTag = callHistory.FromTag; - dbCallHistory.FromUserAgentHead = callHistory.FromUserAgentHead; - dbCallHistory.FromUsername = callHistory.FromUsername; - dbCallHistory.SipCallId = callHistory.SipCallId; - dbCallHistory.Started = callHistory.Started; - dbCallHistory.ToCodecTypeColor = callHistory.ToCodecTypeColor; - dbCallHistory.ToCodecTypeId = callHistory.ToCodecTypeId; - dbCallHistory.ToCodecTypeName = callHistory.ToCodecTypeName; - dbCallHistory.ToComment = callHistory.ToComment; - dbCallHistory.ToDisplayName = callHistory.ToDisplayName; - dbCallHistory.ToId = callHistory.ToId; - dbCallHistory.ToLocationId = callHistory.ToLocationId; - dbCallHistory.ToLocationComment = callHistory.ToLocationComment; - dbCallHistory.ToLocationName = callHistory.ToLocationName; - dbCallHistory.ToLocationShortName = callHistory.ToLocationShortName; - dbCallHistory.ToOwnerId = callHistory.ToOwnerId; - dbCallHistory.ToOwnerName = callHistory.ToOwnerName; - dbCallHistory.ToRegionId = callHistory.ToRegionId; - dbCallHistory.ToRegionName = callHistory.ToRegionName; - dbCallHistory.ToSip = callHistory.ToSip; - dbCallHistory.ToTag = callHistory.ToTag; - dbCallHistory.ToUserAgentHead = callHistory.ToUserAgentHead; - dbCallHistory.ToUsername = callHistory.ToUsername; - dbCallHistory.IsPhoneCall = callHistory.IsPhoneCall; - - db.SaveChanges(); - return true; + Id = Guid.NewGuid() + }; + callHistory.CallHistoryId = dbCallHistory.Id; + _ccmDbContext.CallHistories.Add(dbCallHistory); } + + dbCallHistory.CallId = callHistory.CallId; + + dbCallHistory.DialogCallId = callHistory.DialogCallId; + dbCallHistory.DialogHashEnt = callHistory.DialogHashEnt; + dbCallHistory.DialogHashId = callHistory.DialogHashId; + + dbCallHistory.Started = callHistory.Started; + dbCallHistory.Ended = callHistory.Ended; + dbCallHistory.IsPhoneCall = callHistory.IsPhoneCall; + + dbCallHistory.FromCodecTypeCategory = callHistory.FromCodecTypeCategory; + dbCallHistory.FromCodecTypeId = callHistory.FromCodecTypeId; + dbCallHistory.FromCodecTypeName = callHistory.FromCodecTypeName; + dbCallHistory.FromCodecTypeColor = callHistory.FromCodecTypeColor; + dbCallHistory.FromComment = callHistory.FromComment; + dbCallHistory.FromDisplayName = callHistory.FromDisplayName; + dbCallHistory.FromId = callHistory.FromId; + dbCallHistory.FromLocationId = callHistory.FromLocationId; + dbCallHistory.FromLocationComment = callHistory.FromLocationComment; + dbCallHistory.FromLocationName = callHistory.FromLocationName; + dbCallHistory.FromLocationShortName = callHistory.FromLocationShortName; + dbCallHistory.FromLocationCategory = callHistory.FromLocationCategory; + dbCallHistory.FromOwnerId = callHistory.FromOwnerId; + dbCallHistory.FromOwnerName = callHistory.FromOwnerName; + dbCallHistory.FromRegionId = callHistory.FromRegionId; + dbCallHistory.FromRegionName = callHistory.FromRegionName; + dbCallHistory.FromSip = callHistory.FromSip; + dbCallHistory.FromTag = callHistory.FromTag; + dbCallHistory.FromUserAgentHeader = callHistory.FromUserAgentHeader; + dbCallHistory.FromUsername = callHistory.FromUsername; + + dbCallHistory.ToCodecTypeCategory = callHistory.ToCodecTypeCategory; + dbCallHistory.ToCodecTypeId = callHistory.ToCodecTypeId; + dbCallHistory.ToCodecTypeName = callHistory.ToCodecTypeName; + dbCallHistory.ToCodecTypeColor = callHistory.ToCodecTypeColor; + dbCallHistory.ToComment = callHistory.ToComment; + dbCallHistory.ToDisplayName = callHistory.ToDisplayName; + dbCallHistory.ToId = callHistory.ToId; + dbCallHistory.ToLocationId = callHistory.ToLocationId; + dbCallHistory.ToLocationComment = callHistory.ToLocationComment; + dbCallHistory.ToLocationName = callHistory.ToLocationName; + dbCallHistory.ToLocationShortName = callHistory.ToLocationShortName; + dbCallHistory.ToLocationCategory = callHistory.ToLocationCategory; + dbCallHistory.ToOwnerId = callHistory.ToOwnerId; + dbCallHistory.ToOwnerName = callHistory.ToOwnerName; + dbCallHistory.ToRegionId = callHistory.ToRegionId; + dbCallHistory.ToRegionName = callHistory.ToRegionName; + dbCallHistory.ToSip = callHistory.ToSip; + dbCallHistory.ToTag = callHistory.ToTag; + dbCallHistory.ToUserAgentHeader = callHistory.ToUserAgentHeader; + dbCallHistory.ToUsername = callHistory.ToUsername; + + return _ccmDbContext.SaveChanges() >= 1; } public CallHistory GetById(Guid id) { - using (var db = GetDbContext()) - { - var dbCallHistory = db.CallHistories.AsNoTracking().SingleOrDefault(c => c.Id == id); - return dbCallHistory == null ? null : MapCallHistory(dbCallHistory); - } + var dbCallHistory = _ccmDbContext.CallHistories.AsNoTracking().SingleOrDefault(c => c.Id == id); + return dbCallHistory == null ? null : MapToCallHistory(dbCallHistory); } /// - /// Used by CodecStatusHub + /// Used by WebGuiHub on frontpage /// - /// - public CallHistory GetCallHistoryByCallId(Guid callId) + public IReadOnlyCollection GetOneMonthOldCalls() { - using (var db = GetDbContext()) - { - var dbCallHistory = db.CallHistories.SingleOrDefault(c => c.CallId == callId); - return dbCallHistory == null ? null : MapCallHistory(dbCallHistory); - } + var nowTime = DateTime.Now; + var startTime = DateTime.Now.AddMonths(-1); + var callHistories = _ccmDbContext.CallHistories + .AsNoTracking() + .OrderByDescending(callHistory => callHistory.Ended) + .Where(c => c.Started <= nowTime && c.Ended >= startTime) + .ToList(); + return callHistories.Select(MapToOldCall).ToList().AsReadOnly(); } - /// - /// Used by WebGuiHub - /// - /// - /// - public IList GetOldCalls(int callCount, bool anonymize) + public IReadOnlyCollection GetOneMonthCallHistories() { - using (var db = GetDbContext()) - { - var dbCalls = db.CallHistories.OrderByDescending(callHistory => callHistory.Ended).Take(callCount).ToList(); - return dbCalls.Select(dbCall => MapToOldCall(dbCall, anonymize)).ToList(); - } + var nowTime = DateTime.Now; + var startTime = DateTime.Now.AddMonths(-1); + var callHistories = _ccmDbContext.CallHistories + .AsNoTracking() + .OrderByDescending(callHistory => callHistory.Ended) + .Where(c => c.Started <= nowTime && c.Ended >= startTime) + .ToList(); + return callHistories.Select(MapToCallHistory).ToList().AsReadOnly(); } - public IList GetOldCallsFiltered(string region, string codecType, string sipAddress, string searchString, bool anonymize, bool onlyPhoneCalls, int callCount) + private OldCall MapToOldCall(CallHistoryEntity dbCallHistory) { - using (var db = GetDbContext()) + return new OldCall { - var query = db.CallHistories.AsQueryable(); - - if (!string.IsNullOrEmpty(region)) - { - query = query.Where(ch => ch.FromRegionName == region || ch.ToRegionName == region); - } + CallId = MapGuidString(dbCallHistory.CallId), + Started = dbCallHistory.Started.ToLocalTime(), + Ended = dbCallHistory.Ended.ToLocalTime(), + Duration = dbCallHistory.Ended.Subtract(dbCallHistory.Started).ToString(@"dd\d\ hh\:mm\:ss"), + IsPhoneCall = dbCallHistory.IsPhoneCall, - if (!string.IsNullOrEmpty(codecType)) - { - query = query.Where(ch => ch.FromCodecTypeName == codecType || ch.ToCodecTypeName == codecType); - } + FromId = MapGuidString(dbCallHistory.FromId), + FromSip = dbCallHistory.FromUsername, + FromCodecTypeColor = dbCallHistory.FromCodecTypeColor, + FromCodecTypeName = dbCallHistory.FromCodecTypeName, + FromCodecTypeCategory = dbCallHistory.FromCodecTypeCategory, + FromComment = dbCallHistory.FromComment, + FromDisplayName = dbCallHistory.FromDisplayName, + FromLocationName = dbCallHistory.FromLocationName, + FromLocationShortName = dbCallHistory.FromLocationShortName, + FromRegionName = dbCallHistory.FromRegionName, + FromLocationCategory = dbCallHistory.FromLocationCategory, - if (!string.IsNullOrEmpty(sipAddress)) - { - query = query.Where(ch => ch.FromSip.Contains(sipAddress) || ch.ToSip.Contains(sipAddress)); - } + ToId = MapGuidString(dbCallHistory.ToId), + ToSip = dbCallHistory.ToUsername, + ToCodecTypeColor = dbCallHistory.ToCodecTypeColor, + ToCodecTypeName = dbCallHistory.ToCodecTypeName, + ToCodecTypeCategory = dbCallHistory.ToCodecTypeCategory, + ToComment = dbCallHistory.ToComment, + ToDisplayName = dbCallHistory.ToDisplayName, + ToLocationName = dbCallHistory.ToLocationName, + ToLocationShortName = dbCallHistory.ToLocationShortName, + ToRegionName = dbCallHistory.ToRegionName, + ToLocationCategory = dbCallHistory.ToLocationCategory + }; + } - if (onlyPhoneCalls) - { - query = query.Where(ch => ch.IsPhoneCall); - } + private string MapGuidString(Guid guid) { return guid == Guid.Empty ? string.Empty : guid.ToString(); } - if (!string.IsNullOrEmpty(searchString)) - { - query = query.Where(ch => - ch.FromDisplayName.Contains(searchString) || - ch.ToDisplayName.Contains(searchString) || - ch.FromSip.Contains(searchString) || - ch.ToSip.Contains(searchString) || - ch.FromLocationName.Contains(searchString) || - ch.ToLocationName.Contains(searchString) || - ch.FromLocationShortName.Contains(searchString) || - ch.ToLocationShortName.Contains(searchString) || - ch.FromUsername.Contains(searchString) || - ch.ToUsername.Contains(searchString) - ); - } - - var dbCalls = query.OrderByDescending(callHistory => callHistory.Ended).Take(callCount).ToList(); - return dbCalls.Select(dbCall => MapToOldCall(dbCall, anonymize)).ToList(); - } + #region Statistics + public IReadOnlyList GetOneYearCallHistory() + { + var nowTime = DateTime.Now; + var startTime = DateTime.Now.AddYears(-1); + var callHistories = _ccmDbContext.CallHistories + .AsNoTracking() + .OrderByDescending(callHistory => callHistory.Ended) + .Where(c => c.Started <= nowTime && c.Ended >= startTime) + .ToList(); + return callHistories.Select(MapToCallHistory).ToList(); } - private OldCall MapToOldCall(CallHistoryEntity dbCall, bool anonymize) + public IList GetCallHistoriesByDate(DateTime startTime, DateTime endTime) { - return new OldCall - { - CallId = GuidString(dbCall.CallId), - Started = dbCall.Started.ToLocalTime(), - Ended = dbCall.Ended.ToLocalTime(), - Duration = dbCall.Ended.Subtract(dbCall.Started).ToString(@"dd\d\ hh\:mm\:ss"), - IsPhoneCall = dbCall.IsPhoneCall, - FromId = GuidString(dbCall.FromId), - FromSip = anonymize ? DisplayNameHelper.AnonymizePhonenumber(dbCall.FromUsername) : dbCall.FromUsername, - FromCodecTypeColor = dbCall.FromCodecTypeColor, - FromCodecTypeName = dbCall.FromCodecTypeName, - FromComment = dbCall.FromComment, - FromDisplayName = anonymize ? DisplayNameHelper.AnonymizeDisplayName(dbCall.FromDisplayName) : dbCall.FromDisplayName, - FromLocationName = dbCall.FromLocationName, - FromLocationShortName = dbCall.FromLocationShortName, - FromRegionName = dbCall.FromRegionName, - ToId = GuidString(dbCall.ToId), - ToSip = anonymize ? DisplayNameHelper.AnonymizePhonenumber(dbCall.ToUsername) : dbCall.ToUsername, - ToCodecTypeColor = dbCall.ToCodecTypeColor, - ToCodecTypeName = dbCall.ToCodecTypeName, - ToComment = dbCall.ToComment, - ToDisplayName = anonymize ? DisplayNameHelper.AnonymizeDisplayName(dbCall.ToDisplayName) : dbCall.ToDisplayName, - ToLocationName = dbCall.ToLocationName, - ToLocationShortName = dbCall.ToLocationShortName, - ToRegionName = dbCall.ToRegionName - }; + return GetFiltered(c => c.Started <= endTime && c.Ended >= startTime); } - private string GuidString(Guid guid) { return guid == Guid.Empty ? string.Empty : guid.ToString(); } - - #region Statistics - public IList GetCallHistoriesByDate(DateTime startTime, DateTime endTime) + public IList GetCallHistoriesByDate(IReadOnlyList callHistories, DateTime startTime, DateTime endTime) { - return GetFiltered(c => c.Started < endTime && c.Ended >= startTime); + return callHistories.Where(c => c.Started <= endTime && c.Ended >= startTime).ToList(); } public IList GetCallHistoriesForRegion(DateTime startDate, DateTime endDate, Guid regionId) { - return regionId == Guid.Empty ? - GetFiltered(c => c.Started < endDate && c.Ended >= startDate) : - GetFiltered(c => c.Started < endDate && c.Ended >= startDate && (c.FromRegionId == regionId || c.ToRegionId == regionId)); + return regionId == Guid.Empty + ? GetFiltered(c => c.Started <= endDate && c.Ended >= startDate) + : GetFiltered(c => c.Started <= endDate && c.Ended >= startDate && (c.FromRegionId == regionId || c.ToRegionId == regionId)); + } + + public IList GetCallHistoriesForRegion(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, Guid regionId) + { + return regionId == Guid.Empty + ? callHistories.Where(c => c.Started <= endDate && c.Ended >= startDate).ToList() + : callHistories.Where(c => c.Started <= endDate && c.Ended >= startDate && (c.FromRegionId == regionId || c.ToRegionId == regionId)).ToList(); } public IList GetCallHistoriesForRegisteredSip(DateTime startDate, DateTime endDate, string sipId) { - return GetFiltered(c => c.Started < endDate && c.Ended >= startDate && (c.FromSip == sipId || c.ToSip == sipId)); + return GetFiltered(c => c.Started <= endDate && c.Ended >= startDate && (c.FromSip == sipId || c.ToSip == sipId)); + } + + public IList GetCallHistoriesForRegisteredSip(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, string sipId) + { + return callHistories.Where(c => c.Started <= endDate && c.Ended >= startDate && (c.FromSip == sipId || c.ToSip == sipId)).ToList(); } public IList GetCallHistoriesForCodecType(DateTime startDate, DateTime endDate, Guid codecTypeId) { return codecTypeId == Guid.Empty - ? GetFiltered(c => c.Started < endDate && c.Ended >= startDate) - : GetFiltered(c => c.Started < endDate && c.Ended >= startDate && (c.FromCodecTypeId == codecTypeId || c.ToCodecTypeId == codecTypeId)); + ? GetFiltered(c => c.Started <= endDate && c.Ended >= startDate) + : GetFiltered(c => c.Started <= endDate && c.Ended >= startDate && (c.FromCodecTypeId == codecTypeId || c.ToCodecTypeId == codecTypeId)); + } + + public IList GetCallHistoriesForCodecType(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, Guid codecTypeId) + { + return codecTypeId == Guid.Empty + ? callHistories.Where(c => c.Started <= endDate && c.Ended >= startDate).ToList() + : callHistories.Where(c => c.Started <= endDate && c.Ended >= startDate && (c.FromCodecTypeId == codecTypeId || c.ToCodecTypeId == codecTypeId)).ToList(); } public IList GetCallHistoriesForLocation(DateTime startDate, DateTime endDate, Guid locationId) { return locationId == Guid.Empty ? new List() - : GetFiltered(c => c.Started < endDate && c.Ended >= startDate && (c.FromLocationId == locationId || c.ToLocationId == locationId)); + : GetFiltered(c => c.Started <= endDate && c.Ended >= startDate && (c.FromLocationId == locationId || c.ToLocationId == locationId)); + } + + public IList GetCallHistoriesForLocation(IReadOnlyList callHistories, DateTime startDate, DateTime endDate, Guid locationId) + { + return locationId == Guid.Empty + ? new List() + : callHistories.Where(c => c.Started <= endDate && c.Ended >= startDate && (c.FromLocationId == locationId || c.ToLocationId == locationId)).ToList(); } private IList GetFiltered(Expression> filterExpression) { - using (var db = GetDbContext()) - { - var dbCallHistories = db.CallHistories - .AsNoTracking() - .Where(filterExpression) - .ToList(); - return dbCallHistories.Select(MapCallHistory).ToList(); - } + var dbCallHistories = _ccmDbContext.CallHistories + .AsNoTracking() + .Where(filterExpression) + .ToList(); + return dbCallHistories.Select(MapToCallHistory).ToList(); } - private CallHistory MapCallHistory(CallHistoryEntity dbCallHistory) + private CallHistory MapToCallHistory(CallHistoryEntity dbCallHistory) { return dbCallHistory == null ? null : new CallHistory() { CallHistoryId = dbCallHistory.Id, CallId = dbCallHistory.CallId, - DlgHashEnt = dbCallHistory.DlgHashEnt, - DlgHashId = dbCallHistory.DlgHashId, + DialogHashEnt = dbCallHistory.DialogHashEnt, + DialogHashId = dbCallHistory.DialogHashId, + DialogCallId = dbCallHistory.DialogCallId, + Started = dbCallHistory.Started, Ended = dbCallHistory.Ended, IsPhoneCall = dbCallHistory.IsPhoneCall, - FromCodecTypeColor = dbCallHistory.FromCodecTypeColor, + + FromCodecTypeCategory = dbCallHistory.FromCodecTypeCategory, FromCodecTypeId = dbCallHistory.FromCodecTypeId, FromCodecTypeName = dbCallHistory.FromCodecTypeName, FromComment = dbCallHistory.FromComment, @@ -289,17 +296,17 @@ private CallHistory MapCallHistory(CallHistoryEntity dbCallHistory) FromLocationComment = dbCallHistory.FromLocationComment, FromLocationName = dbCallHistory.FromLocationName, FromLocationShortName = dbCallHistory.FromLocationShortName, + FromLocationCategory = dbCallHistory.FromLocationCategory, FromOwnerId = dbCallHistory.FromOwnerId, FromOwnerName = dbCallHistory.FromOwnerName, FromRegionId = dbCallHistory.FromRegionId, FromRegionName = dbCallHistory.FromRegionName, FromSip = dbCallHistory.FromSip, FromTag = dbCallHistory.FromTag, - FromUserAgentHead = dbCallHistory.FromUserAgentHead, + FromUserAgentHeader = dbCallHistory.FromUserAgentHeader, FromUsername = dbCallHistory.FromUsername, - SipCallId = dbCallHistory.SipCallId, - Started = dbCallHistory.Started, - ToCodecTypeColor = dbCallHistory.ToCodecTypeColor, + + ToCodecTypeCategory = dbCallHistory.ToCodecTypeCategory, ToCodecTypeId = dbCallHistory.ToCodecTypeId, ToCodecTypeName = dbCallHistory.ToCodecTypeName, ToComment = dbCallHistory.ToComment, @@ -309,13 +316,14 @@ private CallHistory MapCallHistory(CallHistoryEntity dbCallHistory) ToLocationComment = dbCallHistory.ToLocationComment, ToLocationName = dbCallHistory.ToLocationName, ToLocationShortName = dbCallHistory.ToLocationShortName, + ToLocationCategory = dbCallHistory.ToLocationCategory, ToOwnerId = dbCallHistory.ToOwnerId, ToOwnerName = dbCallHistory.ToOwnerName, ToRegionId = dbCallHistory.ToRegionId, ToRegionName = dbCallHistory.ToRegionName, ToSip = dbCallHistory.ToSip, ToTag = dbCallHistory.ToTag, - ToUserAgentHead = dbCallHistory.ToUserAgentHead, + ToUserAgentHeader = dbCallHistory.ToUserAgentHeader, ToUsername = dbCallHistory.ToUsername }; } diff --git a/CCM.Data/Repositories/CallRepository.cs b/CCM.Data/Repositories/CallRepository.cs index eef1ad73..5c0bc561 100644 --- a/CCM.Data/Repositories/CallRepository.cs +++ b/CCM.Data/Repositories/CallRepository.cs @@ -26,7 +26,7 @@ using System; using System.Collections.Generic; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; using CCM.Core.Entities; using CCM.Core.Entities.Specific; @@ -37,6 +37,7 @@ using CCM.Data.Entities; using CCM.Data.Helpers; using LazyCache; +using Microsoft.Extensions.Logging; using NLog; namespace CCM.Data.Repositories @@ -45,73 +46,170 @@ public class CallRepository : BaseRepository, ICallRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - private readonly ICallHistoryRepository _callHistoryRepository; + private readonly ILogger _logger; + private readonly ICachedCallHistoryRepository _cachedCallHistoryRepository; private readonly ISettingsManager _settingsManager; - public CallRepository(ICallHistoryRepository callHistoryRepository, ISettingsManager settingsManager, IAppCache cache) : base(cache) + public CallRepository(ICachedCallHistoryRepository cachedCallHistoryRepository, ISettingsManager settingsManager, IAppCache cache, CcmDbContext ccmDbContext, ILogger logger) : base(cache, ccmDbContext) { - _callHistoryRepository = callHistoryRepository; + _cachedCallHistoryRepository = cachedCallHistoryRepository; _settingsManager = settingsManager; + _logger = logger; } public bool CallExists(string callId, string hashId, string hashEnt) { - using (var db = GetDbContext()) - { - return db.Calls.Any(c => c.SipCallID == callId && c.DlgHashId == hashId && c.DlgHashEnt == hashEnt); - } + return _ccmDbContext.Calls.Any(c => c.DialogCallId == callId && c.DialogHashId == hashId && c.DialogHashEnt == hashEnt); } - public void CloseCall(Guid callId) + /// + /// Update or add information about a call. Can be used to close calls as well + /// + /// + public void UpdateCall(Call call) { - using (var db = GetDbContext()) + try { - var dbCall = db.Calls.SingleOrDefault(c => c.Id == callId); + var dbCall = call.Id != Guid.Empty ? _ccmDbContext.Calls.FirstOrDefault(c => c.Id == call.Id) : null; if (dbCall == null) { - log.Warn("Trying to close call but call with id {0} doesn't exist", callId); - return; + var callId = Guid.NewGuid(); + call.Id = callId; + + dbCall = new CallEntity + { + Id = callId, + DialogCallId = call.CallId, + DialogHashId = call.DialogHashId, + DialogHashEnt = call.DialogHashEnt, + Started = call.Started, + + FromId = call.FromId, + FromTag = call.FromTag, + FromUsername = call.FromSip, + FromDisplayName = call.FromDisplayName, + FromCategory = call.FromCategory, + + ToId = call.ToId, + ToTag = call.ToTag, + ToUsername = call.ToSip, + ToDisplayName = call.ToDisplayName, + ToCategory = call.ToCategory, + + IsPhoneCall = call.IsPhoneCall, + SDP = call.SDP + }; + + _ccmDbContext.Calls.Add(dbCall); } - dbCall.Updated = DateTime.UtcNow; - dbCall.Closed = true; - // TODO: Is it necessary to save this closing of the call, to then remove it later? - db.SaveChanges(); + // Common properties. Updated also for existing call + var updated = DateTime.UtcNow; + call.Updated = updated; + dbCall.Updated = updated; + dbCall.State = call.State; + dbCall.Closed = call.Closed; + var success = _ccmDbContext.SaveChanges() > 0; + + if (success && call.Closed) + { + // Call ended. Save call history and delete call from db + var callHistory = MapToCallHistory(dbCall); + var callHistorySuccess = _cachedCallHistoryRepository.Save(callHistory); + if (callHistorySuccess) + { + // Remove the original call + _ccmDbContext.Calls.Remove(dbCall); + _ccmDbContext.SaveChanges(); + } + else + { + _logger.LogWarning($"Unable to save call history with call id: {call.CallId}, hash id: {call.DialogHashId}, hash ent: {call.DialogHashEnt}"); + } + } + } + catch (Exception ex) + { + log.Error(ex); + _logger.LogError(ex, $"Error saving/updating call with call id: {call.CallId}, hash id: {call.DialogHashId}, hash ent: {call.DialogHashEnt}"); + } + } + + /// + /// Closes a call and saves it to call history + /// + /// + public void CloseCall(Guid callId) + { + // TODO: Make help function that returns one call + var dbCall = _ccmDbContext.Calls + .Include(c => c.FromCodec) + .Include(c => c.FromCodec.User) + .Include(c => c.FromCodec.User.CodecType) + .Include(c => c.FromCodec.User.Owner) + .Include(c => c.FromCodec.UserAgent.Category) + .Include(c => c.FromCodec.Location) + .Include(c => c.FromCodec.Location.Region) + .Include(c => c.FromCodec.Location.Category) + .Include(c => c.ToCodec) + .Include(c => c.ToCodec.User) + .Include(c => c.ToCodec.User.CodecType) + .Include(c => c.ToCodec.User.Owner) + .Include(c => c.ToCodec.UserAgent.Category) + .Include(c => c.ToCodec.Location) + .Include(c => c.ToCodec.Location.Region) + .Include(c => c.ToCodec.Location.Category) + .SingleOrDefault(c => c.Id == callId); + + if (dbCall == null) + { + _logger.LogWarning($"Trying to close call but call with id {callId} doesn't exist"); + return; + } + + // Close call to remove it later + dbCall.Closed = true; + dbCall.Updated = DateTime.UtcNow; + var success = _ccmDbContext.SaveChanges() > 0; + + if (success) { // Save call history - var callHistory = MapToCallHistory(dbCall, _settingsManager.SipDomain); - var success = _callHistoryRepository.Save(callHistory); + var callHistory = MapToCallHistory(dbCall); + var callHistorySuccess = _cachedCallHistoryRepository.Save(callHistory); - if (success) + if (callHistorySuccess) { // Remove the original call - db.Calls.Remove(dbCall); - db.SaveChanges(); + _ccmDbContext.Calls.Remove(dbCall); + _ccmDbContext.SaveChanges(); } else { - log.Error($"Unable to save call history with the call fromSip: {dbCall.FromSip}, toSip: {dbCall.ToSip}, hash id: {dbCall.DlgHashId}, hash ent: {dbCall.DlgHashEnt}"); + _logger.LogWarning( + $"Unable to save call history with the call fromSip: {dbCall.FromCodec}, toSip: {dbCall.ToCodec}, hash id: {dbCall.DialogHashId}, hash ent: {dbCall.DialogHashEnt}"); } } } - public CallInfo GetCallInfo(string callId, string hashId, string hashEnt) // CallId, HashId and HashEntry is a unique key for calls in Kamailio + /// + /// CallId, HashId and HashEntry is a unique key for calls + /// + /// + /// + /// + /// + public CallInfo GetCallInfo(string callId, string hashId, string hashEnt) { - using (var db = GetDbContext()) - { - var dbCall = db.Calls.SingleOrDefault(c => c.SipCallID == callId && c.DlgHashId == hashId && c.DlgHashEnt == hashEnt); - return MapToCallInfo(dbCall); - } + var dbCall = _ccmDbContext.Calls.SingleOrDefault(c => c.DialogCallId == callId && c.DialogHashId == hashId && c.DialogHashEnt == hashEnt); + return MapToCallInfo(dbCall); } public CallInfo GetCallInfoById(Guid callId) { - using (var db = GetDbContext()) - { - var dbCall = db.Calls.SingleOrDefault(c => c.Id == callId); - return MapToCallInfo(dbCall); - } + var dbCall = _ccmDbContext.Calls.SingleOrDefault(c => c.Id == callId); + return MapToCallInfo(dbCall); } private CallInfo MapToCallInfo(CallEntity dbCall) @@ -134,263 +232,228 @@ public Call GetCallBySipAddress(string sipAddress) { return null; } - using (var db = GetDbContext()) - { - var dbCall = db.Calls - .OrderByDescending(c => c.Updated) // Last call in case several happens to exist in database - .FirstOrDefault(c => !c.Closed && (c.FromUsername == sipAddress || c.ToUsername == sipAddress)); - return MapCall(dbCall); - } + var dbCall = _ccmDbContext.Calls + .OrderByDescending(c => c.Updated) // Last call in case several happens to exist in database + .FirstOrDefault(c => !c.Closed && (c.FromUsername == sipAddress || c.ToUsername == sipAddress)); + + return MapToCall(dbCall); } - public void UpdateCall(Call call) + public IReadOnlyCollection GetOngoingCalls(bool anonymize) { - try - { - using (var db = GetDbContext()) - { - var dbCall = call.Id != Guid.Empty ? db.Calls.SingleOrDefault(c => c.Id == call.Id) : null; - - if (dbCall == null) - { - var callId = Guid.NewGuid(); - call.Id = callId; - - dbCall = new CallEntity - { - Id = callId, - SipCallID = call.CallId, - DlgHashId = call.DlgHashId, - DlgHashEnt = call.DlgHashEnt, - ToTag = call.ToTag, - FromTag = call.FromTag, - Started = call.Started, - FromId = call.FromId, - FromUsername = call.FromSip, - FromDisplayName = call.FromDisplayName, - ToId = call.ToId, - ToUsername = call.ToSip, - ToDisplayName = call.ToDisplayName, - IsPhoneCall = call.IsPhoneCall - }; - - db.Calls.Add(dbCall); - } - - // Common properties. Updated also for existing call - var updated = DateTime.UtcNow; - call.Updated = updated; - dbCall.Updated = updated; - dbCall.State = call.State; - dbCall.Closed = call.Closed; - - var success = db.SaveChanges() > 0; - - if (success && call.Closed) - { - // Call ended. Save call history and delete call from db - var callHistory = MapToCallHistory(dbCall, _settingsManager.SipDomain); - var callHistorySaved = _callHistoryRepository.Save(callHistory); - - if (callHistorySaved) - { - // Remove the original call - db.Calls.Remove(dbCall); - db.SaveChanges(); - } - else - { - log.Error($"Unable to save call history with call id: {call.CallId}, hash id: {call.DlgHashId}, hash ent: {call.DlgHashEnt}"); - } - } - } - } - catch (Exception ex) - { - log.Error(ex, $"Error saving/updating call with call id: {call.CallId}, hash id: {call.DlgHashId}, hash ent: {call.DlgHashEnt}"); - } + var dbCalls = _ccmDbContext.Calls + .Include(c => c.FromCodec) + .Include(c => c.FromCodec.User) + .Include(c => c.FromCodec.User.CodecType) + .Include(c => c.FromCodec.UserAgent.Category) + .Include(c => c.FromCodec.Location) + .Include(c => c.FromCodec.Location.Region) + .Include(c => c.FromCodec.Location.Category) + .Include(c => c.ToCodec) + .Include(c => c.ToCodec.User) + .Include(c => c.ToCodec.User.CodecType) + .Include(c => c.ToCodec.UserAgent.Category) + .Include(c => c.ToCodec.Location) + .Include(c => c.ToCodec.Location.Region) + .Include(c => c.ToCodec.Location.Category) + .Where(call => !call.Closed).OrderByDescending(call => call.Started).ToList(); + return dbCalls.Select(dbCall => MapToOngoingCall(dbCall, anonymize)).ToList().AsReadOnly(); } - public IReadOnlyCollection GetOngoingCalls(bool anonymize) + public OnGoingCall GetOngoingCallById(Guid callId) { - using (var db = GetDbContext()) - { - var dbCalls = db.Calls - .Include(c => c.FromSip) - .Include(c => c.FromSip.User) - .Include(c => c.FromSip.User.CodecType) - .Include(c => c.FromSip.Location) - .Include(c => c.FromSip.Location.Region) - .Include(c => c.ToSip) - .Include(c => c.ToSip.User) - .Include(c => c.ToSip.User.CodecType) - .Include(c => c.ToSip.Location) - .Include(c => c.ToSip.Location.Region) - .Where(call => !call.Closed).ToList(); - return dbCalls.Select(dbCall => MapToOngoingCall(dbCall, _settingsManager.SipDomain, anonymize)).ToList().AsReadOnly(); - } + var dbCall = _ccmDbContext.Calls.Include(c => c.FromCodec) + .Include(c => c.FromCodec.User) + .Include(c => c.FromCodec.User.CodecType) + .Include(c => c.FromCodec.UserAgent.Category) + .Include(c => c.FromCodec.Location) + .Include(c => c.FromCodec.Location.Region) + .Include(c => c.FromCodec.Location.Category) + .Include(c => c.ToCodec) + .Include(c => c.ToCodec.User) + .Include(c => c.ToCodec.User.CodecType) + .Include(c => c.ToCodec.UserAgent.Category) + .Include(c => c.ToCodec.Location) + .Include(c => c.ToCodec.Location.Region) + .Include(c => c.ToCodec.Location.Category) + .SingleOrDefault(c => c.Id == callId); + return MapToOngoingCall(dbCall, false); } - private OnGoingCall MapToOngoingCall(CallEntity dbCall, string sipDomain, bool anonymize) + private OnGoingCall MapToOngoingCall(CallEntity dbCall, bool anonymize) { // TODO: Fix this mapping, and maybe redo the query? - var fromDisplayName = CallDisplayNameHelper.GetDisplayName(dbCall.FromSip, dbCall.FromDisplayName, dbCall.FromUsername, sipDomain); - var toDisplayName = CallDisplayNameHelper.GetDisplayName(dbCall.ToSip, dbCall.ToDisplayName, dbCall.ToUsername, sipDomain); + string sipDomain = _settingsManager.SipDomain; + var fromDisplayName = CallDisplayNameHelper.GetDisplayName(dbCall.FromCodec, dbCall.FromDisplayName, dbCall.FromUsername, sipDomain); + var toDisplayName = CallDisplayNameHelper.GetDisplayName(dbCall.ToCodec, dbCall.ToDisplayName, dbCall.ToUsername, sipDomain); var onGoingCall = new OnGoingCall { - CallId = GuidHelper.GuidString(dbCall.Id), + CallId = GuidHelper.AsString(dbCall.Id), Started = dbCall.Started, - FromId = GuidHelper.GuidString(dbCall.FromId), + SDP = dbCall.SDP, + IsPhoneCall = dbCall.IsPhoneCall, + + FromId = GuidHelper.AsString(dbCall.FromId), FromSip = anonymize ? DisplayNameHelper.AnonymizePhonenumber(dbCall.FromUsername) : dbCall.FromUsername, FromDisplayName = anonymize ? DisplayNameHelper.AnonymizeDisplayName(fromDisplayName) : fromDisplayName, - FromCodecTypeColor = dbCall.FromSip != null && dbCall.FromSip.User != null && dbCall.FromSip.User.CodecType != null ? dbCall.FromSip.User.CodecType.Color : string.Empty, - FromCodecTypeName = dbCall.FromSip != null && dbCall.FromSip.User != null && dbCall.FromSip.User.CodecType != null ? dbCall.FromSip.User.CodecType.Name : string.Empty, - FromComment = dbCall.FromSip != null && dbCall.FromSip.User != null ? dbCall.FromSip.User.Comment : string.Empty, - FromLocationName = dbCall.FromSip != null && dbCall.FromSip.Location != null ? dbCall.FromSip.Location.Name : string.Empty, - FromLocationShortName = dbCall.FromSip != null && dbCall.FromSip.Location != null ? dbCall.FromSip.Location.ShortName : string.Empty, - FromRegionName = dbCall.FromSip != null && dbCall.FromSip.Location != null && dbCall.FromSip.Location.Region != null ? dbCall.FromSip.Location.Region.Name : string.Empty, - ToId = GuidHelper.GuidString(dbCall.ToId), + FromCodecTypeColor = dbCall.FromCodec?.User?.CodecType?.Color ?? string.Empty, + FromCodecTypeName = dbCall.FromCodec?.User?.CodecType?.Name ?? string.Empty, + FromCodecTypeCategory = dbCall.FromCodec?.UserAgent?.Category?.Name ?? string.Empty, + FromComment = dbCall.FromCodec?.User?.Comment ?? string.Empty, + FromExternalReference = dbCall.FromCodec?.User?.ExternalReference ?? string.Empty, + FromLocationName = dbCall.FromCodec?.Location?.Name ?? string.Empty, + FromLocationShortName = dbCall.FromCodec?.Location?.ShortName ?? string.Empty, + FromLocationCategory = dbCall.FromCodec?.Location?.Category?.Name ?? string.Empty, + FromRegionName = dbCall.FromCodec?.Location?.Region?.Name ?? string.Empty, + FromCategory = dbCall.FromCategory, + + ToId = GuidHelper.AsString(dbCall.ToId), ToSip = anonymize ? DisplayNameHelper.AnonymizePhonenumber(dbCall.ToUsername) : dbCall.ToUsername, ToDisplayName = anonymize ? DisplayNameHelper.AnonymizeDisplayName(toDisplayName) : toDisplayName, - ToCodecTypeColor = dbCall.ToSip != null && dbCall.ToSip.User != null && dbCall.ToSip.User.CodecType != null ? dbCall.ToSip.User.CodecType.Color : string.Empty, - ToCodecTypeName = dbCall.ToSip != null && dbCall.ToSip.User != null && dbCall.ToSip.User.CodecType != null ? dbCall.ToSip.User.CodecType.Name : string.Empty, - ToComment = dbCall.ToSip != null && dbCall.ToSip.User != null ? dbCall.ToSip.User.Comment : string.Empty, - ToLocationName = dbCall.ToSip != null && dbCall.ToSip.Location != null ? dbCall.ToSip.Location.Name : string.Empty, - ToLocationShortName = dbCall.ToSip != null && dbCall.ToSip.Location != null ? dbCall.ToSip.Location.ShortName : string.Empty, - ToRegionName = dbCall.ToSip != null && dbCall.ToSip.Location != null && dbCall.ToSip.Location.Region != null ? dbCall.ToSip.Location.Region.Name : string.Empty + ToCodecTypeColor = dbCall.ToCodec?.User?.CodecType?.Color ?? string.Empty, + ToCodecTypeName = dbCall.ToCodec?.User?.CodecType?.Name ?? string.Empty, + ToCodecTypeCategory = dbCall.ToCodec?.UserAgent?.Category?.Name ?? string.Empty, + ToComment = dbCall.ToCodec?.User?.Comment ?? string.Empty, + ToExternalReference = dbCall.ToCodec?.User?.ExternalReference ?? string.Empty, + ToLocationName = dbCall.ToCodec?.Location?.Name ?? string.Empty, + ToLocationShortName = dbCall.ToCodec?.Location?.ShortName ?? string.Empty, + ToLocationCategory = dbCall.ToCodec?.Location?.Category?.Name ?? string.Empty, + ToRegionName = dbCall.ToCodec?.Location?.Region?.Name ?? string.Empty, + ToCategory = dbCall.ToCategory }; return onGoingCall; } - private CallHistory MapToCallHistory(CallEntity call, string sipDomain) + private CallHistory MapToCallHistory(CallEntity call) { - // TODO: Clean up this null checks + string sipDomain = _settingsManager.SipDomain; var callHistory = new CallHistory() { CallId = call.Id, - DlgHashEnt = call.DlgHashEnt, - DlgHashId = call.DlgHashId, + DialogCallId = call.DialogCallId, + DialogHashEnt = call.DialogHashEnt, + DialogHashId = call.DialogHashId, + Started = call.Started, Ended = call.Updated, - FromCodecTypeColor = call.FromSip != null && call.FromSip.User != null && call.FromSip.User.CodecType != null - ? call.FromSip.User.CodecType.Color - : string.Empty, - FromCodecTypeId = call.FromSip != null && call.FromSip.User != null && call.FromSip.User.CodecType != null - ? call.FromSip.User.CodecType.Id - : Guid.Empty, - FromCodecTypeName = call.FromSip != null && call.FromSip.User != null && call.FromSip.User.CodecType != null - ? call.FromSip.User.CodecType.Name - : string.Empty, - FromComment = call.FromSip != null && call.FromSip.User != null ? call.FromSip.User.Comment : string.Empty, - FromDisplayName = CallDisplayNameHelper.GetDisplayName(call.FromSip, call.FromDisplayName, call.FromUsername, sipDomain), + IsPhoneCall = call.IsPhoneCall, + + FromCodecTypeColor = call.FromCodec?.User?.CodecType?.Color ?? string.Empty, + FromCodecTypeId = call.FromCodec?.User?.CodecType?.Id ?? Guid.Empty, + FromCodecTypeName = call.FromCodec?.User?.CodecType?.Name ?? string.Empty, + FromCodecTypeCategory = call.FromCodec?.UserAgent?.Category?.Name, + FromComment = call.FromCodec?.User?.Comment ?? string.Empty, + FromDisplayName = CallDisplayNameHelper.GetDisplayName(call.FromCodec, call.FromDisplayName, call.FromUsername, sipDomain), FromId = call.FromId ?? Guid.Empty, - FromLocationComment = call.FromSip != null && call.FromSip.Location != null ? call.FromSip.Location.Comment : string.Empty, - FromLocationId = call.FromSip != null && call.FromSip.Location != null ? call.FromSip.Location.Id : Guid.Empty, - FromLocationName = call.FromSip != null && call.FromSip.Location != null ? call.FromSip.Location.Name : string.Empty, - FromLocationShortName = call.FromSip != null && call.FromSip.Location != null ? call.FromSip.Location.ShortName : string.Empty, - FromOwnerId = call.FromSip != null && call.FromSip.User != null && call.FromSip.User.Owner != null - ? call.FromSip.User.Owner.Id - : Guid.Empty, - FromOwnerName = call.FromSip != null && call.FromSip.User != null && call.FromSip.User.Owner != null - ? call.FromSip.User.Owner.Name - : string.Empty, - FromRegionId = call.FromSip != null && call.FromSip.Location != null && call.FromSip.Location.Region != null - ? call.FromSip.Location.Region.Id - : Guid.Empty, - FromRegionName = call.FromSip != null && call.FromSip.Location != null && call.FromSip.Location.Region != null - ? call.FromSip.Location.Region.Name - : string.Empty, - FromSip = call.FromSip != null ? call.FromSip.SIP : call.FromUsername, + FromLocationComment = call.FromCodec?.Location?.Comment ?? string.Empty, + FromLocationId = call.FromCodec?.Location?.Id ?? Guid.Empty, + FromLocationName = call.FromCodec?.Location?.Name ?? string.Empty, + FromLocationShortName = call.FromCodec?.Location?.ShortName ?? string.Empty, + FromLocationCategory = call.FromCodec?.Location?.Category?.Name, + FromOwnerId = call.FromCodec?.User?.Owner?.Id ?? Guid.Empty, + FromOwnerName = call.FromCodec?.User?.Owner?.Name ?? string.Empty, + FromRegionId = call.FromCodec?.Location?.Region?.Id ?? Guid.Empty, + FromRegionName = call.FromCodec?.Location?.Region?.Name ?? string.Empty, + FromSip = call.FromCodec?.SIP ?? call.FromUsername, FromTag = call.FromTag, - FromUserAgentHead = call.FromSip != null ? call.FromSip.UserAgentHeader : string.Empty, - FromUsername = call.FromSip != null ? call.FromSip.Username : call.FromUsername, - SipCallId = call.SipCallID, - Started = call.Started, - ToCodecTypeColor = call.ToSip != null && call.ToSip.User != null && call.ToSip.User.CodecType != null - ? call.ToSip.User.CodecType.Color - : string.Empty, - ToCodecTypeId = call.ToSip != null && call.ToSip.User != null && call.ToSip.User.CodecType != null - ? call.ToSip.User.CodecType.Id - : Guid.Empty, - ToCodecTypeName = call.ToSip != null && call.ToSip.User != null && call.ToSip.User.CodecType != null - ? call.ToSip.User.CodecType.Name - : string.Empty, - ToComment = call.ToSip != null && call.ToSip.User != null ? call.ToSip.User.Comment : string.Empty, - ToDisplayName = CallDisplayNameHelper.GetDisplayName(call.ToSip, call.ToDisplayName, call.ToUsername, sipDomain), + FromUserAgentHeader = call.FromCodec?.UserAgentHeader ?? string.Empty, + FromUsername = call.FromCodec?.Username ?? call.FromUsername, + + ToCodecTypeColor = call.ToCodec?.User?.CodecType?.Color ?? string.Empty, + ToCodecTypeId = call.ToCodec?.User?.CodecType?.Id ?? Guid.Empty, + ToCodecTypeName = call.ToCodec?.User?.CodecType?.Name ?? string.Empty, + ToCodecTypeCategory = call.ToCodec?.UserAgent?.Category?.Name, + ToComment = call.ToCodec?.User?.Comment ?? string.Empty, + ToDisplayName = CallDisplayNameHelper.GetDisplayName(call.ToCodec, call.ToDisplayName, call.ToUsername, sipDomain), ToId = call.ToId ?? Guid.Empty, - ToLocationComment = call.ToSip != null && call.ToSip.Location != null ? call.ToSip.Location.Comment : string.Empty, - ToLocationId = call.ToSip != null && call.ToSip.Location != null ? call.ToSip.Location.Id : Guid.Empty, - ToLocationName = call.ToSip != null && call.ToSip.Location != null ? call.ToSip.Location.Name : string.Empty, - ToLocationShortName = call.ToSip != null && call.ToSip.Location != null ? call.ToSip.Location.ShortName : string.Empty, - ToOwnerId = call.ToSip != null && call.ToSip.User != null && call.ToSip.User.Owner != null - ? call.ToSip.User.Owner.Id - : Guid.Empty, - ToOwnerName = call.ToSip != null && call.ToSip.User != null && call.ToSip.User.Owner != null - ? call.ToSip.User.Owner.Name - : string.Empty, - ToRegionId = call.ToSip != null && call.ToSip.Location != null && call.ToSip.Location.Region != null - ? call.ToSip.Location.Region.Id - : Guid.Empty, - ToRegionName = call.ToSip != null && call.ToSip.Location != null && call.ToSip.Location.Region != null - ? call.ToSip.Location.Region.Name - : string.Empty, - ToSip = call.ToSip != null ? call.ToSip.SIP : call.ToUsername, + ToLocationComment = call.ToCodec?.Location?.Comment ?? string.Empty, + ToLocationId = call.ToCodec?.Location?.Id ?? Guid.Empty, + ToLocationName = call.ToCodec?.Location?.Name ?? string.Empty, + ToLocationShortName = call.ToCodec?.Location?.ShortName ?? string.Empty, + ToLocationCategory = call.ToCodec?.Location?.Category?.Name, + ToOwnerId = call.ToCodec?.User?.Owner?.Id ?? Guid.Empty, + ToOwnerName = call.ToCodec?.User?.Owner?.Name ?? string.Empty, + ToRegionId = call.ToCodec?.Location?.Region?.Id ?? Guid.Empty, + ToRegionName = call.ToCodec?.Location?.Region?.Name ?? string.Empty, + ToSip = call.ToCodec?.SIP ?? call.ToUsername, ToTag = call.ToTag, - ToUserAgentHead = call.ToSip != null ? call.ToSip.UserAgentHeader : string.Empty, - ToUsername = call.ToSip != null ? call.ToSip.Username : call.ToUsername, - IsPhoneCall = call.IsPhoneCall + ToUserAgentHeader = call.ToCodec?.UserAgentHeader ?? string.Empty, + ToUsername = call.ToCodec?.Username ?? call.ToUsername }; + + // Determine category + if (call.FromCategory != null && !string.IsNullOrEmpty(call.FromCategory)) + { + callHistory.FromCodecTypeCategory = call.FromCategory; + } + + if (call.ToCategory != null && !string.IsNullOrEmpty(call.ToCategory)) + { + callHistory.ToCodecTypeCategory = call.ToCategory; + } + return callHistory; } - private Call MapCall(CallEntity dbCall) + private Call MapToCall(CallEntity dbCall) { return dbCall == null ? null : new Call { + Id = dbCall.Id, FromId = dbCall.FromId ?? Guid.Empty, ToId = dbCall.ToId ?? Guid.Empty, Started = dbCall.Started, State = dbCall.State ?? SipCallState.NONE, Updated = dbCall.Updated, - Id = dbCall.Id, - CallId = dbCall.SipCallID, + CallId = dbCall.DialogCallId, Closed = dbCall.Closed, - From = MapRegisteredSip(dbCall.FromSip), - To = MapRegisteredSip(dbCall.ToSip), + DialogHashId = dbCall.DialogHashId, + DialogHashEnt = dbCall.DialogHashEnt, + From = MapToRegisteredCodec(dbCall.FromCodec), + To = MapToRegisteredCodec(dbCall.ToCodec), FromSip = dbCall.FromUsername, ToSip = dbCall.ToUsername, FromTag = dbCall.FromTag, ToTag = dbCall.ToTag, - DlgHashId = dbCall.DlgHashId, - DlgHashEnt = dbCall.DlgHashEnt, - IsPhoneCall = dbCall.IsPhoneCall + FromCategory = dbCall.FromCategory, + ToCategory = dbCall.ToCategory, + IsPhoneCall = dbCall.IsPhoneCall, + SDP = dbCall.SDP }; } - private RegisteredSip MapRegisteredSip(RegisteredSipEntity dbSip) + private CallRegisteredCodec MapToRegisteredCodec(RegisteredCodecEntity dbCodec) { - var sip = dbSip == null ? null : new RegisteredSip() + var sip = dbCodec == null ? null : new CallRegisteredCodec() { - Id = dbSip.Id, - SIP = dbSip.SIP, - DisplayName = dbSip.DisplayName, - UserAgentHead = dbSip.UserAgentHeader, - Username = dbSip.Username, - User = MapUser(dbSip.User), + Id = dbCodec.Id, + SIP = dbCodec.SIP, + DisplayName = dbCodec.DisplayName, + UserAgentHead = dbCodec.UserAgentHeader, + UserName = dbCodec.Username, + PresentationName = DisplayNameHelper.GetDisplayName( + dbCodec?.DisplayName ?? string.Empty, + dbCodec?.User?.DisplayName ?? string.Empty, + string.Empty, + dbCodec?.Username ?? string.Empty, + dbCodec?.SIP ?? string.Empty, + string.Empty, + _settingsManager.SipDomain), + User = MapToSipAccount(dbCodec.User), }; return sip; } - private SipAccount MapUser(SipAccountEntity dbAccount) + private CallRegisteredCodecSipAccount MapToSipAccount(SipAccountEntity dbAccount) { - return dbAccount == null ? null : new SipAccount() + return dbAccount == null ? null : new CallRegisteredCodecSipAccount() { Id = dbAccount.Id, UserName = dbAccount.UserName, - DisplayName = dbAccount.DisplayName, + DisplayName = dbAccount.DisplayName }; } } diff --git a/CCM.Data/Repositories/CategoryRepository.cs b/CCM.Data/Repositories/CategoryRepository.cs new file mode 100644 index 00000000..8907c999 --- /dev/null +++ b/CCM.Data/Repositories/CategoryRepository.cs @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using CCM.Core.Entities; +using CCM.Core.Interfaces.Repositories; +using CCM.Data.Entities; +using LazyCache; +using Microsoft.EntityFrameworkCore; + +namespace CCM.Data.Repositories +{ + public class CategoryRepository : BaseRepository, ICategoryRepository + { + public CategoryRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) + { + } + + public void Save(Category category) + { + var db = _ccmDbContext; + CategoryEntity dbCategory = null; + var timeStamp = DateTime.UtcNow; + + if (category.Id != Guid.Empty) + { + dbCategory = db.Categories + .Include(r => r.Locations) + .Include(r => r.UserAgents) + .SingleOrDefault(g => g.Id == category.Id); + + if (dbCategory == null) + { + throw new Exception("Category could not be found"); + } + + dbCategory.Locations?.Clear(); + + dbCategory.UserAgents?.Clear(); + } + else + { + dbCategory = new CategoryEntity + { + Id = Guid.NewGuid(), + CreatedBy = category.CreatedBy, + CreatedOn = timeStamp, + Locations = new Collection() + }; + + category.Id = dbCategory.Id; + category.CreatedOn = dbCategory.CreatedOn; + db.Categories.Add(dbCategory); + } + + dbCategory.Name = category.Name; + dbCategory.Description = category.Description; + dbCategory.UpdatedBy = category.UpdatedBy; + dbCategory.UpdatedOn = timeStamp; + + // Add relations + foreach (var location in category.Locations) + { + var dbLocation = db.Locations.SingleOrDefault(l => l.Id == location.Id); + if (dbLocation != null) + { + dbCategory.Locations?.Add(dbLocation); + } + } + + foreach (var useragents in category.UserAgents) + { + var dbUserAgent = db.UserAgents.SingleOrDefault(l => l.Id == useragents.Id); + if (dbUserAgent != null) + { + dbCategory.UserAgents?.Add(dbUserAgent); + } + } + + db.SaveChanges(); + } + + public void Delete(Guid id) + { + var db = _ccmDbContext; + CategoryEntity category = db.Categories.SingleOrDefault(o => o.Id == id); + if (category != null) + { + db.Categories.Remove(category); + db.SaveChanges(); + } + } + + public List GetAll() + { + var dbCategory = _ccmDbContext.Categories + .Include(c => c.Locations) + .Include(c => c.UserAgents).ToList(); + return dbCategory + .Select(category => MapToCategory(category)).OrderBy(o => o.Name).ToList(); + } + + public Category GetById(Guid id) + { + var category = _ccmDbContext.Categories + .Include(c => c.Locations) + .Include(c => c.UserAgents) + .SingleOrDefault(o => o.Id == id); + return category == null ? null : MapToCategory(category); + } + + public List FindCategories(string search) + { + var db = _ccmDbContext; + var dbCategory = db.Categories + .Include(c => c.Locations) + .Include(c => c.UserAgents) + .Where(o => o.Name.ToLower().Contains(search.ToLower())).ToList(); + return dbCategory.Select(category => MapToCategory(category)).OrderBy(o => o.Name).ToList(); + } + + private Category MapToCategory(CategoryEntity dbCategory, bool includeLocations = true, bool includeUserAgents = true) + { + return dbCategory == null ? null : new Category { + Id = dbCategory.Id, + Name = dbCategory.Name, + Description = dbCategory.Description, + Locations = includeLocations ? dbCategory.Locations.Select(MapToLocation).ToList() : new List(), + UserAgents = includeUserAgents ? dbCategory.UserAgents.Select(MapToUserAgent).ToList() : new List(), + CreatedBy = dbCategory.CreatedBy, + CreatedOn = dbCategory.CreatedOn, + UpdatedBy = dbCategory.UpdatedBy, + UpdatedOn = dbCategory.UpdatedOn, + }; + } + + private Location MapToLocation(LocationEntity dbLocation) + { + if (dbLocation == null) return null; + + return new Location + { + Id = dbLocation.Id, + Name = dbLocation.Name, + Comment = dbLocation.Comment, + CarrierConnectionId = dbLocation.CarrierConnectionId, + CreatedBy = dbLocation.CreatedBy, + CreatedOn = dbLocation.CreatedOn, + UpdatedBy = dbLocation.UpdatedBy, + UpdatedOn = dbLocation.UpdatedOn, + }; + } + + private UserAgent MapToUserAgent(UserAgentEntity dbUserAgent) + { + if (dbUserAgent == null) return null; + + return new UserAgent + { + Id = dbUserAgent.Id, + Name = dbUserAgent.Name, + Comment = dbUserAgent.Comment, + Identifier = dbUserAgent.Identifier, + CreatedBy = dbUserAgent.CreatedBy, + CreatedOn = dbUserAgent.CreatedOn, + UpdatedBy = dbUserAgent.UpdatedBy, + UpdatedOn = dbUserAgent.UpdatedOn, + }; + } + } +} diff --git a/CCM.Data/Repositories/CcmUserRepository.cs b/CCM.Data/Repositories/CcmUserRepository.cs index c9bcfd1f..4ecf41c2 100644 --- a/CCM.Data/Repositories/CcmUserRepository.cs +++ b/CCM.Data/Repositories/CcmUserRepository.cs @@ -26,7 +26,7 @@ using System; using System.Collections.Generic; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; using System.Threading.Tasks; using CCM.Core.Entities; @@ -41,146 +41,112 @@ namespace CCM.Data.Repositories public class CcmUserRepository : BaseRepository, ICcmUserRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); + private readonly IRoleRepository _roleRepository; - public CcmUserRepository(IAppCache cache) : base(cache) + public CcmUserRepository( + IAppCache cache, + CcmDbContext ccmDbContext, + IRoleRepository roleRepository) + : base(cache, ccmDbContext) { + _roleRepository = roleRepository; } public bool Create(CcmUser ccmUser) { - using (var db = GetDbContext()) - { - var dbUser = new UserEntity(); - MapUserEntity(db, ccmUser, dbUser); + var dbUser = new UserEntity(); + dbUser = MapToUserEntity(ccmUser, dbUser); - db.Users.Add(dbUser); - var result = db.SaveChanges(); - ccmUser.Id = dbUser.Id; - return result >= 1; - } + _ccmDbContext.Users.Add(dbUser); + var success = _ccmDbContext.SaveChanges(); + ccmUser.Id = dbUser.Id; + return success >= 1; } public bool Update(CcmUser ccmUser) { - using (var db = GetDbContext()) + UserEntity dbUser = _ccmDbContext.Users.SingleOrDefault(u => u.Id == ccmUser.Id); + if (dbUser == null) { - var dbUser = db.Users.SingleOrDefault(u => u.Id == ccmUser.Id); - if (dbUser == null) - { - return false; - } + return false; + } - MapUserEntity(db, ccmUser, dbUser); + dbUser = MapToUserEntity(ccmUser, dbUser); - var result = db.SaveChanges(); - return result == 1; - } + return _ccmDbContext.SaveChanges() == 1; } public void UpdatePassword(Guid id, string passwordHash, string salt) { - using (var db = GetDbContext()) + UserEntity dbUser = _ccmDbContext.Users.SingleOrDefault(u => u.Id == id); + if (dbUser != null) { - UserEntity dbUser = db.Users.SingleOrDefault(u => u.Id == id); - - if (dbUser != null) - { - dbUser.PasswordHash = passwordHash; - dbUser.Salt = salt; - db.SaveChanges(); - } + dbUser.PasswordHash = passwordHash; + dbUser.Salt = salt; + _ccmDbContext.SaveChanges(); } } public bool Delete(Guid userId) { - using (var db = GetDbContext()) + UserEntity user = _ccmDbContext.Users.SingleOrDefault(u => u.Id == userId); + if (user == null) { - UserEntity user = db.Users.SingleOrDefault(u => u.Id == userId); + return false; + } - if (user == null) - { - return false; - } + _ccmDbContext.Users.Remove(user); - db.Users.Remove(user); - var result = db.SaveChanges(); - return result == 1; - } + return _ccmDbContext.SaveChanges() == 1; } public CcmUser GetById(Guid userId) { - using (var db = GetDbContext()) - { - UserEntity user = db.Users.SingleOrDefault(u => u.Id == userId); - return MapToCcmUser(user); - } + UserEntity user = _ccmDbContext.Users + .Include(u => u.Role) + .SingleOrDefault(u => u.Id == userId); + return MapToCcmUser(user); } public List GetAll() { - using (var db = GetDbContext()) - { - var users = db.Users - .Include(u => u.Role) - .ToList(); - - return users.Select(MapToCcmUser).OrderBy(u => u.UserName).ToList(); - } + var users = _ccmDbContext.Users + .Include(u => u.Role) + .ToList(); + return users.Select(MapToCcmUser).OrderBy(u => u.UserName).ToList(); } public List FindUsers(string startsWith) { - using (var db = GetDbContext()) - { - var users = db.Users - .Where(u => u.UserName.Contains(startsWith)) - .ToList(); - return users.Select(MapToCcmUser).OrderBy(u => u.UserName).ToList(); - } + var users = _ccmDbContext.Users + .Where(u => u.UserName.Contains(startsWith)) + .ToList(); + return users.Select(MapToCcmUser).OrderBy(u => u.UserName).ToList(); } public CcmUser GetByUserName(string userName) { - using (var db = GetDbContext()) - { - UserEntity user = db.Users.SingleOrDefault(u => u.UserName == userName); - return MapToCcmUser(user); - } + UserEntity user = _ccmDbContext.Users.Include(usr => usr.Role).SingleOrDefault(u => u.UserName == userName); + return MapToCcmUser(user); } public async Task AuthenticateAsync(string username, string password) { - using (var db = GetDbContext()) + var user = await _ccmDbContext.Users.FirstOrDefaultAsync(u => u.UserName == username); + if (user == null) { - var user = await db.Users.FirstOrDefaultAsync(u => u.UserName == username); - if (user == null) - { - return false; - } - - string hash = CryptoHelper.Md5HashSaltedPassword(password, user.Salt); - var success = (hash == user.PasswordHash); - - if (!success) - { - log.Info("Authentication failed for user {0}", username); - } - - return success; - + return false; } - } - public CcmRole GetUserRole(CcmUser ccmUser) - { - using (var db = GetDbContext()) - { - var user = db.Users.SingleOrDefault(u => u.Id == ccmUser.Id); + string hash = CryptoHelper.Md5HashSaltedPassword(password, user.Salt); + var success = (hash == user.PasswordHash); - return user?.Role == null ? null : new CcmRole { Id = user.Role.Id, Name = user.Role.Name }; + if (!success) + { + log.Info("Authentication failed for user {0}", username); } + + return success; } private static CcmUser MapToCcmUser(UserEntity dbUser) @@ -197,27 +163,24 @@ private static CcmUser MapToCcmUser(UserEntity dbUser) }; } - private void MapUserEntity(CcmDbContext cxt, CcmUser ccmUser, UserEntity dbUser) + private UserEntity MapToUserEntity(CcmUser ccmUser, UserEntity dbUser) { dbUser.UserName = ccmUser.UserName; dbUser.FirstName = ccmUser.FirstName; dbUser.LastName = ccmUser.LastName; dbUser.Comment = ccmUser.Comment; - var role = string.IsNullOrWhiteSpace(ccmUser.RoleId) ? null : cxt.Roles.SingleOrDefault(r => r.Id == new Guid(ccmUser.RoleId)); - // Only admins allowed to assign admin role to account - if (CurrentUserIsAdmin() || role == null || role.Name != Roles.Admin) - { - dbUser.Role = role; - } - + dbUser.Role = string.IsNullOrWhiteSpace(ccmUser.RoleId) ? null : _ccmDbContext.Roles.SingleOrDefault(r => r.Id == new Guid(ccmUser.RoleId)); + if (!string.IsNullOrEmpty(ccmUser.Password)) { var saltBytes = CryptoHelper.GenerateSaltBytes(); dbUser.PasswordHash = CryptoHelper.Md5HashSaltedPassword(ccmUser.Password, saltBytes); dbUser.Salt = Convert.ToBase64String(saltBytes); } + + return dbUser; } } } diff --git a/CCM.Data/Repositories/CityRepository.cs b/CCM.Data/Repositories/CityRepository.cs index 5ffb598b..c5bbc6f7 100644 --- a/CCM.Data/Repositories/CityRepository.cs +++ b/CCM.Data/Repositories/CityRepository.cs @@ -32,6 +32,7 @@ using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; +using Microsoft.EntityFrameworkCore; using NLog; namespace CCM.Data.Repositories @@ -40,59 +41,58 @@ public class CityRepository : BaseRepository, ICityRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public CityRepository(IAppCache cache) : base(cache) + public CityRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public override void Save(City city) { - using (var db = GetDbContext()) - { - CityEntity dbCity; + CityEntity dbCity; - if (city.Id != Guid.Empty) - { - dbCity = db.Cities.SingleOrDefault(g => g.Id == city.Id); - if (dbCity == null) - { - throw new Exception("Region could not be found"); - } + if (city.Id != Guid.Empty) + { + dbCity = _ccmDbContext.Cities + .Include(c => c.Locations) + .SingleOrDefault(g => g.Id == city.Id); - dbCity.Locations.Clear(); - } - else + if (dbCity == null) { - dbCity = new CityEntity {Locations = new Collection()}; - db.Cities.Add(dbCity); + throw new Exception("City could not be found"); } - dbCity.Name = city.Name; + dbCity.Locations?.Clear(); + } + else + { + dbCity = new CityEntity { Locations = new Collection() }; + _ccmDbContext.Cities.Add(dbCity); + } + + dbCity.Name = city.Name; - foreach (var location in city.Locations) + foreach (var location in city.Locations) + { + var dbLocation = _ccmDbContext.Locations.SingleOrDefault(l => l.Id == location.Id); + if (dbLocation != null) { - var dbLocation = db.Locations.SingleOrDefault(l => l.Id == location.Id); - if (dbLocation != null) - { - dbCity.Locations.Add(dbLocation); - } + dbCity.Locations?.Add(dbLocation); } - - db.SaveChanges(); - city.Id = dbCity.Id; } + + _ccmDbContext.SaveChanges(); + city.Id = dbCity.Id; } public override void Delete(Guid id) { - using (var db = GetDbContext()) + var dbCity = _ccmDbContext.Cities + .Include(c => c.Locations) + .SingleOrDefault(g => g.Id == id); + if (dbCity != null) { - var dbCity = db.Cities.SingleOrDefault(g => g.Id == id); - if (dbCity != null) - { - dbCity.Locations.Clear(); - db.Cities.Remove(dbCity); - db.SaveChanges(); - } + dbCity.Locations?.Clear(); + _ccmDbContext.Cities.Remove(dbCity); + _ccmDbContext.SaveChanges(); } } @@ -118,15 +118,17 @@ public List Find(string search) public override City MapToCoreObject(CityEntity dbCity) { - return dbCity != null ? new City { - Id = dbCity.Id, - Name = dbCity.Name, - Locations = dbCity.Locations.Select(MapToLocation).ToList(), - } + // TODO: is this one needed? feels like no other is using this + return dbCity != null ? new City + { + Id = dbCity.Id, + Name = dbCity.Name, + Locations = dbCity.Locations.Select(MapToLocation).ToList(), + } : null; } - public Location MapToLocation(LocationEntity dbLocation) + private Location MapToLocation(LocationEntity dbLocation) { if (dbLocation == null) return null; diff --git a/CCM.Data/Repositories/CodecPresetRepository.cs b/CCM.Data/Repositories/CodecPresetRepository.cs deleted file mode 100644 index 32374fc4..00000000 --- a/CCM.Data/Repositories/CodecPresetRepository.cs +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using CCM.Core.Entities; -using CCM.Core.Interfaces.Repositories; -using CCM.Data.Entities; -using LazyCache; - -namespace CCM.Data.Repositories -{ - public class CodecPresetRepository : BaseRepository, ICodecPresetRepository - { - public CodecPresetRepository(IAppCache cache) : base(cache) - { - } - - public List GetAll() - { - using (var db = GetDbContext()) - { - var dbCodecPresets = db.CodecPresets.ToList(); - return dbCodecPresets.Select(MapToCodecPreset).ToList(); - } - } - - public void Save(CodecPreset codecPreset) - { - using (var db = GetDbContext()) - { - CodecPresetEntity dbCodecPreset = null; - - if (codecPreset.Id != Guid.Empty) - { - dbCodecPreset = db.CodecPresets.SingleOrDefault(c => c.Id == codecPreset.Id); - } - - if (dbCodecPreset == null) - { - dbCodecPreset = new CodecPresetEntity - { - Id = Guid.NewGuid(), - CreatedBy = codecPreset.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - codecPreset.Id = dbCodecPreset.Id; - codecPreset.CreatedOn = dbCodecPreset.CreatedOn; - db.CodecPresets.Add(dbCodecPreset); - } - - dbCodecPreset.Name = codecPreset.Name; - dbCodecPreset.UpdatedBy = codecPreset.UpdatedBy; - dbCodecPreset.UpdatedOn = DateTime.UtcNow; - codecPreset.UpdatedOn = dbCodecPreset.UpdatedOn; - - db.SaveChanges(); - } - } - - public void Delete(Guid id) - { - using (var db = GetDbContext()) - { - var dbCodecPreset = db.CodecPresets.SingleOrDefault(c => c.Id == id); - - if (dbCodecPreset == null) - { - return; - } - - db.CodecPresets.Remove(dbCodecPreset); - db.SaveChanges(); - } - } - - public CodecPreset GetById(Guid id) - { - if (id == Guid.Empty) - return null; - - using (var db = GetDbContext()) - { - var dbCodecPreset = db.CodecPresets.SingleOrDefault(c => c.Id == id); - return MapToCodecPreset(dbCodecPreset); - } - } - - public List Find(string search) - { - using (var db = GetDbContext()) - { - var dbCodecPresets = db.CodecPresets - .Where(c => c.Name.ToLower().Contains(search.ToLower())) - .ToList(); - return dbCodecPresets.Select(MapToCodecPreset).OrderBy(c => c.Name).ToList(); - } - } - - private CodecPreset MapToCodecPreset(CodecPresetEntity dbPreset) - { - return dbPreset == null ? null - : new CodecPreset - { - Id = dbPreset.Id, - Name = dbPreset.Name, - CreatedBy = dbPreset.CreatedBy, - CreatedOn = dbPreset.CreatedOn, - UpdatedBy = dbPreset.UpdatedBy, - UpdatedOn = dbPreset.UpdatedOn - }; - } - } -} diff --git a/CCM.Data/Repositories/CodecTypeRepository.cs b/CCM.Data/Repositories/CodecTypeRepository.cs index e48cc5e9..d5a077fc 100644 --- a/CCM.Data/Repositories/CodecTypeRepository.cs +++ b/CCM.Data/Repositories/CodecTypeRepository.cs @@ -27,14 +27,12 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; using NLog; -using CodecType = CCM.Core.Entities.CodecType; -using Owner = CCM.Core.Entities.Owner; namespace CCM.Data.Repositories { @@ -42,53 +40,61 @@ public class CodecTypeRepository : BaseRepository, ICodecTypeRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public CodecTypeRepository(IAppCache cache) : base(cache) + public CodecTypeRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public void Save(CodecType codecType) { - using (var db = GetDbContext()) - { - CodecTypeEntity dbCodecType = null; + var db = _ccmDbContext; + CodecTypeEntity dbCodecType = null; - if (codecType.Id != Guid.Empty) + if (codecType.Id != Guid.Empty) + { + dbCodecType = db.CodecTypes + .Include(c => c.SipAccounts) + .SingleOrDefault(c => c.Id == codecType.Id); + if(dbCodecType == null) { - dbCodecType = db.CodecTypes.SingleOrDefault(c => c.Id == codecType.Id); + throw new Exception("Codec type could not be found"); } + } - if (dbCodecType == null) + if (dbCodecType == null) + { + dbCodecType = new CodecTypeEntity() { - dbCodecType = new CodecTypeEntity() - { - Id = Guid.NewGuid(), - CreatedBy = codecType.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - db.CodecTypes.Add(dbCodecType); - } + Id = Guid.NewGuid(), + CreatedBy = codecType.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + db.CodecTypes.Add(dbCodecType); + } - dbCodecType.Name = codecType.Name; - dbCodecType.Color = codecType.Color; - dbCodecType.UpdatedBy = codecType.UpdatedBy; - dbCodecType.UpdatedOn = DateTime.UtcNow; + dbCodecType.Name = codecType.Name; + dbCodecType.Color = codecType.Color; + dbCodecType.UpdatedBy = codecType.UpdatedBy; + dbCodecType.UpdatedOn = DateTime.UtcNow; - db.SaveChanges(); - } + db.SaveChanges(); } public void Delete(Guid codecTypeId) { - using (var db = GetDbContext()) - { - var dbCodecType = db.CodecTypes.SingleOrDefault(c => c.Id == codecTypeId); + var db = _ccmDbContext; + var dbCodecType = db.CodecTypes + .Include(ct => ct.SipAccounts) + .SingleOrDefault(c => c.Id == codecTypeId); - if (dbCodecType != null) + if (dbCodecType != null) + { + if (dbCodecType.SipAccounts != null) { - dbCodecType.Users.Clear(); - db.CodecTypes.Remove(dbCodecType); - db.SaveChanges(); + dbCodecType.SipAccounts.Clear(); } + + db.CodecTypes.Remove(dbCodecType); + db.SaveChanges(); } } @@ -99,21 +105,19 @@ public CodecType GetById(Guid codecTypeId) return null; } - using (var db = GetDbContext()) - { - var dbCodecType = db.CodecTypes - .Include(ct => ct.Users) - .SingleOrDefault(c => c.Id == codecTypeId); + var db = _ccmDbContext; + var dbCodecType = db.CodecTypes + .Include(ct => ct.SipAccounts) + .SingleOrDefault(c => c.Id == codecTypeId); - if (dbCodecType == null) - { - return null; - } + if (dbCodecType == null) + { + return null; + } - var codecType = MapToCodecType(dbCodecType); + var codecType = MapToCodecType(dbCodecType); - return codecType; - } + return codecType; } public List GetAll() @@ -123,36 +127,39 @@ public List GetAll() public List GetAll(bool includeUsers) { - using (var db = GetDbContext()) + if (includeUsers) { - var dbCodecTypes = db.CodecTypes - .Include(ct => ct.Users) - .Include(ct => ct.Users.Select(u => u.Owner)) - .ToList(); - - return dbCodecTypes - .Select(dbCodecType => MapToCodecType(dbCodecType, includeUsers)) + return _ccmDbContext.CodecTypes + .Include(it => it.SipAccounts) + .ThenInclude(acc => acc.Owner) + .AsEnumerable() + .Select(dbCodecType => MapToCodecType(dbCodecType, true)) .OrderBy(c => c.Name) .ToList(); + } + + return _ccmDbContext.CodecTypes? + .AsEnumerable() + .Select(dbCodecType => MapToCodecType(dbCodecType, false)) + .OrderBy(c => c.Name) + .ToList(); } public List Find(string search, bool includeUsers = true) { - using (var db = GetDbContext()) - { - var dbCodecTypes = db.CodecTypes - .Include(ct => ct.Users) - .Where(c => c.Name.ToLower().Contains(search.ToLower())).OrderBy(c => c.Name) - .ToList(); - - return dbCodecTypes - .Select(dbCodecType => MapToCodecType(dbCodecType, includeUsers)) - .ToList(); - } + var db = _ccmDbContext; + var dbCodecTypes = db.CodecTypes + .Include(ct => ct.SipAccounts) + .Where(c => c.Name.ToLower().Contains(search.ToLower())).OrderBy(c => c.Name) + .ToList(); + + return dbCodecTypes + .Select(dbCodecType => MapToCodecType(dbCodecType, includeUsers)) + .ToList(); } - private CodecType MapToCodecType(CodecTypeEntity dbCodecType, bool includeUsers = true) + private static CodecType MapToCodecType(CodecTypeEntity dbCodecType, bool includeUsers = true) { var codecType = new CodecType() { @@ -167,13 +174,13 @@ private CodecType MapToCodecType(CodecTypeEntity dbCodecType, bool includeUsers if (includeUsers) { - codecType.Users = dbCodecType.Users.Select(u => MapEntityToSipAccont(codecType, u)).ToList(); + codecType.Users = dbCodecType.SipAccounts.Select(u => MapEntityToSipAccount(codecType, u)).ToList(); } return codecType; } - private SipAccount MapEntityToSipAccont(CodecType codecType, SipAccountEntity user) + private static SipAccount MapEntityToSipAccount(CodecType codecType, SipAccountEntity user) { return new SipAccount { diff --git a/CCM.Data/Repositories/DocumentDb/BaseDocumentRepository.cs b/CCM.Data/Repositories/DocumentDb/BaseDocumentRepository.cs deleted file mode 100644 index bfb1d0c0..00000000 --- a/CCM.Data/Repositories/DocumentDb/BaseDocumentRepository.cs +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data.Entity.Migrations; -using System.Linq; -using CCM.Core.Entities.DocumentDb; -using CCM.Data.Entities.DocumentDb; -using LazyCache; -using Newtonsoft.Json; - -namespace CCM.Data.Repositories.DocumentDb -{ - public abstract class BaseDocumentRepository : BaseDocumentRepository where T : DocumentDbObjectBase where TU : DocumentDbEntity, new() - { - protected BaseDocumentRepository(IAppCache cache) : base(cache) - { - } - - public List GetAll() - { - using (var ctx = GetDbContext()) - { - IQueryable> data = ctx.Set().GroupBy(r => r.ContentId); - - var list = new List(); - foreach (IGrouping grouping in data) - { - var r = grouping.OrderByDescending(re => re.UpdatedDateTime).FirstOrDefault(); - list.Add(r); - } - - return list.Select(MapRowToObject).Where(r => r != null).ToList(); - } - } - - public T GetById(int id) - { - using (var ctx = GetDbContext()) - { - var data = ctx.Set().OrderByDescending(r => r.UpdatedDateTime).FirstOrDefault(r => r.ContentId == id); - var region = MapRowToObject(data); - return region; - } - } - - public T Save(T o) - { - using (var ctx = GetDbContext()) - { - if (o == null) - { - return null; - } - - if (o.Id == 0) - { - // New item - var dbSet = ctx.Set(); - int? max = dbSet.Max(r => (int?)r.ContentId); - var nextId = (max ?? 0) + 1; - o.Id = nextId; - } - - // TODO: Get user - //PrincipalContext principalContext = new PrincipalContext(ContextType.Domain); - //UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, Thread.CurrentPrincipal.Identity.Name); - var userPrincipal = "Unknown"; - var json = JsonConvert.SerializeObject(o); - var row = new TU() - { - ContentId = o.Id, - JsonData = json, - UpdatedDateTime = DateTime.UtcNow, - UpdatedByUser = userPrincipal - }; - ctx.Set().Add(row); - ctx.SaveChanges(); - - return o; - } - } - - public bool Delete(int id) - { - using (var ctx = GetDbContext()) - { - var regions = ctx.Set().Where(r => r.ContentId == id); - ctx.Set().RemoveRange(regions); - int result = ctx.SaveChanges(); - return result > 0; - } - } - - public bool DeleteRow(int id) - { - using (var ctx = GetDbContext()) - { - int result = 0; - var config = ctx.Set().FirstOrDefault(c => c.Id == id); - if (config != null) - { - ctx.Set().Remove(config); - result = ctx.SaveChanges(); - } - return result > 0; - } - } - - public bool UpdateDate(int id) - { - using (var ctx = GetDbContext()) - { - int result = 0; - var config = ctx.Set().FirstOrDefault(r => r.Id == id); - if (config != null) - { - //PrincipalContext principalContext = new PrincipalContext(ContextType.Domain); - //UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, Thread.CurrentPrincipal.Identity.Name); - var userPrincipal = "Unknown"; - - config.UpdatedDateTime = DateTime.UtcNow; // Stter aktuellt datum vilket gr att den konfigurationen anvnds nu - config.UpdatedByUser = userPrincipal; - - ctx.Set().AddOrUpdate(config); - result = ctx.SaveChanges(); - } - - return result > 0; - } - } - - private T MapRowToObject(TU data) - { - if (data == null) - { - return default(T); - } - - var o = JsonConvert.DeserializeObject(data.JsonData); - if (o != null) - { - o.Id = data.ContentId; - o.UpdatedDateTime = data.UpdatedDateTime; - o.UpdatedByUser = data.UpdatedByUser; - } - return o; - } - } - - public abstract class BaseDocumentRepository - { - private readonly IAppCache _cache; - - protected BaseDocumentRepository(IAppCache cache) - { - _cache = cache; - } - - protected CcmDbContext GetDbContext() - { - return new CcmDbContext(_cache); - } - } -} diff --git a/CCM.Data/Repositories/FilterRepository.cs b/CCM.Data/Repositories/FilterRepository.cs index 538dd9a0..33071b12 100644 --- a/CCM.Data/Repositories/FilterRepository.cs +++ b/CCM.Data/Repositories/FilterRepository.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; @@ -36,18 +37,45 @@ namespace CCM.Data.Repositories { public class FilterRepository : BaseRepository, IFilterRepository { - public FilterRepository(IAppCache cache) : base(cache) + public FilterRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public List GetFilterPropertyValues(string tableName, string columnName) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + // TODO: Redo this one, so it supports later Entity framework queries. And for .NET core + // TODO: redone, but could probably be niear looking... + var sql = string.Format("SELECT {0} FROM {1}", columnName, tableName); + //var filterValues = db.Database.SqlQuery(sql).Where(s => s != null).ToList(); + + if (tableName == "UserAgents") + { + var ty = typeof(UserAgentEntity).GetProperty(columnName); + return db.UserAgents.Where(ua => ua != null).Select(ua => (string)ty.GetValue(ua)).Distinct().ToList(); + } + else if(tableName == "Locations") + { + var ty = typeof(LocationEntity).GetProperty(columnName); + return db.Locations.Where(lo => lo != null).Select(lo => (string)ty.GetValue(lo)).Distinct().ToList(); + } + else if(tableName == "Regions") + { + var ty = typeof(RegionEntity).GetProperty(columnName); + return db.Regions.Where(r => r != null).Select(re => (string)ty.GetValue(re)).Distinct().ToList(); + } + else if(tableName == "Cities") + { + var ty = typeof(CityEntity).GetProperty(columnName); + return db.Cities.Where(c => c != null).Select(c => (string)ty.GetValue(c)).Distinct().ToList(); + } + else if(tableName == "CodecTypes") { - // TODO: Redo this one, so it supports later Entity framework queries. And for .NET core - var sql = string.Format("SELECT {0} FROM {1}", columnName, tableName); - var filterValues = db.Database.SqlQuery(sql).Where(s => s != null).ToList(); - return filterValues; + var ty = typeof(CodecTypeEntity).GetProperty(columnName); + return db.CodecTypes.Where(ct => ct != null).Select(ct => (string)ty.GetValue(ct)).Distinct().ToList(); + } + else { + return new List(); } } @@ -59,10 +87,7 @@ public List GetFilterPropertyValues(string tableName, string columnName) /// public bool CheckFilterNameAvailability(string name, Guid id) { - using (var db = GetDbContext()) - { - return !db.Filters.Any(f => f.Name == name && f.Id != id); - } + return !_ccmDbContext.Filters.Any(f => f.Name == name && f.Id != id); } /// @@ -71,76 +96,64 @@ public bool CheckFilterNameAvailability(string name, Guid id) /// The filter. public void Save(Filter filter) { - using (var db = GetDbContext()) - { - FilterEntity dbFilter = null; + var db = _ccmDbContext; + FilterEntity dbFilter = null; - if (filter.Id != Guid.Empty) - { - dbFilter = db.Filters.SingleOrDefault(f => f.Id == filter.Id); - } + if (filter.Id != Guid.Empty) + { + dbFilter = db.Filters.SingleOrDefault(f => f.Id == filter.Id); + } - if (dbFilter == null) + if (dbFilter == null) + { + dbFilter = new FilterEntity { - dbFilter = new FilterEntity - { - Id = Guid.NewGuid(), - CreatedBy = filter.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - filter.Id = dbFilter.Id; - filter.CreatedOn = dbFilter.CreatedOn; - db.Filters.Add(dbFilter); - } - - - dbFilter.FilteringName = filter.FilteringName; - dbFilter.Name = filter.Name; - dbFilter.PropertyName = filter.ColumnName; - dbFilter.Type = filter.TableName; - dbFilter.UpdatedBy = filter.UpdatedBy; - dbFilter.UpdatedOn = DateTime.UtcNow; - filter.UpdatedOn = dbFilter.UpdatedOn; - - db.SaveChanges(); - + Id = Guid.NewGuid(), + CreatedBy = filter.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + filter.Id = dbFilter.Id; filter.CreatedOn = dbFilter.CreatedOn; - filter.UpdatedOn = dbFilter.UpdatedOn; + db.Filters.Add(dbFilter); } + + dbFilter.FilteringName = filter.FilteringName; + dbFilter.Name = filter.Name; + dbFilter.PropertyName = filter.ColumnName; + dbFilter.Type = filter.TableName; + dbFilter.UpdatedBy = filter.UpdatedBy; + dbFilter.UpdatedOn = DateTime.UtcNow; + + filter.CreatedOn = dbFilter.CreatedOn; + filter.UpdatedOn = dbFilter.UpdatedOn; + + db.SaveChanges(); } public List GetAll() { - using (var db = GetDbContext()) - { - var dbFilters = db.Filters.ToList(); - return dbFilters.Select(MapToFilter).OrderBy(f => f.Name).ToList(); - } + var dbFilters = _ccmDbContext.Filters.ToList(); + return dbFilters.Select(MapToFilter).OrderBy(f => f.Name).ToList(); } public Filter GetById(Guid id) { - using (var db = GetDbContext()) - { - var dbFilter = db.Filters.SingleOrDefault(f => f.Id == id); - return dbFilter != null ? MapToFilter(dbFilter) : null; - } + var dbFilter = _ccmDbContext.Filters.SingleOrDefault(f => f.Id == id); + return dbFilter != null ? MapToFilter(dbFilter) : null; } public void Delete(Guid id) { - using (var db = GetDbContext()) - { - var dbFilter = db.Filters.SingleOrDefault(f => f.Id == id); - - if (dbFilter == null) - { - return; - } + var db = _ccmDbContext; + var dbFilter = db.Filters.SingleOrDefault(f => f.Id == id); - db.Filters.Remove(dbFilter); - db.SaveChanges(); + if (dbFilter == null) + { + return; } + + db.Filters.Remove(dbFilter); + db.SaveChanges(); } /// @@ -150,15 +163,12 @@ public void Delete(Guid id) /// public List Find(string search) { - using (var db = GetDbContext()) - { - var dbFilters = db.Filters - .Where(f => f.Name.ToLower().Contains(search.ToLower()) || - f.PropertyName.ToLower().Contains(search.ToLower())) - .OrderBy(f => f.Name); + var dbFilters = _ccmDbContext.Filters + .Where(f => f.Name.ToLower().Contains(search.ToLower()) || + f.PropertyName.ToLower().Contains(search.ToLower())) + .OrderBy(f => f.Name).ToList(); - return dbFilters.Select(dbFilter => MapToFilter(dbFilter)).ToList(); - } + return dbFilters.Select(dbFilter => MapToFilter(dbFilter)).ToList(); } private Filter MapToFilter(FilterEntity dbFilter) diff --git a/CCM.Data/Repositories/LocationRepository.cs b/CCM.Data/Repositories/LocationRepository.cs index 783e2a8c..c1d96f37 100644 --- a/CCM.Data/Repositories/LocationRepository.cs +++ b/CCM.Data/Repositories/LocationRepository.cs @@ -28,16 +28,15 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Net.Sockets; +using NLog; +using LazyCache; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; -using System.Data.Entity; -using System.Net.Sockets; using CCM.Core.Entities.Specific; -using NLog; -using AutoMapper; using CCM.Core.Extensions; -using LazyCache; namespace CCM.Data.Repositories { @@ -45,256 +44,263 @@ public class LocationRepository : BaseRepository, ILocationRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public LocationRepository(IAppCache cache) : base(cache) + public LocationRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public void Save(Location location) { - using (var db = GetDbContext()) - { - LocationEntity dbLocation; - - if (location.Id != Guid.Empty) - { - dbLocation = db.Locations - .Include(l => l.ProfileGroup) - .SingleOrDefault(l => l.Id == location.Id); - - if (dbLocation == null) - { - throw new NullReferenceException("Location"); - } - } - else - { - dbLocation = new LocationEntity - { - Id = Guid.NewGuid(), - CreatedBy = location.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - location.Id = dbLocation.Id; - location.CreatedOn = dbLocation.CreatedOn; - db.Locations.Add(dbLocation); - } + var db = _ccmDbContext; + LocationEntity dbLocation; - dbLocation.Name = location.Name; - dbLocation.ShortName = location.ShortName; - dbLocation.Comment = location.Comment; - dbLocation.CarrierConnectionId = location.CarrierConnectionId; - dbLocation.UpdatedBy = location.UpdatedBy; - dbLocation.UpdatedOn = DateTime.UtcNow; - - location.UpdatedOn = dbLocation.UpdatedOn; - - // IP V4 - if (IPNetwork.TryParse(location.Net, location.Cidr ?? 0, out IPNetwork ipv4Network)) - { - dbLocation.Net_Address_v4 = ipv4Network.Network.ToString(); - dbLocation.Cidr = ipv4Network.Cidr; - } - else - { - dbLocation.Net_Address_v4 = location.Net; - dbLocation.Cidr = location.Cidr; - } + if (location.Id != Guid.Empty) + { + dbLocation = db.Locations + .SingleOrDefault(l => l.Id == location.Id); - // IP v6 - if (IPNetwork.TryParse(location.Net_v6, location.Cidr_v6 ?? 0, out IPNetwork ipv6Network)) + if (dbLocation == null) { - dbLocation.Net_Address_v6 = ipv6Network.Network.ToString(); - dbLocation.Cidr_v6 = ipv6Network.Cidr; + throw new Exception("Location could not be found"); } - else + } + else + { + dbLocation = new LocationEntity { - dbLocation.Net_Address_v6 = location.Net_v6; - dbLocation.Cidr_v6 = location.Cidr_v6; - } + Id = Guid.NewGuid(), + CreatedBy = location.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + location.Id = dbLocation.Id; + location.CreatedOn = dbLocation.CreatedOn; + db.Locations.Add(dbLocation); + } - // Profile Group - dbLocation.ProfileGroup = db.ProfileGroups.SingleOrDefault(r => r.Id == location.ProfileGroup.Id); + dbLocation.Name = location.Name; + dbLocation.ShortName = location.ShortName; + dbLocation.Comment = location.Comment; + dbLocation.CarrierConnectionId = location.CarrierConnectionId; + dbLocation.UpdatedBy = location.UpdatedBy; + dbLocation.UpdatedOn = DateTime.UtcNow; - // Region - dbLocation.Region = location.Region != null && location.Region.Id != Guid.Empty - ? db.Regions.SingleOrDefault(r => r.Id == location.Region.Id) - : null; + location.UpdatedOn = dbLocation.UpdatedOn; - // City - dbLocation.City = location.City != null && location.City.Id != Guid.Empty - ? db.Cities.SingleOrDefault(c => c.Id == location.City.Id) - : null; + // IP V4 + if (IPNetwork.TryParse(location.Net, location.Cidr ?? 0, out IPNetwork ipv4Network)) + { + dbLocation.Net_Address_v4 = ipv4Network.Network.ToString(); + dbLocation.Cidr = ipv4Network.Cidr; + } + else + { + dbLocation.Net_Address_v4 = location.Net; + dbLocation.Cidr = location.Cidr; + } - db.SaveChanges(); + // IP v6 + if (IPNetwork.TryParse(location.Net_v6, location.Cidr_v6 ?? 0, out IPNetwork ipv6Network)) + { + dbLocation.Net_Address_v6 = ipv6Network.Network.ToString(); + dbLocation.Cidr_v6 = ipv6Network.Cidr; + } + else + { + dbLocation.Net_Address_v6 = location.Net_v6; + dbLocation.Cidr_v6 = location.Cidr_v6; } + + // Profile Group + dbLocation.ProfileGroup = location.ProfileGroup != null && location.ProfileGroup.Id != Guid.Empty + ? db.ProfileGroups.SingleOrDefault(r => r.Id == location.ProfileGroup.Id) + : null; + + // Region + dbLocation.Region = location.Region != null && location.Region.Id != Guid.Empty + ? db.Regions.SingleOrDefault(r => r.Id == location.Region.Id) + : null; + dbLocation.Region_Id = dbLocation.Region?.Id ?? null; + + // City + dbLocation.City = location.City != null && location.City.Id != Guid.Empty + ? db.Cities.SingleOrDefault(c => c.Id == location.City.Id) + : null; + dbLocation.City_Id = dbLocation.City?.Id ?? null; + + // Category + dbLocation.Category = location.Category != null && location.Category.Id != Guid.Empty + ? db.Categories.SingleOrDefault(c => c.Id == location.Category.Id) + : null; + dbLocation.Category_Id = dbLocation.Category?.Id ?? null; + + db.SaveChanges(); } public Location GetById(Guid id) { - using (var db = GetDbContext()) - { - var dbLocation = db.Locations - .Include(l => l.Region) - .Include(l => l.City) - .Include(l => l.ProfileGroup) - .SingleOrDefault(l => l.Id == id); - return MapToLocation(dbLocation, true, true, true); - } + var dbLocation = _ccmDbContext.Locations + .Include(l => l.Region) + .Include(l => l.City) + .Include(l => l.ProfileGroup) + .Include(l => l.Category) + .SingleOrDefault(l => l.Id == id); + return MapToLocation(dbLocation, true, true, true); } public List GetAll() { - using (var db = GetDbContext()) - { - var dbLocations = db.Locations - .Include(l => l.City) - .Include(l => l.Region) - .Include(l => l.ProfileGroup) - .ToList(); - var locations = dbLocations - .Select(dbLocation => MapToLocation(dbLocation, true, true, true)) - .OrderBy(l => l.Name).ToList(); - return locations; - } + var dbLocations = _ccmDbContext.Locations + .Include(l => l.City) + .Include(l => l.Region) + .Include(l => l.ProfileGroup) + .Include(l => l.Category) + .ToList(); + + var locations = dbLocations + .Select(dbLocation => MapToLocation(dbLocation, true, true, true)) + .OrderBy(l => l.Name).ToList(); + return locations; } public void Delete(Guid id) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + var location = db.Locations + .Include(l => l.RegisteredSips) + .SingleOrDefault(l => l.Id == id); + + if (location != null) { - var location = db.Locations.SingleOrDefault(l => l.Id == id); - if (location != null) - { - if (location.RegisteredSips != null) - { - location.RegisteredSips.Clear(); - } + location.RegisteredSips?.Clear(); - db.Locations.Remove(location); - db.SaveChanges(); - } + db.Locations.Remove(location); + db.SaveChanges(); } } public List FindLocations(string searchString) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + IQueryable dbLocationsQuery; + + // Search on IP-Address if the search string can be interpreted as such + if (IPAddress.TryParse(searchString, out IPAddress searchIpAddress) && !searchString.IsNumeric()) { - IQueryable dbLocationsQuery; + // Search on only numbers, to not be interpreted as IP-Address + if (searchIpAddress.AddressFamily == AddressFamily.InterNetwork) // V4 + { + var locationEntities = db.Locations.Where(l => !string.IsNullOrEmpty(l.Net_Address_v4)) + .ToList(); + + var networks = locationEntities + .Where(l => l.Cidr.HasValue) + .Select(l => new LocationNetwork(l.Id, l.Net_Address_v4, l.Cidr.Value)) + .Where(n => n.Network != null) + .ToList(); + + var locationIds = networks + //.Where(n => IPNetwork.Contains(n.Network, searchIpAddress)) // TODO: check if correctly changed + .Where(n => n.Network.Contains(searchIpAddress)) + .Select(n => n.Id); + + dbLocationsQuery = db.Locations + .Include(l => l.ProfileGroup) + .Where(l => locationIds.Contains(l.Id)) + .OrderBy(l => l.Cidr); - // Search on IP-Address if the search string can be interpreted as such - if (IPAddress.TryParse(searchString, out IPAddress searchIpAddress) && !searchString.IsNumeric()) + } + else if (searchIpAddress.AddressFamily == AddressFamily.InterNetworkV6) // V6 { - // Search on only numbers, to not be interpreted as IP-Address - if (searchIpAddress.AddressFamily == AddressFamily.InterNetwork) // V4 - { - var locationEntities = db.Locations.Where(l => !string.IsNullOrEmpty(l.Net_Address_v4)) - .ToList(); - - var networks = locationEntities - .Where(l => l.Cidr.HasValue) - .Select(l => new LocationNetwork(l.Id, l.Net_Address_v4, l.Cidr.Value)) - .Where(n => n.Network != null) - .ToList(); - - var locationIds = networks - .Where(n => IPNetwork.Contains(n.Network, searchIpAddress)) - .Select(n => n.Id); - - dbLocationsQuery = db.Locations - .Include(l => l.ProfileGroup) - .Where(l => locationIds.Contains(l.Id)) - .OrderBy(l => l.Cidr); - - } - else if (searchIpAddress.AddressFamily == AddressFamily.InterNetworkV6) // V6 - { - var networks = db.Locations - .Where(l => !string.IsNullOrEmpty(l.Net_Address_v6)) - .Select(l => new LocationNetwork(l.Id, l.Net_Address_v6, l.Cidr_v6.Value)) - .Where(n => n.Network != null) - .ToList(); - - var locationIds = networks - .Where(n => IPNetwork.Contains(n.Network, searchIpAddress)) - .Select(n => n.Id); - - dbLocationsQuery = db.Locations - .Where(l => locationIds.Contains(l.Id)) - .OrderBy(l => l.Cidr_v6); - } - else - { - // Unknown address type - dbLocationsQuery = Enumerable.Empty().AsQueryable(); - } + var networks = db.Locations + .Where(l => !string.IsNullOrEmpty(l.Net_Address_v6)) + .Select(l => new LocationNetwork(l.Id, l.Net_Address_v6, l.Cidr_v6.Value)) + .Where(n => n.Network != null) + .ToList(); + + var locationIds = networks + //.Where(n => IPNetwork.Contains(n.Network, searchIpAddress)) // TODO: check if correctly changed + .Where(n => n.Network.Contains(searchIpAddress)) + .Select(n => n.Id); + + dbLocationsQuery = db.Locations + .Where(l => locationIds.Contains(l.Id)) + .OrderBy(l => l.Cidr_v6); } else { - // Search by name - dbLocationsQuery = db.Locations - .Where(l => - l.CarrierConnectionId.ToLower().Contains(searchString.ToLower()) || - l.Name.ToLower().Contains(searchString.ToLower()) || - l.ShortName.ToLower().Contains(searchString.ToLower())) - .OrderBy(l => l.Name); + // Unknown address type + dbLocationsQuery = Enumerable.Empty().AsQueryable(); } - - var dbLocations = dbLocationsQuery.ToList(); - return dbLocations.Select(dbLocation => MapToLocation(dbLocation, true, true, true)).ToList(); } + else + { + // Search by name + dbLocationsQuery = db.Locations + .Where(l => + l.CarrierConnectionId.ToLower().Contains(searchString.ToLower()) || + l.Name.ToLower().Contains(searchString.ToLower()) || + l.ShortName.ToLower().Contains(searchString.ToLower())) + .OrderBy(l => l.Name); + } + + var dbLocations = dbLocationsQuery.ToList(); + return dbLocations.Select(dbLocation => MapToLocation(dbLocation, true, true, true)).ToList(); } public List GetAllLocationNetworks() { - using (var db = GetDbContext()) - { - var locations = db.Locations.ToList(); - - var networksV4 = locations - .Where(l => !string.IsNullOrEmpty(l.Net_Address_v4) && l.Cidr.HasValue) - .Select(l => new LocationNetwork(l.Id, l.Net_Address_v4, l.Cidr.Value)) - .Where(l => l.Network != null) - .ToList(); - - var networksV6 = locations - .Where(l => !string.IsNullOrEmpty(l.Net_Address_v6) && l.Cidr_v6.HasValue) - .Select(l => new LocationNetwork(l.Id, l.Net_Address_v6, l.Cidr_v6.Value)) - .Where(l => l.Network != null) - .ToList(); + var db = _ccmDbContext; + var locations = db.Locations.ToList(); + + var networksV4 = locations + .Where(l => !string.IsNullOrEmpty(l.Net_Address_v4) && l.Cidr.HasValue) + .Select(l => new LocationNetwork(l.Id, l.Net_Address_v4, l.Cidr.Value)) + .Where(l => l.Network != null) + .ToList(); + + var networksV6 = locations + .Where(l => !string.IsNullOrEmpty(l.Net_Address_v6) && l.Cidr_v6.HasValue) + .Select(l => new LocationNetwork(l.Id, l.Net_Address_v6, l.Cidr_v6.Value)) + .Where(l => l.Network != null) + .ToList(); + + return networksV4.Concat(networksV6).ToList(); + } - return networksV4.Concat(networksV6).ToList(); - } + public Dictionary GetLocationsAndProfiles() + { + var db = _ccmDbContext; + var result = db.Locations + .OrderBy(y => y.Name) + .Select(x => + new + { + LocationId = x.Id, + LocationName = x.Name, + ProfileGroupId = x.ProfileGroup.Id, + ProfileGroupName = x.ProfileGroup.Name + }) + .ToList(); + + return result.ToDictionary(u => u.LocationId, x => + { + return new LocationAndProfiles( + locationId: x.LocationId, + locationName: x.LocationName, + profileGroupId: x.ProfileGroupId, + profileGroupName: x.ProfileGroupName); + }); } - public Dictionary GetLocationsAndProfiles() + public List GetAllLocationInfo() { - using (var db = GetDbContext()) + return _ccmDbContext.Locations.Select(l => new LocationInfo() { - var result = db.Locations - .OrderBy(y => y.Name) - .Select(x => - new - { - LocationId = x.Id, - LocationName = x.Name, - ProfileGroupId = x.ProfileGroup.Id, - ProfileGroupName = x.ProfileGroup.Name - }) - .ToList(); - - return result.ToDictionary(u => u.LocationId, x => - { - return new LocationAndProfiles( - locationId: x.LocationId, - locationName: x.LocationName, - profileGroupId: x.ProfileGroupId, - profileGroupName: x.ProfileGroupName); - }); - } + Id = l.Id, + Name = l.Name + }).ToList(); } - private Location MapToLocation(LocationEntity dbLocation, bool includeCity, bool includeRegion, bool includeProfileGroup) + private Location MapToLocation(LocationEntity dbLocation, bool includeCity, bool includeRegion, bool includeProfileGroup, bool includeCategory = true) { if (dbLocation == null) return null; @@ -315,7 +321,8 @@ private Location MapToLocation(LocationEntity dbLocation, bool includeCity, bool UpdatedOn = dbLocation.UpdatedOn, Region = includeRegion ? MapToRegion(dbLocation.Region) : null, City = includeCity ? MapToCity(dbLocation.City) : null, - ProfileGroup = includeProfileGroup ? MapToProfileGroup(dbLocation.ProfileGroup) : null + ProfileGroup = includeProfileGroup ? MapToProfileGroup(dbLocation.ProfileGroup) : null, + Category = includeCategory ? MapToCategory(dbLocation.Category) : null }; return location; @@ -333,7 +340,36 @@ private City MapToCity(CityEntity dbCity) private ProfileGroup MapToProfileGroup(ProfileGroupEntity dbProfileGroup) { - return Mapper.Map(dbProfileGroup); + return dbProfileGroup != null ? new ProfileGroup + { + Id = dbProfileGroup.Id, + Name = dbProfileGroup.Name, + Description = dbProfileGroup.Description, + GroupSortWeight = dbProfileGroup.GroupSortWeight, + Profiles = dbProfileGroup?.OrderedProfiles?.Select(MapToProfileCodec).OrderBy(p => p.OrderIndex).ToList() ?? null + } : null; + } + + private ProfileCodec MapToProfileCodec(ProfileGroupProfileOrdersEntity profileGroupProfileOrdersEntity) + { + return profileGroupProfileOrdersEntity != null ? new ProfileCodec + { + Id = profileGroupProfileOrdersEntity.Profile.Id, + Name = profileGroupProfileOrdersEntity.Profile.Name, + Description = profileGroupProfileOrdersEntity.Profile.Description, + LongDescription = profileGroupProfileOrdersEntity.Profile.LongDescription, + Sdp = profileGroupProfileOrdersEntity.Profile.Sdp, + OrderIndex = profileGroupProfileOrdersEntity.SortIndexForProfileInGroup + } : null; + } + + private Category MapToCategory(CategoryEntity dbCategory) + { + return dbCategory != null ? new Category + { + Id = dbCategory.Id, + Name = dbCategory.Name + } : null; } } } diff --git a/CCM.Data/Repositories/LogRepository.cs b/CCM.Data/Repositories/LogRepository.cs index 2cde3c28..d1629e1c 100644 --- a/CCM.Data/Repositories/LogRepository.cs +++ b/CCM.Data/Repositories/LogRepository.cs @@ -26,99 +26,113 @@ using System; using System.Collections.Generic; -using System.Data.Entity; using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; +using Microsoft.Data.SqlClient; namespace CCM.Data.Repositories { public class LogRepository : BaseRepository, ILogRepository { - public LogRepository(IAppCache cache) : base(cache) + public LogRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public async Task> GetLastAsync(int nrOfRows, string application, DateTime? startTime, DateTime? endTime, int minLevel, string search, Guid activityId) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + List dbLogRows; + + if (activityId != Guid.Empty) + { + dbLogRows = await db.Logs + .Where(l => l.ActivityId == activityId) + .OrderByDescending(l => l.Id) + .ToListAsync(); + } + else { - List dbLogRows; + IQueryable dbLogQuery = db.Logs.Where(l => l.LevelValue >= minLevel); - if (activityId != Guid.Empty) + if (!string.IsNullOrEmpty(application)) { - dbLogRows = await db.Logs - .Where(l => l.ActivityId == activityId) - .OrderByDescending(l => l.Id) - .ToListAsync(); + dbLogQuery = dbLogQuery.Where(r => r.Application == application); } - else + + if (startTime != null) { - IQueryable dbLogQuery = db.Logs.Where(l => l.LevelValue >= minLevel); - - if (!string.IsNullOrEmpty(application)) - { - dbLogQuery = dbLogQuery.Where(r => r.Application == application); - } - - if (startTime != null) - { - dbLogQuery = dbLogQuery.Where(r => r.Date >= startTime.Value); - } - - if (endTime != null) - { - dbLogQuery = dbLogQuery.Where(r => r.Date <= endTime.Value); - } - - if (!string.IsNullOrEmpty(search)) - { - dbLogQuery = dbLogQuery.Where(r => r.Message.Contains(search)); - } - - dbLogRows = await dbLogQuery - .OrderByDescending(l => l.Id) - .Take(nrOfRows) - .ToListAsync(); + dbLogQuery = dbLogQuery.Where(r => r.Date >= startTime.Value); } - return dbLogRows.Select(r => new Log + if (endTime != null) { - Id = r.Id, - Date = r.Date, - Level = r.Level, - Callsite = r.Callsite, - Message = r.Message, - Exception = r.Exception, - Application = r.Application, - ActivityId = r.ActivityId - }).ToList(); + dbLogQuery = dbLogQuery.Where(r => r.Date <= endTime.Value); + } + + if (!string.IsNullOrEmpty(search)) + { + dbLogQuery = dbLogQuery.Where(r => r.Message.Contains(search)); + } + + dbLogRows = await dbLogQuery + .OrderByDescending(l => l.Id) + .Take(nrOfRows) + .ToListAsync(); } + + return dbLogRows.Select(r => new Log + { + Id = r.Id, + Date = r.Date, + Level = r.Level, + Callsite = r.Callsite, + Message = r.Message, + Exception = r.Exception, + Application = r.Application, + ActivityId = r.ActivityId + }).ToList(); } public async Task> GetLogInfoAsync() { - using (var db = GetDbContext()) - { - var logInfo = await db.Logs - .GroupBy(l => l.Application) - .Select(g => new LogInfo() { Application = g.Key, Count = g.Count(), MinDate = g.Min(x => x.Date) }) - .ToListAsync(); + var db = _ccmDbContext; + var logInfo = await db.Logs + .GroupBy(l => l.Application) + .Select(g => new LogInfo() { Application = g.Key, Count = g.Count(), MinDate = g.Min(x => x.Date) }) + .ToListAsync(); - return logInfo; - } + return logInfo; } - public void DeleteOldest(int nrOfRowsToDelete = 100) + public async Task GetLogTableInfoAsync() { - using (var db = GetDbContext()) + var db = _ccmDbContext; + var rows = await db.Logs.CountAsync(); + var minDate = db.Logs.OrderBy(l => l.Date).FirstOrDefault(); + + return new LogInfo() { - var sql = $"DELETE FROM `Logs` ORDER BY Id LIMIT {nrOfRowsToDelete};"; - db.Database.ExecuteSqlCommand(sql); - } + Application = "CCM", + Count = rows, + MinDate = minDate?.Date ?? DateTime.MinValue + }; + } + + public void DeleteOldest(int nrOfRowsToDelete = 100) + { + var commandText = $"DELETE FROM `Logs` ORDER BY Date ASC LIMIT {nrOfRowsToDelete}"; + _ccmDbContext.Database.ExecuteSqlRaw(commandText); + } + + public void DeleteAll() + { + var commandText = $"TRUNCATE `Logs`"; + _ccmDbContext.Database.ExecuteSqlRaw(commandText); } } } diff --git a/CCM.Data/Repositories/MetaRepository.cs b/CCM.Data/Repositories/MetaRepository.cs index 19b896b1..51a7daca 100644 --- a/CCM.Data/Repositories/MetaRepository.cs +++ b/CCM.Data/Repositories/MetaRepository.cs @@ -42,115 +42,106 @@ public class MetaRepository : BaseRepository, IMetaRepository protected static readonly Logger log = LogManager.GetCurrentClassLogger(); private static List availableMetaTypes; - public MetaRepository(IAppCache cache) : base(cache) + public MetaRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } - /// - /// Gets the meta type property values. - /// - /// Type of the meta. - /// - public List GetMetaTypePropertyValues(AvailableMetaType metaType) - { - using (var db = GetDbContext()) - { - var values = new List(); - var objectType = Type.GetType(metaType.Type); - var contextSet = db.Set(objectType); - - foreach (var item in contextSet) - { - try - { - var prop = item.GetType().GetProperty(metaType.PropertyName); - var objectValue = prop?.GetValue(item) ?? String.Empty; - values.Add(objectValue.ToString()); - } - catch (Exception ex) - { - log.Error(ex, $"Error getting {metaType.Type} Meta value for property {metaType.PropertyName}"); - } - } - - return values; - } - } + ///// + ///// Gets the meta type property values. + ///// + ///// Type of the meta. + ///// + ///// TODO: does not seem to be in use + //public List GetMetaTypePropertyValues(AvailableMetaType metaType) + //{ + // var db = _ccmDbContext; + // { + // var values = new List(); + // Type objectType = Type.GetType(metaType.Type); + // var contextSet = db.Set(); // TODO: replaced this db.Set(objectType); + + // foreach (var item in contextSet) + // { + // try + // { + // var prop = item.GetType().GetProperty(metaType.PropertyName); + // var objectValue = prop?.GetValue(item) ?? String.Empty; + // values.Add(objectValue.ToString()); + // } + // catch (Exception ex) + // { + // log.Error(ex, $"Error getting {metaType.Type} Meta value for property {metaType.PropertyName}"); + // } + // } + + // return values; + // } + //} public bool CheckMetaTypeNameAvailability(string name, Guid id) { - using (var db = GetDbContext()) - { - return !db.MetaTypes.Any(m => m.Name == name && m.Id != id); - } + var db = _ccmDbContext; + return !db.MetaTypes.Any(m => m.Name == name && m.Id != id); } public void Save(MetaType metaType) { - using (var db = GetDbContext()) - { - Entities.MetaTypeEntity dbMetaType = null; + var db = _ccmDbContext; + Entities.MetaTypeEntity dbMetaType = null; - if (metaType.Id != Guid.Empty) - { - dbMetaType = db.MetaTypes.SingleOrDefault(m => m.Id == metaType.Id); - } + if (metaType.Id != Guid.Empty) + { + dbMetaType = db.MetaTypes.SingleOrDefault(m => m.Id == metaType.Id); + } - if (dbMetaType == null) + if (dbMetaType == null) + { + dbMetaType = new Entities.MetaTypeEntity() { - dbMetaType = new Entities.MetaTypeEntity() - { - Id = Guid.NewGuid(), - CreatedBy = metaType.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - metaType.Id = dbMetaType.Id; - metaType.CreatedOn = dbMetaType.CreatedOn; - - db.MetaTypes.Add(dbMetaType); - } + Id = Guid.NewGuid(), + CreatedBy = metaType.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + metaType.Id = dbMetaType.Id; + metaType.CreatedOn = dbMetaType.CreatedOn; + + db.MetaTypes.Add(dbMetaType); + } - dbMetaType.FullPropertyName = metaType.FullPropertyName; - dbMetaType.Name = metaType.Name; - dbMetaType.PropertyName = metaType.PropertyName; - dbMetaType.Type = metaType.Type; - dbMetaType.UpdatedBy = metaType.UpdatedBy; - dbMetaType.UpdatedOn = DateTime.UtcNow; - metaType.UpdatedOn = dbMetaType.UpdatedOn; + dbMetaType.FullPropertyName = metaType.FullPropertyName; + dbMetaType.Name = metaType.Name; + dbMetaType.PropertyName = metaType.PropertyName; + dbMetaType.Type = metaType.Type; + dbMetaType.UpdatedBy = metaType.UpdatedBy; + dbMetaType.UpdatedOn = DateTime.UtcNow; + metaType.UpdatedOn = dbMetaType.UpdatedOn; - db.SaveChanges(); - } + db.SaveChanges(); } public List GetAll() { - using (var db = GetDbContext()) - { - var dbMetaTypes = db.MetaTypes.ToList(); - return dbMetaTypes.Select(MapMetaType).OrderBy(m => m.Name).ToList(); - } + var db = _ccmDbContext; + var dbMetaTypes = db.MetaTypes.ToList(); + return dbMetaTypes.Select(MapMetaType).OrderBy(m => m.Name).ToList(); } public MetaType GetById(Guid id) { - using (var db = GetDbContext()) - { - var dbMetaType = db.MetaTypes.SingleOrDefault(m => m.Id == id); - return dbMetaType != null ? MapMetaType(dbMetaType) : null; - } + var db = _ccmDbContext; + var dbMetaType = db.MetaTypes.SingleOrDefault(m => m.Id == id); + return dbMetaType != null ? MapMetaType(dbMetaType) : null; } public void Delete(Guid id) { - using (var db = GetDbContext()) - { - var dbMetaType = db.MetaTypes.SingleOrDefault(m => m.Id == id); + var db = _ccmDbContext; + var dbMetaType = db.MetaTypes.SingleOrDefault(m => m.Id == id); - if (dbMetaType != null) - { - db.MetaTypes.Remove(dbMetaType); - db.SaveChanges(); - } + if (dbMetaType != null) + { + db.MetaTypes.Remove(dbMetaType); + db.SaveChanges(); } } @@ -166,7 +157,7 @@ public List GetMetaTypeProperties() } availableMetaTypes = new List(); - var properties = (typeof(Entities.RegisteredSipEntity)).GetProperties().Where(p => p.GetCustomAttributes(false).Any(a => a is MetaPropertyAttribute || a is MetaTypeAttribute)); + var properties = (typeof(Entities.RegisteredCodecEntity)).GetProperties().Where(p => p.GetCustomAttributes(false).Any(a => a is MetaPropertyAttribute || a is MetaTypeAttribute)); foreach (var property in properties) { @@ -186,12 +177,10 @@ public List GetMetaTypeProperties() public List FindMetaTypes(string search) { - using (var db = GetDbContext()) - { - var list = db.MetaTypes.Where(m => m.Name.ToLower().Contains(search.ToLower()) || - m.PropertyName.ToLower().Contains(search.ToLower())).ToList(); - return list.Select(MapMetaType).OrderBy(m => m.Name).ToList(); - } + var db = _ccmDbContext; + var list = db.MetaTypes.Where(m => m.Name.ToLower().Contains(search.ToLower()) || + m.PropertyName.ToLower().Contains(search.ToLower())).ToList(); + return list.Select(MapMetaType).OrderBy(m => m.Name).ToList(); } private List GetSubMetaTypeProperties(System.Reflection.PropertyInfo property, string parent) diff --git a/CCM.Data/Repositories/OwnersRepository.cs b/CCM.Data/Repositories/OwnersRepository.cs index 18e89ac1..e3ed61bf 100644 --- a/CCM.Data/Repositories/OwnersRepository.cs +++ b/CCM.Data/Repositories/OwnersRepository.cs @@ -31,60 +31,59 @@ using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; +using Microsoft.EntityFrameworkCore; namespace CCM.Data.Repositories { public class OwnersRepository : BaseRepository, IOwnersRepository { - public OwnersRepository(IAppCache cache) : base(cache) + public OwnersRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public void Save(Owner owner) { - using (var db = GetDbContext()) - { - OwnerEntity dbOwner = null; + var db = _ccmDbContext; + OwnerEntity dbOwner = null; + if (owner.Id != Guid.Empty) + { + dbOwner = db.Owners + .Include(o => o.SipAccounts) + .SingleOrDefault(o => o.Id == owner.Id); + } - if (owner.Id != Guid.Empty) + if (dbOwner == null) + { + dbOwner = new OwnerEntity() { - dbOwner = db.Owners.SingleOrDefault(o => o.Id == owner.Id); - } + Id = Guid.NewGuid(), + CreatedBy = owner.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + db.Owners.Add(dbOwner); + owner.Id = dbOwner.Id; + owner.CreatedOn = dbOwner.CreatedOn; + } - if (dbOwner == null) - { - dbOwner = new OwnerEntity() - { - Id = Guid.NewGuid(), - CreatedBy = owner.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - db.Owners.Add(dbOwner); - owner.Id = dbOwner.Id; - owner.CreatedOn = dbOwner.CreatedOn; - } - - - dbOwner.Name = owner.Name; - dbOwner.UpdatedBy = owner.UpdatedBy; - dbOwner.UpdatedOn = DateTime.UtcNow; - owner.UpdatedOn = dbOwner.UpdatedOn; - db.SaveChanges(); - } + dbOwner.Name = owner.Name; + dbOwner.UpdatedBy = owner.UpdatedBy; + dbOwner.UpdatedOn = DateTime.UtcNow; + owner.UpdatedOn = dbOwner.UpdatedOn; + + db.SaveChanges(); } public void Delete(Guid id) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + OwnerEntity owner = db.Owners + .Include(o => o.SipAccounts) + .SingleOrDefault(o => o.Id == id); + if (owner != null) { - OwnerEntity owner = db.Owners.SingleOrDefault(o => o.Id == id); - if (owner == null) - { - return; - } - + owner.SipAccounts?.Clear(); db.Owners.Remove(owner); db.SaveChanges(); } @@ -92,59 +91,60 @@ public void Delete(Guid id) public List GetAll() { - using (var db = GetDbContext()) - { - var dbOwners = db.Owners.ToList(); - return dbOwners.Select(owner => MapOwner(owner)).OrderBy(o => o.Name).ToList(); - } + var db = _ccmDbContext; + var dbOwners = db.Owners + .Include(o => o.SipAccounts).ToList(); + + return dbOwners.Select(owner => MapToOwner(owner)).OrderBy(o => o.Name).ToList(); } public Owner GetById(Guid id) { - using (var db = GetDbContext()) - { - var owner = db.Owners.SingleOrDefault(o => o.Id == id); - return owner == null ? null : MapOwner(owner); - } + var db = _ccmDbContext; + var owner = db.Owners + .Include(o => o.SipAccounts) + .SingleOrDefault(o => o.Id == id); + + return owner == null ? null : MapToOwner(owner); } public Owner GetByName(string name) { - using (var db = GetDbContext()) - { - name = (name ?? string.Empty).ToLower(); + name = (name ?? string.Empty).ToLower(); - var owner = db.Owners.SingleOrDefault(o => o.Name.ToLower() == name); - return owner == null ? null : MapOwner(owner, false); - } + var owner = _ccmDbContext.Owners + .Include(o => o.SipAccounts) + .SingleOrDefault(o => o.Name.ToLower() == name); + + return owner == null ? null : MapToOwner(owner, false); } public List FindOwners(string search) { - using (var db = GetDbContext()) - { - var dbOwners = db.Owners.Where(o => o.Name.ToLower().Contains(search.ToLower())).ToList(); - return dbOwners.Select(owner => MapOwner(owner)).OrderBy(o => o.Name).ToList(); - } + var dbOwners = _ccmDbContext.Owners + .Include(o => o.SipAccounts) + .Where(o => o.Name.ToLower().Contains(search.ToLower())).ToList(); + + return dbOwners.Select(owner => MapToOwner(owner)).OrderBy(o => o.Name).ToList(); } - private Owner MapOwner(OwnerEntity owner, bool includeUsers = true) + private Owner MapToOwner(OwnerEntity owner, bool includeUsers = true) { return owner == null ? null : new Owner - { - Id = owner.Id, - Name = owner.Name, - CreatedBy = owner.CreatedBy, - CreatedOn = owner.CreatedOn, - UpdatedBy = owner.UpdatedBy, - UpdatedOn = owner.UpdatedOn, - Users = includeUsers && owner.Users != null - ? owner.Users.Select(MapUser).OrderBy(u => u.UserName).ToList() + { + Id = owner.Id, + Name = owner.Name, + CreatedBy = owner.CreatedBy, + CreatedOn = owner.CreatedOn, + UpdatedBy = owner.UpdatedBy, + UpdatedOn = owner.UpdatedOn, + Users = includeUsers && owner.SipAccounts != null + ? owner.SipAccounts.Select(MapToUser).OrderBy(u => u.UserName).ToList() : new List() - }; + }; } - private SipAccount MapUser(SipAccountEntity dbUser) + private SipAccount MapToUser(SipAccountEntity dbUser) { return new SipAccount { diff --git a/CCM.Data/Repositories/ProfileGroupRepository.cs b/CCM.Data/Repositories/ProfileGroupRepository.cs index 2f918ca1..d49684ca 100644 --- a/CCM.Data/Repositories/ProfileGroupRepository.cs +++ b/CCM.Data/Repositories/ProfileGroupRepository.cs @@ -28,161 +28,177 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using System.Data.Entity; -using AutoMapper; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; -using Profile = AutoMapper.Profile; namespace CCM.Data.Repositories { public class ProfileGroupRepository : BaseRepository, IProfileGroupRepository { - public ProfileGroupRepository(IAppCache cache) : base(cache) + public ProfileGroupRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public List GetAll() { - using (var db = GetDbContext()) - { - var profileGroups = db.ProfileGroups - .Include(g => g.OrderedProfiles.Select(op => op.Profile)) - .ToList(); - var pg = profileGroups.OrderBy(p => p.GroupSortWeight).Select(gp => Mapper.Map(gp)).ToList(); - return pg; - // TODO: This needs to keep it's order in some way, for the profiles.. just make sure. - } + var profileGroups = _ccmDbContext.ProfileGroups + .Include(p => p.OrderedProfiles) + .ThenInclude(op => op.Profile) + .ToList(); + + var pg = profileGroups.OrderBy(p => p.GroupSortWeight).Select(MapToProfileGroup).ToList(); + return pg; } - public ProfileGroup GetById(Guid id) + public List FindProfileGroups(string search) { - using (var db = GetDbContext()) - { - var group = db.ProfileGroups - .Include(g => g.OrderedProfiles.Select(op => op.Profile)) - .SingleOrDefault(g => g.Id == id); - var profileGroup = Mapper.Map(group); + var profileGroups = _ccmDbContext.ProfileGroups + .Include(p => p.OrderedProfiles) + .ThenInclude(op => op.Profile) + .Where(u => u.Name.ToLower().Contains(search.ToLower()) || + u.Description.ToLower().Contains(search.ToLower())) + .ToList(); + + var pg = profileGroups.OrderBy(p => p.GroupSortWeight).Select(MapToProfileGroup).ToList(); + return pg; + } - return profileGroup; - } + public ProfileGroup GetById(Guid id) + { + var db = _ccmDbContext; + var profileGroup = db.ProfileGroups + .Include(g => g.OrderedProfiles) + .ThenInclude(p => p.Profile) + .Select(MapToProfileGroup) + .SingleOrDefault(g => g.Id == id); + + return profileGroup; } public void Save(ProfileGroup profileGroup) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + bool nameCollision = db.ProfileGroups.Any(p => p.Name == profileGroup.Name && p.Id != profileGroup.Id); + if (nameCollision) { - bool nameCollision = db.ProfileGroups.Any(p => p.Name == profileGroup.Name && p.Id != profileGroup.Id); - if (nameCollision) - { - throw new DuplicateNameException(); - } + throw new DuplicateNameException(); + } - ProfileGroupEntity dbProfileGroup; + ProfileGroupEntity dbProfileGroup; - if (profileGroup.Id != Guid.Empty) + if (profileGroup.Id != Guid.Empty) + { + dbProfileGroup = db.ProfileGroups + .Include(op => op.OrderedProfiles) + .SingleOrDefault(g => g.Id == profileGroup.Id); + if (dbProfileGroup == null) { - // Update - dbProfileGroup = db.ProfileGroups.SingleOrDefault(g => g.Id == profileGroup.Id); - if (dbProfileGroup == null) - { - throw new Exception("Group could not be found"); - } - - Mapper.Map(profileGroup, dbProfileGroup); - - dbProfileGroup.OrderedProfiles.Where(op => !profileGroup.Profiles.Any(sp => sp.Id == op.ProfileId)) - .ToList() - .ForEach(pg => - { - dbProfileGroup.OrderedProfiles.Remove(pg); - } - ); + throw new Exception("ProfileGroup could not be found"); + } - profileGroup.Profiles.Where(sp => !dbProfileGroup.OrderedProfiles.Any(op => op.ProfileId == sp.Id)) - .ToList() - .ForEach(sp => + // Goes through profiles in profilegroup table. Compares to see changes in incoming profile list and removes removed profiles. + dbProfileGroup.OrderedProfiles.Where(op => !profileGroup.Profiles.Any(sp => sp.Id == op.ProfileId)) + .ToList() + .ForEach(pg => { - var pgpo = new ProfileGroupProfileOrdersEntity() - { - ProfileGroupId = dbProfileGroup.Id, - ProfileId = sp.Id, - }; - dbProfileGroup.OrderedProfiles.Add(pgpo); - }); - - int i = 0; - foreach (var p in profileGroup.Profiles.OrderBy(sp => sp.SortIndex)) + dbProfileGroup.OrderedProfiles.Remove(pg); + } + ); + + // Goes through incoming profile list. Compares to see changes in profiles in table and adds missing profiles. + profileGroup.Profiles.Where(sp => !dbProfileGroup.OrderedProfiles.Any(op => op.ProfileId == sp.Id)) + .ToList() + .ForEach(sp => { - dbProfileGroup.OrderedProfiles.Where(op => p.Id == op.ProfileId).SingleOrDefault().SortIndex = i++; - } - } - else + var pgpo = new ProfileGroupProfileOrdersEntity() + { + ProfileGroupId = dbProfileGroup.Id, + ProfileId = sp.Id, + }; + dbProfileGroup.OrderedProfiles.Add(pgpo); + }); + + int i = 0; + foreach (var p in profileGroup.Profiles.OrderBy(sp => sp.OrderIndex)) { - // New - profileGroup.Id = Guid.NewGuid(); - dbProfileGroup = Mapper.Map(profileGroup); - dbProfileGroup.OrderedProfiles = new List(); - - profileGroup.Profiles.ForEach(profile => - dbProfileGroup.OrderedProfiles.Add(new ProfileGroupProfileOrdersEntity() - { - ProfileGroupId = dbProfileGroup.Id, - ProfileId = profile.Id, - } - )); - - int i = 0; - foreach (var p in profileGroup.Profiles.OrderBy(sp => sp.SortIndex)) + var a = dbProfileGroup.OrderedProfiles.Where(op => p.Id == op.ProfileId).SingleOrDefault().SortIndexForProfileInGroup = i++; + } + } + else + { + dbProfileGroup = new ProfileGroupEntity() { Id = Guid.NewGuid() }; + + dbProfileGroup.OrderedProfiles = new List(); + + profileGroup.Profiles.ForEach(profile => + dbProfileGroup.OrderedProfiles.Add(new ProfileGroupProfileOrdersEntity() { - dbProfileGroup.OrderedProfiles.Where(op => p.Id == op.ProfileId).SingleOrDefault().SortIndex = i++; + ProfileGroupId = dbProfileGroup.Id, + ProfileId = profile.Id, } + )); - dbProfileGroup.CreatedBy = profileGroup.CreatedBy; - dbProfileGroup.CreatedOn = profileGroup.CreatedOn; - - db.ProfileGroups.Add(dbProfileGroup); + int i = 0; + foreach (var p in profileGroup.Profiles.OrderBy(sp => sp.OrderIndex)) + { + dbProfileGroup.OrderedProfiles.Where(op => p.Id == op.ProfileId).SingleOrDefault().SortIndexForProfileInGroup = i++; } - db.SaveChanges(); + dbProfileGroup.CreatedBy = profileGroup.CreatedBy; + dbProfileGroup.CreatedOn = DateTime.UtcNow; + + db.ProfileGroups.Add(dbProfileGroup); } + + dbProfileGroup.Name = profileGroup.Name; + dbProfileGroup.Description = profileGroup.Description; + dbProfileGroup.GroupSortWeight = profileGroup.GroupSortWeight; + dbProfileGroup.UpdatedBy = profileGroup.UpdatedBy; + dbProfileGroup.UpdatedOn = DateTime.UtcNow; + + db.SaveChanges(); } public void Delete(Guid id) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + var group = db.ProfileGroups.SingleOrDefault(g => g.Id == id); + if (@group != null) { - var group = db.ProfileGroups.SingleOrDefault(g => g.Id == id); - if (group != null) - { - db.ProfileGroups.Remove(group); - db.SaveChanges(); - } + db.ProfileGroups.Remove(@group); + db.SaveChanges(); } } - public void SetProfileGroupSortWeight(IList> profileTuples) + private ProfileGroup MapToProfileGroup(ProfileGroupEntity profileGroupEntity) { - using (var db = GetDbContext()) - { - foreach (var tuple in profileTuples) - { - var id = tuple.Item1; - var sortWeightIndex = tuple.Item2; + if (profileGroupEntity == null) return null; - var profile = db.ProfileGroups.SingleOrDefault(p => p.Id == id); - if (profile == null) + return new ProfileGroup + { + Id = profileGroupEntity.Id, + Name = profileGroupEntity.Name, + Description = profileGroupEntity.Description, + GroupSortWeight = profileGroupEntity.GroupSortWeight, + Profiles = profileGroupEntity.OrderedProfiles.Select(x => + new ProfileCodec { - continue; - } - - profile.GroupSortWeight = sortWeightIndex; - } - - db.SaveChanges(); - } + Id = x.Profile.Id, + Name = x.Profile.Name, + Description = x.Profile.Description, + LongDescription = x.Profile.LongDescription, + Sdp = x.Profile.Sdp, + OrderIndex = x.SortIndexForProfileInGroup + + }).OrderBy(x => x.OrderIndex).ToList(), + CreatedBy = profileGroupEntity.CreatedBy, + CreatedOn = profileGroupEntity.CreatedOn, + UpdatedBy = profileGroupEntity.UpdatedBy, + UpdatedOn = profileGroupEntity.UpdatedOn + }; } } } diff --git a/CCM.Data/Repositories/ProfileRepository.cs b/CCM.Data/Repositories/ProfileRepository.cs index 1b9ef06f..c74e25e2 100644 --- a/CCM.Data/Repositories/ProfileRepository.cs +++ b/CCM.Data/Repositories/ProfileRepository.cs @@ -29,88 +29,88 @@ using System.Data; using System.Linq; using System.Linq.Expressions; -using System.Data.Entity; using CCM.Core.Entities; using CCM.Core.Entities.Specific; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; using LazyCache; +using Microsoft.EntityFrameworkCore; namespace CCM.Data.Repositories { public class ProfileRepository : BaseRepository, IProfileRepository { - public ProfileRepository(IAppCache cache) : base(cache) + public ProfileRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } - public void Save(Profile profile) + public void Save(ProfileCodec profile) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + // Check if name already taken + bool profileNameCollision = db.Profiles.Any(p => p.Name.ToLower() == profile.Name.ToLower() && p.Id != profile.Id); + if (profileNameCollision) { - // Check if name already taken - bool profileNameCollision = db.Profiles.Any(p => p.Name.ToLower() == profile.Name.ToLower() && p.Id != profile.Id); - if (profileNameCollision) - { - throw new DuplicateNameException(); - } + throw new DuplicateNameException(); + } - ProfileEntity dbProfile; + ProfileCodecEntity dbProfile; - if (profile.Id != Guid.Empty) - { - dbProfile = db.Profiles.SingleOrDefault(p => p.Id == profile.Id); + if (profile.Id != Guid.Empty) + { + dbProfile = db.Profiles + .SingleOrDefault(p => p.Id == profile.Id); - if (dbProfile == null) - { - throw new NullReferenceException("Profile"); - } - } - else + if (dbProfile == null) { - dbProfile = new ProfileEntity() - { - Id = Guid.NewGuid(), - CreatedBy = profile.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - profile.Id = dbProfile.Id; - profile.CreatedOn = dbProfile.CreatedOn; - db.Profiles.Add(dbProfile); - dbProfile.SortIndex = db.Profiles.Any() ? db.Profiles.Max(p => p.SortIndex) + 1 : 0; - profile.SortIndex = dbProfile.SortIndex; + throw new Exception("Profile could not be found"); } + } + else + { + dbProfile = new ProfileCodecEntity + { + Id = Guid.NewGuid(), + CreatedBy = profile.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + profile.Id = dbProfile.Id; + profile.CreatedOn = dbProfile.CreatedOn; + db.Profiles.Add(dbProfile); + //dbProfile.SortIndex = db.Profiles.Any() ? db.Profiles.Max(p => p.SortIndex) + 1 : 0; + //profile.OrderIndex = dbProfile.SortIndex; + } - dbProfile.Description = profile.Description; - dbProfile.Name = profile.Name; - dbProfile.Sdp = profile.Sdp; - dbProfile.UpdatedBy = profile.UpdatedBy; - dbProfile.UpdatedOn = DateTime.UtcNow; + dbProfile.Description = profile.Description; + dbProfile.LongDescription = profile.LongDescription; + dbProfile.Name = profile.Name; + dbProfile.Sdp = profile.Sdp; + dbProfile.UpdatedBy = profile.UpdatedBy; + dbProfile.UpdatedOn = DateTime.UtcNow; - profile.UpdatedOn = dbProfile.UpdatedOn; + profile.UpdatedOn = dbProfile.UpdatedOn; - db.SaveChanges(); - } + db.SaveChanges(); } - public Profile GetById(Guid id) + public ProfileCodec GetById(Guid id) { - using (var db = GetDbContext()) - { - var profile = db.Profiles - .Include(p => p.ProfileGroups) - .Include(p => p.UserAgents.Select(o => o.UserAgent)) - .SingleOrDefault(p => p.Id == id); - return MapToProfile(profile); - } + var db = _ccmDbContext; + var profile = db.Profiles + .Include(p => p.ProfileGroups) + .ThenInclude(p => p.ProfileGroup) + .Include(p => p.UserAgents) + .ThenInclude(u => u.UserAgent) + .SingleOrDefault(p => p.Id == id); + return MapToProfileCodec(profile); } - public List GetAll() + public List GetAll() { return GetProfilesByExpression(p => true); } - public List FindProfiles(string searchString) + public List FindProfiles(string searchString) { return GetProfilesByExpression(p => p.Description.ToLower().Contains(searchString) || @@ -118,93 +118,99 @@ public List FindProfiles(string searchString) p.Sdp.ToLower().Contains(searchString)); } - private List GetProfilesByExpression(Expression> whereExpression) + private List GetProfilesByExpression(Expression> whereExpression) { - using (var db = GetDbContext()) - { - var profiles = db.Profiles - .Include(p => p.ProfileGroups) - .Include(p => p.UserAgents.Select(o => o.UserAgent)) - .Where(whereExpression) - .ToList(); + var db = _ccmDbContext; - return profiles.OrderBy(p => p.SortIndex).Select(MapToProfile).ToList(); - } + var profiles = db.Profiles + .Include(p => p.ProfileGroups) + .ThenInclude(p => p.ProfileGroup) + .Include(ua => ua.UserAgents) + .ThenInclude(o => o.UserAgent) + .Where(whereExpression) + .ToList(); + + return profiles.OrderBy(p => p.Name).Select(MapToProfileCodec).ToList(); } public IList GetAllProfileNamesAndSdp() { - using (var db = GetDbContext()) - { - var profiles = db.Profiles.OrderBy(p => p.SortIndex) - .Select(p => new ProfileNameAndSdp() {Name = p.Name, Sdp = p.Sdp}).ToList(); - return profiles; - } + var profiles = _ccmDbContext.Profiles.OrderBy(p => p.Name) + .Select(p => new ProfileNameAndSdp + { + Name = p.Name, + Sdp = p.Sdp + }).ToList(); + return profiles; } public IList GetAllProfileInfos() { - using (var db = GetDbContext()) + return _ccmDbContext.Profiles.Select(p => new ProfileInfo { - return db.Profiles.Select(p => new ProfileInfo() {Id = p.Id, Name = p.Name}).ToList(); - } + Id = p.Id, + Name = p.Name + }).ToList(); } - public void Delete(Guid id) + public IReadOnlyCollection GetFullDetails() { - using (var db = GetDbContext()) - { - var profile = db.Profiles.SingleOrDefault(p => p.Id == id); - if (profile == null) - { - return; - } - db.Profiles.Remove(profile); - - db.SaveChanges(); - } + return _ccmDbContext.Profiles + .Include(p => p.ProfileGroups) + .ThenInclude(pg => pg.ProfileGroup) + .Include(p => p.UserAgents) + .ThenInclude(ua => ua.UserAgent) + .Select(p => new ProfileFullDetail(p.Id, p.Name, p.Description, p.LongDescription, p.Sdp, p.UserAgents.Select(ua => ua.UserAgent.Name).ToList())).ToList().AsReadOnly().ToList(); } - public void SetProfileSortIndex(IList> profileTuples) + public void Delete(Guid id) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + var profile = db.Profiles + .Include(p => p.ProfileGroups) + .ThenInclude(pg => pg.ProfileGroup) + .Include(p => p.UserAgents) + .ThenInclude(ua => ua.UserAgent) + .SingleOrDefault(p => p.Id == id); + + if (profile != null) { - foreach (var tuple in profileTuples) + if (profile.ProfileGroups != null) { - var id = tuple.Item1; - var sortIndex = tuple.Item2; - - var profile = db.Profiles.SingleOrDefault(p => p.Id == id); - if (profile == null) - { - continue; - } - - profile.SortIndex = sortIndex; + profile.ProfileGroups.Clear(); + } + if (profile.UserAgents != null) + { + profile.UserAgents.Clear(); } + db.Profiles.Remove(profile); db.SaveChanges(); } } - private Profile MapToProfile(ProfileEntity dbProfile) + private ProfileCodec MapToProfileCodec(ProfileCodecEntity dbProfile) { - if (dbProfile == null) { return null; } + if (dbProfile == null) + { + return null; + } - var profile = new Profile + var profile = new ProfileCodec { - Description = dbProfile.Description, Id = dbProfile.Id, Name = dbProfile.Name, + Description = dbProfile.Description, + LongDescription = dbProfile.LongDescription, Sdp = dbProfile.Sdp, - SortIndex = dbProfile.SortIndex, + OrderIndex = -1, CreatedBy = dbProfile.CreatedBy, CreatedOn = dbProfile.CreatedOn, UpdatedBy = dbProfile.UpdatedBy, UpdatedOn = dbProfile.UpdatedOn, Groups = MapToProfileGroups(dbProfile.ProfileGroups), UserAgents = dbProfile.UserAgents == null ? new List() - : dbProfile.UserAgents.Select(oua => MapToUserAgent(oua.UserAgent)).ToList() + : dbProfile.UserAgents.Select(oua => MapToUserAgent(oua.UserAgent)).ToList() }; return profile; @@ -212,21 +218,21 @@ private Profile MapToProfile(ProfileEntity dbProfile) private ICollection MapToProfileGroups(ICollection groups) { - var l = new List(); - - foreach (var group in groups) + var profileGroupInfos = groups.Select(x => + new ProfileGroupInfo { - l.Add(AutoMapper.Mapper.Map(group.ProfileGroup)); - } + Name = x.ProfileGroup.Name, + Description = x.ProfileGroup.Description, + GroupSortWeight = x.ProfileGroup.GroupSortWeight + }).ToList(); - return l; + return profileGroupInfos; } private static UserAgent MapToUserAgent(UserAgentEntity userAgent) { - return userAgent == null ? null : new UserAgent() + return userAgent == null ? null : new UserAgent { - Ax = userAgent.Ax, Height = userAgent.Height, Id = userAgent.Id, Identifier = userAgent.Identifier, @@ -236,14 +242,8 @@ private static UserAgent MapToUserAgent(UserAgentEntity userAgent) UserInterfaceLink = userAgent.UserInterfaceLink, Width = userAgent.Width, Api = userAgent.Api, - Lines = userAgent.Lines, - Inputs = userAgent.Inputs, - NrOfGpos = userAgent.NrOfGpos, - InputMinDb = userAgent.MinInputDb, - InputMaxDb = userAgent.MaxInputDb, Comment = userAgent.Comment }; } - } } diff --git a/CCM.Data/Repositories/RegionRepository.cs b/CCM.Data/Repositories/RegionRepository.cs index 7bf76499..4da9d056 100644 --- a/CCM.Data/Repositories/RegionRepository.cs +++ b/CCM.Data/Repositories/RegionRepository.cs @@ -28,7 +28,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; @@ -38,120 +38,113 @@ namespace CCM.Data.Repositories { public class RegionRepository : BaseRepository, IRegionRepository { - public RegionRepository(IAppCache cache) : base(cache) + public RegionRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public void Save(Region region) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + RegionEntity dbRegion; + var timeStamp = DateTime.UtcNow; + + if (region.Id != Guid.Empty) { - RegionEntity dbRegion; - var timeStamp = DateTime.UtcNow; + dbRegion = db.Regions + .Include(r => r.Locations) + .SingleOrDefault(g => g.Id == region.Id); - if (region.Id != Guid.Empty) + if (dbRegion == null) { - dbRegion = db.Regions.SingleOrDefault(g => g.Id == region.Id); - - if (dbRegion == null) - { - throw new Exception("Region could not be found"); - } - - dbRegion.Locations.Clear(); + throw new Exception("Region could not be found"); } - else + + dbRegion.Locations?.Clear(); + } + else + { + dbRegion = new RegionEntity { - dbRegion = new RegionEntity - { - Id = Guid.NewGuid(), - CreatedBy = region.CreatedBy, - CreatedOn = timeStamp, - Locations = new Collection() - }; - - region.Id = dbRegion.Id; - region.CreatedOn = dbRegion.CreatedOn; - db.Regions.Add(dbRegion); - } + Id = Guid.NewGuid(), + CreatedBy = region.CreatedBy, + CreatedOn = timeStamp, + Locations = new Collection() + }; + + region.Id = dbRegion.Id; + region.CreatedOn = dbRegion.CreatedOn; + db.Regions.Add(dbRegion); + } - dbRegion.Name = region.Name; - dbRegion.UpdatedBy = region.UpdatedBy; - dbRegion.UpdatedOn = timeStamp; - region.UpdatedOn = dbRegion.UpdatedOn; + dbRegion.Name = region.Name; + dbRegion.UpdatedBy = region.UpdatedBy; + dbRegion.UpdatedOn = timeStamp; - // Add relations - foreach (var location in region.Locations) + // Add relations + foreach (var location in region.Locations) + { + var dbLocation = db.Locations.SingleOrDefault(l => l.Id == location.Id); + if (dbLocation != null) { - var dbLocation = db.Locations.SingleOrDefault(l => l.Id == location.Id); - if (dbLocation != null) - { - dbRegion.Locations.Add(dbLocation); - } + dbRegion.Locations?.Add(dbLocation); } - - db.SaveChanges(); } + + db.SaveChanges(); } public void Delete(Guid id) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + var dbRegion = db.Regions + .Include(r => r.Locations) + .SingleOrDefault(g => g.Id == id); + if (dbRegion != null) { - var dbRegion = db.Regions.SingleOrDefault(g => g.Id == id); - if (dbRegion != null) + if (dbRegion.Locations != null) { dbRegion.Locations.Clear(); - - db.Regions.Remove(dbRegion); - db.SaveChanges(); } + + db.Regions.Remove(dbRegion); + db.SaveChanges(); } } public Region GetById(Guid id) { - using (var db = GetDbContext()) - { - var dbRegion = db.Regions - .Include(r => r.Locations) - .SingleOrDefault(g => g.Id == id); - return MapToRegion(dbRegion, true); - } + var db = _ccmDbContext; + var dbRegion = db.Regions + .Include(r => r.Locations) + .SingleOrDefault(g => g.Id == id); + return MapToRegion(dbRegion, true); } public List GetAll() { - using (var db = GetDbContext()) - { - var dbRegions = db.Regions - .Include(r => r.Locations) - .ToList(); - return dbRegions.Select(o => MapToRegion(o, true)).OrderBy(g => g.Name).ToList(); - } + var db = _ccmDbContext; + var dbRegions = db.Regions + .Include(r => r.Locations) + .ToList(); + return dbRegions.Select(o => MapToRegion(o, true)).OrderBy(g => g.Name).ToList(); } public List FindRegions(string search) { - using (var db = GetDbContext()) - { - var dbRegions = db.Regions - .Include(r => r.Locations) - .Where(r => r.Name.ToLower().Contains(search)) - .ToList(); - return dbRegions.Select(o => MapToRegion(o, true)).OrderBy(g => g.Name).ToList(); - } + var db = _ccmDbContext; + var dbRegions = db.Regions + .Include(r => r.Locations) + .Where(r => r.Name.ToLower().Contains(search)) + .ToList(); + return dbRegions.Select(o => MapToRegion(o, true)).OrderBy(g => g.Name).ToList(); } public List GetAllRegionNames() { - using (var db = GetDbContext()) - { - return db.Regions.Select(o => o.Name).OrderBy(g => g).ToList(); - } + return _ccmDbContext.Regions.Select(o => o.Name).OrderBy(g => g).ToList(); } - private Region MapToRegion(Entities.RegionEntity dbRegion, bool includeLocations) + private Region MapToRegion(RegionEntity dbRegion, bool includeLocations) { if (dbRegion == null) return null; @@ -167,16 +160,16 @@ private Region MapToRegion(Entities.RegionEntity dbRegion, bool includeLocations }; } - public static Location MapToLocation(LocationEntity dbLocation) + private Location MapToLocation(LocationEntity dbLocation) { if (dbLocation == null) return null; return new Location { - Cidr = dbLocation.Cidr, Id = dbLocation.Id, Name = dbLocation.Name, Net = dbLocation.Net_Address_v4, + Cidr = dbLocation.Cidr, CreatedBy = dbLocation.CreatedBy, CreatedOn = dbLocation.CreatedOn, UpdatedBy = dbLocation.UpdatedBy, diff --git a/CCM.Data/Repositories/RegisteredCodecDetailsRepository.cs b/CCM.Data/Repositories/RegisteredCodecDetailsRepository.cs new file mode 100644 index 00000000..33188463 --- /dev/null +++ b/CCM.Data/Repositories/RegisteredCodecDetailsRepository.cs @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using CCM.Core.Entities.Specific; +using CCM.Core.Interfaces.Repositories; +using CCM.Data.Entities; +using LazyCache; + +namespace CCM.Data.Repositories +{ + /// + /// Used by SIP info details for frontpage + /// + public class RegisteredCodecDetailsRepository : BaseRepository, IRegisteredCodecDetailsRepository + { + public RegisteredCodecDetailsRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) + { + } + + public RegisteredSipDetails GetRegisteredSipById(Guid id) + { + RegisteredCodecEntity dbCodec = _ccmDbContext.RegisteredCodecs + .Include(rs => rs.Location) + .Include(rs => rs.Location.City) + .Include(rs => rs.Location.Region) + .Include(rs => rs.UserAgent) + .Include(rs => rs.User) + .SingleOrDefault(r => r.Id == id); + + return MapToRegisteredSipDetails(dbCodec); + } + + private RegisteredSipDetails MapToRegisteredSipDetails(RegisteredCodecEntity rs) + { + if (rs == null) + { + return null; + } + + var model = new RegisteredSipDetails + { + Id = rs.Id, + Sip = rs.SIP, + DisplayName = rs.DisplayName, + Ip = rs.IP, + UserAgentHeader = rs.UserAgentHeader, + Registrar = rs.Registrar ?? string.Empty, + UserExternalReference = rs.User?.ExternalReference ?? string.Empty, + + Comment = rs.User?.Comment ?? string.Empty, + UserDisplayName = rs.User?.DisplayName ?? string.Empty, + Api = rs.UserAgent?.Api ?? string.Empty, + Image = rs.UserAgent?.Image ?? string.Empty, + Width = rs.UserAgent?.Width ?? 1000, + Height = rs.UserAgent?.Height ?? 1000, + UserInterfaceLink = rs.UserAgent?.UserInterfaceLink ?? string.Empty, + UserInterfaceIsOpen = rs.UserAgent?.UserInterfaceIsOpen ?? false, + UseScrollbars = rs.UserAgent?.UseScrollbars ?? false, + + UserAgentName = rs.UserAgent?.Name ?? string.Empty, + LocationName = rs.Location?.Name ?? string.Empty, + LocationComment = rs.Location?.Comment ?? string.Empty, + CityName = rs.Location?.City?.Name ?? string.Empty, + RegionName = rs.Location?.Region.Name ?? string.Empty, + }; + + return model; + } + } +} diff --git a/CCM.Data/Repositories/RegisteredCodecRepository.cs b/CCM.Data/Repositories/RegisteredCodecRepository.cs new file mode 100644 index 00000000..a4bc178c --- /dev/null +++ b/CCM.Data/Repositories/RegisteredCodecRepository.cs @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Microsoft.EntityFrameworkCore; +using CCM.Core.Entities; +using CCM.Core.Entities.Registration; +using CCM.Core.Enums; +using CCM.Core.Helpers; +using CCM.Core.Interfaces.Managers; +using CCM.Core.Interfaces.Repositories; +using CCM.Core.SipEvent.Models; +using CCM.Data.Entities; +using LazyCache; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.Extensions.Logging; + +namespace CCM.Data.Repositories +{ + /// + /// Handles Registered User-Agents database / cache operations + /// + public class RegisteredCodecRepository : BaseRepository, IRegisteredCodecRepository + { + private readonly ILogger _logger; + + private readonly IMetaRepository _metaRepository; + private readonly ICachedUserAgentRepository _cachedUserAgentRepository; + private readonly ICachedSipAccountRepository _cachedSipAccountRepository; + private readonly ILocationManager _locationManager; + private readonly ISettingsManager _settingsManager; + + public RegisteredCodecRepository( + ISettingsManager settingsManager, + ILocationManager locationManager, + IMetaRepository metaRepository, + ICachedSipAccountRepository cachedSipAccountRepository, + ICachedUserAgentRepository cachedUserAgentRepository, + ILogger logger, + IAppCache cache, + CcmDbContext ccmDbContext) : base(cache, ccmDbContext) + { + _metaRepository = metaRepository; + _cachedUserAgentRepository = cachedUserAgentRepository; + _cachedSipAccountRepository = cachedSipAccountRepository; + _locationManager = locationManager; + _settingsManager = settingsManager; + _logger = logger; + } + + public SipEventHandlerResult UpdateRegisteredSip(UserAgentRegistration registration) + { + // Return value indicates if + // 1. Codec been added + // 2. Codec existed but registration has relevant changes + // 3. Codec existed and registration is identical = NothingChanged + + var isNewRegistration = false; + + try + { + var db = _ccmDbContext; + var dbSip = db.RegisteredCodecs + //.Include(rs => rs.Location) + //.Include(rs => rs.Location.Region) + //.Include(rs => rs.Location.City) + // .Include(rs => rs.User) + //.Include(rs => rs.User.Owner) + //.Include(rs => rs.User.CodecType) + //.Include(rs => rs.UserAgent) + .FirstOrDefault(rs => rs.SIP == registration.SipUri); + + // Is it a new registration? + if (dbSip == null) + { + isNewRegistration = true; + if (registration.ExpirationTimeSeconds == 0) + { + // Unregistration of not registered user-agent. Do nothing. + _logger.LogDebug($"User-agent nothing changed, unregistration of not registered user-agent '{registration.SipUri}'"); + return SipEventHandlerResult.NothingChanged; + } + + // New registration of user-agent + dbSip = new RegisteredCodecEntity + { + Id = Guid.NewGuid() + }; + db.RegisteredCodecs.Add(dbSip); + } + + // Match and map + var userAgentId = GetUserAgentId(registration.UserAgentHeader); + dbSip.UserAgentId = userAgentId; + dbSip.UserAgentHeader = registration.UserAgentHeader; + + var locationId = _locationManager.GetLocationIdByIp(registration.IpAddress); + dbSip.Location_LocationId = locationId != Guid.Empty ? locationId : (Guid?)null; + + var registeredSipUsername = registration.Username.ToLower().Trim(); + dbSip.Username = registeredSipUsername; + var sipAccount = _cachedSipAccountRepository.GetSipAccountByUserName(registeredSipUsername); + dbSip.User_UserId = sipAccount?.Id; + if (isNewRegistration && sipAccount != null) { + var dbUser = db.SipAccounts.FirstOrDefault(rs => rs.Id == sipAccount.Id); + // Log to SIP account that it has been used + dbUser.LastUsed = DateTime.UtcNow; + dbUser.LastKnownAddress = registration.IpAddress; + dbUser.LastUserAgent = registration.UserAgentHeader; + } + dbSip.SIP = registration.SipUri; + dbSip.DisplayName = registration.DisplayName; + dbSip.IP = registration.IpAddress; + dbSip.Port = registration.Port; + dbSip.ServerTimeStamp = registration.ServerTimeStamp; + dbSip.Expires = registration.ExpirationTimeSeconds; + dbSip.Registrar = registration.Registrar; + dbSip.Updated = DateTime.UtcNow; + + var changeStatus = GetChangeStatus(db, dbSip); + + // SaveChanges(false) tells the EF to execute the necessary database commands, but hold on to the changes, so they can be replayed if necessary. + // If you call SaveChanges() or SaveChanges(true),the EF simply assumes that if its work completes okay, everything is okay, so it will discard the changes it has been tracking, and wait for new changes. + db.SaveChanges(true); + + //db.Dispose(); 2021 after issues... + return new SipEventHandlerResult + { + ChangeStatus = changeStatus, + ChangedObjectId = dbSip.Id, + SipAddress = dbSip.SIP + }; + } + catch (Exception ex) + { + _logger.LogError($"Error while updating registered sip {ex.Message}"); + _logger.LogError(ex, "Error while updating registered sip {0}", registration.SipUri); + return SipEventHandlerResult.NothingChanged; + } + } + + public SipEventHandlerResult DeleteRegisteredSip(string sipAddress) + { + if (string.IsNullOrEmpty(sipAddress)) + { + _logger.LogDebug("User-agent nothing changed, delete registered user-agent is empty"); + return SipEventHandlerResult.NothingChanged; + } + + sipAddress = sipAddress.ToLower(); + + try + { + var db = _ccmDbContext; + // Registrations should be unique based on sipAddress, but to be safe we don't assume this. + var dbSips = db.RegisteredCodecs.Where(rs => rs.SIP == sipAddress) + .OrderByDescending(rs => rs.Updated); + + if (!dbSips.Any()) + { + _logger.LogError($"User-agent nothing changed, could not delete user-agent that's not registered {sipAddress}"); + return new SipEventHandlerResult + { + ChangeStatus = SipEventChangeStatus.NothingChanged, + SipAddress = sipAddress + }; + } + + var changedObjectId = dbSips.FirstOrDefault()?.Id ?? Guid.Empty; + db.RegisteredCodecs.RemoveRange(dbSips); + db.SaveChanges(); + + _logger.LogDebug($"User-agent removed '{sipAddress}'"); + return new SipEventHandlerResult + { + ChangeStatus = SipEventChangeStatus.CodecRemoved, + ChangedObjectId = changedObjectId, + SipAddress = sipAddress + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while unregistering codec with sip address {0}", sipAddress); + return SipEventHandlerResult.NothingChanged; + } + } + + private SipEventChangeStatus GetChangeStatus(DbContext cxt, RegisteredCodecEntity dbCodec) + { + var entry = cxt.Entry(dbCodec); + + //_logger.LogDebug($"UPDATE_: SIP: {dbCodec.SIP} STATE {entry.State} {dbCodec.Id} (SAVING_)"); + + if (entry.State == EntityState.Added) + { + _logger.LogDebug($"User-agent added '{dbCodec.SIP}'"); + return SipEventChangeStatus.CodecAdded; + } + + if (entry.State == EntityState.Deleted) + { + _logger.LogDebug($"User-agent deleted '{dbCodec.SIP}'"); + return SipEventChangeStatus.CodecRemoved; + } + + if (entry.State == EntityState.Modified && dbCodec.Expires == 0) + { + _logger.LogDebug($"User-agent expired '{dbCodec.SIP}'"); + return SipEventChangeStatus.CodecRemoved; + } + + if (entry.State == EntityState.Modified && HasRelevantChange(entry)) + { + _logger.LogDebug($"User-agent updated, relevant changes '{dbCodec.SIP}'"); + return SipEventChangeStatus.CodecUpdated; + } + + _logger.LogDebug($"User-agent nothing changed '{dbCodec.SIP}'"); + return SipEventChangeStatus.NothingChanged; + } + + /// + /// Checks if the updating data, should be used to also trigger cache reload. + /// Makes sure change has been done to database fields that we are interested in. + /// Since SaveChanges triggers a full reload of the cache. + /// + private bool HasRelevantChange(EntityEntry entry) // TODO: check new implementation of DbEntityEntry not same as EntityEntry + { + var changedProperties = GetChangedProperties(entry); + + // Remove non-relevant properties + changedProperties.Remove(nameof(entry.Entity.Updated)); + changedProperties.Remove(nameof(entry.Entity.ServerTimeStamp)); + changedProperties.Remove(nameof(entry.Entity.Expires)); + changedProperties.Remove(nameof(entry.Entity.User.LastUsed)); + + return changedProperties.Any(); + } + + private IList GetChangedProperties(EntityEntry entity) // TODO: check new implementation of DbEntityEntry not same as EntityEntry + { + if (entity.State != EntityState.Modified) { + return new List(); + } + + // The OriginalValues are the property values 'as' they were when the entity was retrieved from the database + var entityType = entity.Entity.GetType(); + + var properties = entityType.GetProperties(); + var props = new List(); + foreach (var prop in properties) + { + if (entity.Metadata.FindProperty(prop.Name) == null) + continue; + + var p = entity.Property(prop.Name); + if (p.IsModified) + { + props.Add(prop.Name); + } + } + return props; + } + + public IEnumerable GetRegisteredUserAgentsDiscovery() + { + DateTime maxAge = DateTime.UtcNow.AddSeconds(-_settingsManager.MaxRegistrationAge); + + // Get available meta data properties + List metaList = _metaRepository.GetAll(); + + IEnumerable dbSip = _ccmDbContext.RegisteredCodecs + .Include(rs => rs.Location) + .Include(rs => rs.Location.Region) + .Include(rs => rs.Location.City) + .Include(rs => rs.User) + .Include(rs => rs.User.Owner) + .Include(rs => rs.User.CodecType) + .Include(rs => rs.UserAgent) + .Where(r => r.Updated >= maxAge) + .ToList(); + + return dbSip.Select(x => new RegisteredUserAgentDiscovery( + id: x.Id, + updated: x.Updated, + sipUri: x.SIP, + displayName: x.DisplayName, + ipAddress: x.IP, + userAgentHeader: x.UserAgentHeader, + userAgentId: x.UserAgentId, + userAgentName: x.UserAgent?.Name, + locationId: x.Location_LocationId, + locationName: x.Location?.Name, + locationShortName: x.Location?.ShortName, + regionName: x.Location?.Region?.Name, + cityName: x.Location?.City?.Name, + userOwnerName: x.User?.Owner?.Name, + userDisplayName: x.User?.DisplayName, + codecTypeName: x.User?.CodecType?.Name, + metaData: GetMetaData(metaList, x))) + .ToList(); + } + + public IEnumerable GetRegisteredUserAgents() + { + DateTime maxAge = DateTime.UtcNow.AddSeconds(-_settingsManager.MaxRegistrationAge); + + var result = _ccmDbContext.RegisteredCodecs + .Include(rs => rs.Location) + .ThenInclude(l => l.Region) + .Include(c => c.Location.Category) + .Include(rs => rs.UserAgent) + .ThenInclude(ca => ca.Category) + .Include(rs => rs.User) + .ThenInclude(u => u.CodecType) + .Where(x => x.Updated >= maxAge) + .Select(x => + new + { + SIP = x.SIP, + Id = x.Id, + DisplayName = x.DisplayName, + LocationName = x.Location.Name, + LocationShortName = x.Location.ShortName, + LocationCategory = x.Location.Category.Name, + Image = x.UserAgent.Image, + CodecTypeName = x.User.CodecType.Name, + CodecTypeColor = x.User.CodecType.Color, + CodecTypeCategory = x.UserAgent.Category.Name, + CodecApi = x.UserAgent.Api, + UserExternalReference = x.User.ExternalReference, + UserDisplayName = x.User.DisplayName, + UserComment = x.User.Comment, + RegionName = x.Location.Region.Name + }) + .ToList(); + + return result.Select(x => new RegisteredUserAgent( + sipUri: x.SIP, + id: x.Id, + displayName: x.DisplayName, + location: x.LocationName, + locationShortName: x.LocationShortName, + locationCategory: x.LocationCategory, + image: x.Image, + codecTypeName: x.CodecTypeName, + codecTypeColor: x.CodecTypeColor, + codecTypeCategory: x.CodecTypeCategory, + userExternalReference: x.UserExternalReference, + userDisplayName: x.UserDisplayName, + userComment: x.UserComment, + regionName: x.RegionName, + codecApi: x.CodecApi)) + .ToList(); + } + + private List> GetMetaData(List metaList, RegisteredCodecEntity codec) + { + metaList ??= new List(); + + var userAgentMetaDataList = metaList + .Select(meta => + new KeyValuePair(meta.Name, + MetadataHelper.GetPropertyValue(codec, meta.FullPropertyName))) + .Where(m => !string.IsNullOrEmpty(m.Value)) + .ToList(); + + return userAgentMetaDataList; + } + + private Guid? GetUserAgentId(string userAgentHeader) + { + // TODO: solve this + userAgentHeader = (userAgentHeader ?? string.Empty).Trim(); + + // Get user agents and their identifiers, sort and match on the longest identifier length so it's not the wildcard that catches them all + var allUserAgents = _cachedUserAgentRepository.GetAll() + .Where(ua => !string.IsNullOrEmpty(ua.Identifier)) + .Select(ua => new UserAgentInfo( + userAgentId: ua.Id, + identifier: ua.Identifier, + matchType: ua.MatchType + )) + .OrderByDescending(ua => ua.Identifier.Length) + .ThenBy(ua => ua.Identifier).ToList(); + + //_logger.LogDebug($"UA Indata {userAgentHeader}"); + //foreach (var uaAgent in allUserAgents) + //{ + // _logger.LogInformation($"UA Match {uaAgent.Identifier} {uaAgent.MatchType}"); + //} + + //var dbUserAgent = allUserAgents.FirstOrDefault(u => + // u.MatchType == UserAgentPatternMatchType.Begins_With && userAgentHeader.StartsWith(u.Identifier)); + + //if (dbUserAgent != null) + //{ + // _logger.LogInformation($"UA Match => {dbUserAgent.Identifier} {dbUserAgent.MatchType} on {userAgentHeader}"); + // return dbUserAgent.UserAgentId; + //} + + //dbUserAgent = allUserAgents.FirstOrDefault(u => + // u.MatchType == UserAgentPatternMatchType.Ends_With && userAgentHeader.EndsWith(u.Identifier)); + + //if (dbUserAgent != null) + //{ + // _logger.LogInformation($"UA Match => {dbUserAgent.Identifier} {dbUserAgent.MatchType} on {userAgentHeader}"); + // return dbUserAgent.UserAgentId; + //} + + var dbUserAgent = allUserAgents.FirstOrDefault(u => + { + if (u.MatchType == UserAgentPatternMatchType.Regular_Expression) + { + Match m = Regex.Match(userAgentHeader, u.Identifier, RegexOptions.IgnoreCase); + if (m.Success) + { + _logger.LogDebug($"UA Found '{m.Value}' at position {m.Index}."); + return true; + } + } + return false; + }); + + if (dbUserAgent != null) + { + //_logger.LogDebug($"UA Match {dbUserAgent.MatchType} => {dbUserAgent.Identifier} on {userAgentHeader}"); + return dbUserAgent.UserAgentId; + } + + dbUserAgent = allUserAgents.FirstOrDefault(u => + u.MatchType != UserAgentPatternMatchType.Regular_Expression && userAgentHeader.Contains(u.Identifier)); + + //_logger.LogDebug($"UA Match {dbUserAgent?.MatchType} => {dbUserAgent?.Identifier} on {userAgentHeader}"); + + return dbUserAgent?.UserAgentId; + } + + public IEnumerable GetRegisteredUserAgentsCodecInformation() + { + // TODO: This could maybe be built up in a manager for external api codec information + DateTime maxAge = DateTime.UtcNow.AddSeconds(-_settingsManager.MaxRegistrationAge); + + try + { + var db = _ccmDbContext; + var result = db.RegisteredCodecs + .Where(x => !string.IsNullOrEmpty(x.UserAgent.Api)) + .Where(x => x.Updated >= maxAge) + .Select(x => + new + { + Sip = x.SIP, + Ip = x.IP, + UserAgentApi = x.UserAgent.Api, + UserAgentRaw = x.UserAgentHeader + }) + .ToList(); + + // Only include latest registrations per sip address + var groupBy = result.GroupBy(x => x.Sip).ToList(); + var groupedList = groupBy.Select(g => g.First()) + .OrderBy(rs => rs.Sip) + .ToList(); + + return groupedList.Select(x => new RegisteredUserAgentCodecInformation( + sipAddress: x.Sip, + ip: x.Ip, + api: x.UserAgentApi, + userAgent: x.UserAgentRaw)).ToList(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Problem when returning GetRegisteredUserAgentsCodecInformation"); + return null; + } + } + + public IEnumerable GetRegisteredCodecsUpdateTimes() + { + var result = _ccmDbContext.RegisteredCodecs + //.AsNoTracking() + .Select(x => + new + { + Id = x.Id, + Sip = x.SIP, + Ip = x.IP, + Expires = x.Expires, + ServerTimeStamp = x.ServerTimeStamp, + Updated = x.Updated + }) + .ToList(); + return result.Select(x => new RegisteredUserAgentMiniInformation( + id: x.Id, + sip: x.Sip, + expires: x.Expires, + serverTimeStamp: x.ServerTimeStamp, + updated: x.Updated)).ToList(); + } + } +} diff --git a/CCM.Data/Repositories/RegisteredSipDetailsRepository.cs b/CCM.Data/Repositories/RegisteredSipDetailsRepository.cs deleted file mode 100644 index dd40b290..00000000 --- a/CCM.Data/Repositories/RegisteredSipDetailsRepository.cs +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data.Entity; -using System.Linq; -using CCM.Core.Entities; -using CCM.Core.Entities.Specific; -using CCM.Core.Interfaces.Repositories; -using LazyCache; - -namespace CCM.Data.Repositories -{ - // TODO: This one seems to not be in use.. or am I wrong? - public class RegisteredSipDetailsRepository : BaseRepository, IRegisteredSipDetailsRepository - { - public RegisteredSipDetailsRepository(IAppCache cache) : base(cache) - { - } - - public RegisteredSipDetails GetRegisteredSipById(Guid id) - { - using (var db = GetDbContext()) - { - Entities.RegisteredSipEntity dbSip = db.RegisteredSips - .Include(rs => rs.Location) - .Include(rs => rs.Location.City) - .Include(rs => rs.Location.Region) - .Include(rs => rs.UserAgent) - .Include(rs => rs.User) - .SingleOrDefault(r => r.Id == id); - - return MapToRegisteredSipDetails(dbSip); - } - } - - private RegisteredSipDetails MapToRegisteredSipDetails(Entities.RegisteredSipEntity rs) - { - if (rs == null) - { - return null; - } - - var model = new RegisteredSipDetails - { - Id = rs.Id, - Sip = rs.SIP, - DisplayName = rs.DisplayName, - Ip = rs.IP, - UserAgentHeader = rs.UserAgentHeader, - Registrar = rs.Registrar != null ? rs.Registrar : string.Empty, - - Comment = rs.User != null ? rs.User.Comment : string.Empty, - UserDisplayName = rs.User != null ? rs.User.DisplayName : string.Empty, - Api = rs.UserAgent != null ? rs.UserAgent.Api ?? string.Empty : string.Empty, - Image = rs.UserAgent?.Image ?? string.Empty, - ActiveX = rs.UserAgent != null && rs.UserAgent.Ax, - Width = rs.UserAgent?.Width ?? 1000, - Height = rs.UserAgent?.Height ?? 1000, - UserInterfaceLink = rs.UserAgent != null ? rs.UserAgent.UserInterfaceLink ?? "" : String.Empty, - UserInterfaceIsOpen = rs.UserAgent != null && rs.UserAgent.UserInterfaceIsOpen, - UseScrollbars = rs.UserAgent != null && rs.UserAgent.UseScrollbars, - Inputs = rs.UserAgent?.Inputs ?? 0, - NrOfGpos = rs.UserAgent?.NrOfGpos ?? 0, - InputGainStep = rs.UserAgent?.InputGainStep ?? 0, - InputMaxDb = rs.UserAgent?.MaxInputDb ?? 0, - InputMinDb = rs.UserAgent?.MinInputDb ?? 0, - Lines = rs.UserAgent?.Lines ?? 0, - - CodecPresets = rs.UserAgent != null ? rs.UserAgent.CodecPresets.Select(MapToCodecPreset).ToList() : new List(), - - LocationName = rs.Location != null ? rs.Location.Name : string.Empty, - LocationComment = rs.Location != null ? rs.Location.Comment : string.Empty, - CityName = rs.Location?.City != null ? rs.Location.City.Name : string.Empty, - RegionName = rs.Location?.Region != null ? rs.Location.Region.Name : string.Empty, - }; - - return model; - } - - private CodecPreset MapToCodecPreset(Entities.CodecPresetEntity codecPreset) - { - return new CodecPreset() - { - Id = codecPreset.Id, - Name = codecPreset.Name - }; - } - - } -} diff --git a/CCM.Data/Repositories/RegisteredSipRepository.cs b/CCM.Data/Repositories/RegisteredSipRepository.cs deleted file mode 100644 index 436aaa07..00000000 --- a/CCM.Data/Repositories/RegisteredSipRepository.cs +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data.Entity; -using System.Data.Entity.Infrastructure; -using System.Linq; -using System.Linq.Expressions; -using CCM.Core.Entities; -using CCM.Core.Entities.Registration; -using CCM.Core.Enums; -using CCM.Core.Helpers; -using CCM.Core.Interfaces.Managers; -using CCM.Core.Interfaces.Repositories; -using CCM.Core.SipEvent; -using CCM.Data.Entities; -using LazyCache; -using NLog; - -namespace CCM.Data.Repositories -{ - /// - /// Handles Registered User-Agents database / cache operations - /// - public class RegisteredSipRepository : BaseRepository, IRegisteredSipRepository - { - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - - private readonly IMetaRepository _metaRepository; - private readonly IUserAgentRepository _userAgentRepository; - private readonly ISipAccountManager _sipAccountManager; - public ILocationManager LocationManager { get; set; } // TODO: Set like this? - public ISettingsManager SettingsManager { get; set; } - - public RegisteredSipRepository( - ISettingsManager settingsManager, - ILocationManager locationManager, - IMetaRepository metaRepository, - IUserAgentRepository userAgentRepository, - ISipAccountManager sipAccountManager, - IAppCache cache) - : base(cache) - { - _metaRepository = metaRepository; - _userAgentRepository = userAgentRepository; - _sipAccountManager = sipAccountManager; - LocationManager = locationManager; - SettingsManager = settingsManager; - } - - public SipEventHandlerResult UpdateRegisteredSip(UserAgentRegistration registration) - { - // Return value indicates if - // 1. Codec been added - // 2. Codec existed but registration has relevant changes - // 3. Codec existed and registration is identical = NothingChanged - - try - { - using (var db = GetDbContext()) - { - var dbSip = db.RegisteredSips.SingleOrDefault(rs => rs.SIP == registration.SipUri); - // Is it a new registration? - if (dbSip == null) - { - if (registration.ExpirationTimeSeconds == 0) - { - // Unregistration of not registered user-agent. Do nothing. - log.Debug($"User-agent nothing changed, unregistration of not registered user-agent '{registration.SipUri}'"); - return SipEventHandlerResult.NothingChanged; - } - - // New registration of user-agent - dbSip = new RegisteredSipEntity { Id = Guid.NewGuid() }; - db.RegisteredSips.Add(dbSip); - } - - // Match and map - var userAgentId = GetUserAgentId(registration.UserAgentHeader); - dbSip.UserAgentId = userAgentId; - dbSip.UserAgentHeader = registration.UserAgentHeader; - - var locationId = LocationManager.GetLocationIdByIp(registration.IpAddress); - dbSip.Location_LocationId = locationId != Guid.Empty ? locationId : (Guid?) null; - - var registeredSipUsername = registration.Username.ToLower().Trim(); - dbSip.Username = registeredSipUsername; - - // TODO: Cache test - //var sipAccount = db.SipAccounts.FirstOrDefault(u => u.UserName.ToLower() == registeredSipUsername); - var sipAccount = _sipAccountManager.GetSipAccountByUserName(registeredSipUsername); - dbSip.User_UserId = sipAccount?.Id; - - dbSip.SIP = registration.SipUri; - dbSip.DisplayName = registration.DisplayName; - dbSip.IP = registration.IpAddress; - dbSip.Port = registration.Port; - dbSip.ServerTimeStamp = registration.ServerTimeStamp; - dbSip.Updated = DateTime.UtcNow; - dbSip.Expires = registration.ExpirationTimeSeconds; - dbSip.Registrar = registration.Registrar; - - var changeStatus = GetChangeStatus(db, dbSip); - db.SaveChanges(); - - return new SipEventHandlerResult - { - ChangeStatus = changeStatus, - ChangedObjectId = dbSip.Id, - SipAddress = dbSip.SIP - }; - } - } - catch (Exception ex) - { - log.Error(ex, "Error while updating registered sip {0}", registration.SipUri); - return SipEventHandlerResult.NothingChanged; - } - } - - public SipEventHandlerResult DeleteRegisteredSip(string sipAddress) - { - if (string.IsNullOrEmpty(sipAddress)) - { - log.Debug("User-agent nothing changed, delete registered user-agent is empty"); - return SipEventHandlerResult.NothingChanged; - } - - sipAddress = sipAddress.ToLower(); - - try - { - using (var db = GetDbContext()) - { - // Registrations should be unique based on sipAddress, - // but to be safe we don't assume this. - var dbSips = db.RegisteredSips.Where(rs => rs.SIP == sipAddress) - .OrderByDescending(rs => rs.Updated); - - if (!dbSips.Any()) - { - log.Error("User-agent nothing changed, could not delete user-agent that's not registered"); - return new SipEventHandlerResult - { - ChangeStatus = SipEventChangeStatus.NothingChanged, - SipAddress = sipAddress - }; - } - - var changedObjectId = dbSips.FirstOrDefault()?.Id ?? Guid.Empty; - db.RegisteredSips.RemoveRange(dbSips); - db.SaveChanges(); - - log.Debug($"User-agent removed '{sipAddress}'"); - return new SipEventHandlerResult - { - ChangeStatus = SipEventChangeStatus.CodecRemoved, - ChangedObjectId = changedObjectId, - SipAddress = sipAddress - }; - } - } - catch (Exception ex) - { - log.Error(ex, "Error while unregistering codec with sip address {0}", sipAddress); - return SipEventHandlerResult.NothingChanged; - } - } - - private SipEventChangeStatus GetChangeStatus(DbContext cxt, RegisteredSipEntity dbSip) - { - var entry = cxt.Entry(dbSip); - - if (entry.State == EntityState.Added) - { - log.Debug($"User-agent added '{dbSip.SIP}'"); - return SipEventChangeStatus.CodecAdded; - } - - if (entry.State == EntityState.Deleted || CodecWasExpired(entry)) - { - // There is a problem here, CodecWasExpired just tells us that it was expired when a new registration is sent. Since this is not checked anywhere else - log.Debug($"User-agent expired or deleted '{dbSip.SIP}', CodecWasExpired={CodecWasExpired(entry)}, Entry.State={entry.State.ToString()}, Expires={dbSip.Expires}"); - return SipEventChangeStatus.CodecRemoved; - } - - if (entry.State == EntityState.Modified && dbSip.Expires == 0) - { - log.Error($"User-agent removed, expired '{dbSip.SIP}', this should not happen"); - return SipEventChangeStatus.CodecRemoved; - } - - if (entry.State == EntityState.Modified && HasRelevantChange(entry)) - { - log.Debug($"User-agent updated, relevant changes '{dbSip.SIP}'"); - return SipEventChangeStatus.CodecUpdated; - } - - log.Debug($"User-agent nothing changed '{dbSip.SIP}'"); - return SipEventChangeStatus.NothingChanged; - } - - /// - /// Returns true if registration time expired - /// - private bool CodecWasExpired(DbEntityEntry entry) - { - var maxRegistrationAge = SettingsManager.MaxRegistrationAge; - var expireTime = DateTime.UtcNow.AddSeconds(-maxRegistrationAge); - return entry.OriginalValues.GetValue(nameof(entry.Entity.Updated)) < expireTime; - } - - /// - /// Checks if the updating data, should be used to also trigger cache reload. - /// Since SaveChanges triggers a full reload of the cache - /// - private bool HasRelevantChange(DbEntityEntry entry) - { - var changedProperties = GetChangedProperties(entry); - // Remove non-relevant properties - changedProperties.Remove(nameof(entry.Entity.Updated)); - changedProperties.Remove(nameof(entry.Entity.ServerTimeStamp)); - changedProperties.Remove(nameof(entry.Entity.Expires)); - - return changedProperties.Any(); - } - - private IList GetChangedProperties(DbEntityEntry entry) - { - if (entry.State != EntityState.Modified) - return new List(); - - return entry.OriginalValues.PropertyNames - .Where(propertyName => !Equals(entry.OriginalValues[propertyName], entry.CurrentValues[propertyName])) - .ToList(); - } - - public RegisteredSip Single(Expression> expression) - { - // TODO: Only for tests??? - using (var db = GetDbContext()) - { - RegisteredSipEntity dbRegisteredSip = db.RegisteredSips.SingleOrDefault(expression); - - return dbRegisteredSip == null - ? null - : new RegisteredSip - { - Id = dbRegisteredSip.Id, - DisplayName = dbRegisteredSip.DisplayName, - Expires = dbRegisteredSip.Expires, - IP = dbRegisteredSip.IP, - Port = dbRegisteredSip.Port, - SIP = dbRegisteredSip.SIP, - ServerTimeStamp = dbRegisteredSip.ServerTimeStamp, - Updated = dbRegisteredSip.Updated, - UserAgentHead = dbRegisteredSip.UserAgentHeader, - Username = dbRegisteredSip.Username, - }; - } - } - - public IEnumerable GetRegisteredUserAgentsDiscovery() - { - DateTime maxAge = DateTime.UtcNow.AddSeconds(-SettingsManager.MaxRegistrationAge); - - // Get available meta data properties - List metaList = _metaRepository.GetAll(); - - using (var db = GetDbContext()) - { - IEnumerable dbSip = db.RegisteredSips - .Include(rs => rs.Location) - .Include(rs => rs.Location.Region) - .Include(rs => rs.Location.City) - .Include(rs => rs.User) - .Include(rs => rs.User.Owner) - .Include(rs => rs.User.CodecType) - .Include(rs => rs.UserAgent) - .Where(r => r.Updated >= maxAge) - .ToList(); - - return dbSip.Select(x => - { - return new RegisteredUserAgentDiscovery( - id: x.Id, - updated: x.Updated, - sipUri: x.SIP, - displayName: x.DisplayName, - username: x.Username, - ipAddress: x.IP, - userAgentHeader: x.UserAgentHeader, - userAgentId: x.UserAgentId, - userAgentName: x.UserAgent?.Name, - locationId: x.Location_LocationId, - locationName: x.Location?.Name, - locationShortName: x.Location?.ShortName, - regionName: x.Location?.Region?.Name, - cityName: x.Location?.City?.Name, - userOwnerName: x.User?.Owner?.Name, - userDisplayName: x.User?.DisplayName, - codecTypeName: x.User?.CodecType?.Name, - metaData: GetMetaData(metaList, x)); - }) - .ToList(); - } - } - - public IEnumerable GetRegisteredUserAgents() - { - DateTime maxAge = DateTime.UtcNow.AddSeconds(-SettingsManager.MaxRegistrationAge); - - using (var db = GetDbContext()) - { - var result = db.RegisteredSips - .Where(x => x.Updated >= maxAge) - .Select(x => - new - { - SIP = x.SIP, - Id = x.Id, - DisplayName = x.DisplayName, - LocationName = x.Location.Name, - LocationShortName = x.Location.ShortName, - Image = x.UserAgent.Image, - CodecTypeName = x.User.CodecType.Name, - CodecTypeColor = x.User.CodecType.Color, - Username = x.Username, - UserDisplayName = x.User.DisplayName, - UserComment = x.User.Comment, - RegionName = x.Location.Region.Name - }) - .ToList(); - - return result.Select(x => - { - return new RegisteredUserAgent( - sipUri: x.SIP, - id: x.Id, - displayName: x.DisplayName, - location: x.LocationName, - locationShortName: x.LocationShortName, - image: x.Image, - codecTypeName: x.CodecTypeName, - codecTypeColor: x.CodecTypeColor, - username: x.Username, - userDisplayName: x.UserDisplayName, - userComment: x.UserComment, - regionName: x.RegionName); - }) - .ToList(); - } - } - - //private void AddCallInfoToCachedRegisteredSip(CcmDbContext db, IEnumerable registeredSips) - //{ - // var sipDomain = SettingsManager.SipDomain; - - // var dbCalls = db.Calls - // .Include(c => c.FromSip) - // .Include(c => c.FromSip.Location) - // .Include(c => c.FromSip.UserAgent) - // .Include(c => c.ToSip) - // .Include(c => c.ToSip.Location) - // .Include(c => c.ToSip.UserAgent) - // .Where(call => !call.Closed) - // .ToList(); - - // foreach (var item in registeredSips) - // { - // var sip = item; - // var call = dbCalls.FirstOrDefault(c => c.ToUsername == sip.Sip || c.FromUsername == sip.Sip); - // if (call == null) - // { - // sip.InCall = false; - // continue; - // } - - // sip.InCall = true; - // sip.IsPhoneCall = call.IsPhoneCall; - // sip.CallStartedAt = call.Started; - - // if (call.FromUsername == sip.Sip) - // { - // sip.InCallWithId = GuidHelper.GuidString(call.ToId); - // sip.InCallWithName = - // CallDisplayNameHelper.GetDisplayName(call.ToSip, call.ToDisplayName, call.ToUsername, - // sipDomain); - // sip.InCallWithSip = call.ToUsername; - // sip.InCallWithLocation = call.ToSip != null && call.ToSip.Location != null - // ? call.ToSip.Location.Name - // : string.Empty; - // sip.InCallWithHasGpo = call.ToSip != null && call.ToSip.UserAgent != null && - // !string.IsNullOrEmpty(call.ToSip.UserAgent.GpoNames); - // sip.IsCallingPart = true; - // } - // else - // { - // sip.InCallWithId = GuidHelper.GuidString(call.FromId); - // sip.InCallWithName = CallDisplayNameHelper.GetDisplayName(call.FromSip, call.FromDisplayName, - // call.FromUsername, sipDomain); - // sip.InCallWithSip = call.FromUsername; - // sip.InCallWithLocation = call.FromSip != null && call.FromSip.Location != null - // ? call.FromSip.Location.Name - // : string.Empty; - // sip.InCallWithHasGpo = call.FromSip != null && call.FromSip.UserAgent != null && - // !string.IsNullOrEmpty(call.FromSip.UserAgent.GpoNames); - // sip.IsCallingPart = false; - // } - // } - //} - - private List> GetMetaData(List metaList, RegisteredSipEntity sip) - { - metaList = metaList ?? new List(); - - var userAgentMetaDataList = metaList - .Select(meta => - new KeyValuePair(meta.Name, - MetadataHelper.GetPropertyValue(sip, meta.FullPropertyName))) - .Where(m => !string.IsNullOrEmpty(m.Value)) - .ToList(); - - return userAgentMetaDataList; - } - - private Guid? GetUserAgentId(string userAgent) - { - userAgent = (userAgent ?? string.Empty).Trim(); - - var allUserAgents = _userAgentRepository.GetAll() - .Where(ua => !string.IsNullOrEmpty(ua.Identifier)) - .Select(ua => new UserAgentInfo( - userAgentId: ua.Id, - identifier: ua.Identifier, - matchType: ua.MatchType - )).ToList(); - - var dbUserAgent = allUserAgents.FirstOrDefault(u => - u.MatchType == MatchType.Begins_With && userAgent.StartsWith(u.Identifier)); - - if (dbUserAgent != null) - { - return dbUserAgent.UserAgentId; - } - - dbUserAgent = allUserAgents.FirstOrDefault(u => - u.MatchType == MatchType.Ends_With && userAgent.EndsWith(u.Identifier)); - - if (dbUserAgent != null) - { - return dbUserAgent.UserAgentId; - } - - dbUserAgent = allUserAgents.FirstOrDefault(u => - u.MatchType == MatchType.Contains && userAgent.Contains(u.Identifier)); - - return dbUserAgent?.UserAgentId; - } - - public IEnumerable GetRegisteredUserAgentsCodecInformation() - { - // TODO: This could maybe be built up in a manager for external api codec information - DateTime maxAge = DateTime.UtcNow.AddSeconds(-SettingsManager.MaxRegistrationAge); - - try - { - using (var db = GetDbContext()) - { - var result = db.RegisteredSips - .Where(x => !string.IsNullOrEmpty(x.UserAgent.Api)) // TODO: is this really.. necessary? - .Where(x => x.Updated >= maxAge) - .Select(x => - new - { - Sip = x.SIP, - Ip = x.IP, - UserAgentApi = x.UserAgent.Api, - UserAgentGpoNames = x.UserAgent.GpoNames, - UserAgentInputs = x.UserAgent.Inputs, - UserAgentNrOfGpos = x.UserAgent.NrOfGpos - }) - .ToList(); - - // Only include latest registrations per sip address - var groupBy = result.GroupBy(x => x.Sip).ToList(); - var groupedList = groupBy.Select(g => g.First()) - .OrderBy(rs => rs.Sip) - .ToList(); - - return groupedList.Select(x => - { - return new RegisteredUserAgentCodecInformation( - sipAddress: x.Sip, - ip: x.Ip, - api: x.UserAgentApi, - gpoNames: x.UserAgentGpoNames, - nrOfInputs: x.UserAgentInputs, - nrOfGpos: x.UserAgentNrOfGpos); - }).ToList(); - } - } - catch (Exception ex) - { - log.Error(ex, "Problem when returning GetRegisteredUserAgentsCodecInformation"); - return null; - } - } - - } -} diff --git a/CCM.Data/Repositories/RoleRepository.cs b/CCM.Data/Repositories/RoleRepository.cs index 43204975..1e1761d6 100644 --- a/CCM.Data/Repositories/RoleRepository.cs +++ b/CCM.Data/Repositories/RoleRepository.cs @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.Linq; using CCM.Core.Entities; @@ -35,20 +36,28 @@ namespace CCM.Data.Repositories { public class RoleRepository : BaseRepository, IRoleRepository { - public RoleRepository(IAppCache cache) : base(cache) + public RoleRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public List GetRoles() { - using (var db = GetDbContext()) - { - var roles = db.Roles.ToList() - .Select(MapToRole) - .OrderBy(r => r.Name) - .ToList(); - return roles; - } + var roles = _ccmDbContext.Roles.ToList() + .Select(MapToRole) + .OrderBy(r => r.Name) + .ToList(); + return roles; + } + + public CcmRole GetById(string roleId) + { + return string.IsNullOrWhiteSpace(roleId) ? null : GetById(new Guid(roleId)); + } + + public CcmRole GetById(Guid roleId) + { + RoleEntity role = _ccmDbContext.Roles.SingleOrDefault(r => r.Id == roleId); + return MapToRole(role); } private CcmRole MapToRole(RoleEntity dbRole) diff --git a/CCM.Data/Repositories/SettingsRepository.cs b/CCM.Data/Repositories/SettingsRepository.cs index 40710dd0..02989968 100644 --- a/CCM.Data/Repositories/SettingsRepository.cs +++ b/CCM.Data/Repositories/SettingsRepository.cs @@ -26,10 +26,13 @@ using System; using System.Collections.Generic; -using System.Data.Entity; using System.Linq; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; +using CCM.Core.Enums; +using CCM.Core.Helpers; using CCM.Core.Interfaces.Repositories; +using CCM.Data.Entities; using LazyCache; using NLog; @@ -39,52 +42,67 @@ public class SettingsRepository : BaseRepository, ISettingsRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public SettingsRepository(IAppCache cache) : base(cache) + public SettingsRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public List GetAll() { - using (var db = GetDbContext()) + var db = _ccmDbContext; + var settings = db.Settings.ToList(); + var list = settings.Select(setting => new Setting { - //log.Debug("Hash codes. Settings repository: {0}, Context:{1}", this.GetHashCode(), Context.GetHashCode()); + Name = setting.Name, + Id = setting.Id, + Value = setting.Value, + Description = setting.Description + }).ToList(); - var settings = db.Settings.ToList(); - - var list = settings.Select(setting => new Setting + // Check for settings that is not in the database yet and add them + foreach (string key in Enum.GetNames(typeof(SettingsEnum))) + { + if (!list.Exists(x => x.Name == key)) { - Name = setting.Name, - Id = setting.Id, - Value = setting.Value, - Description = setting.Description - }).ToList(); - - //log.Debug("Getting settings from database. {0}", string.Join(" ", list.Select(s => string.Format("{0}:{1}", s.Name,s.Value)))); + (string, string) defaultData = ((SettingsEnum)Enum.Parse(typeof(SettingsEnum), key)).DefaultValue(); - return list; + db.Settings.Add(new SettingEntity() + { + Id = Guid.NewGuid(), + Name = key, + Value = defaultData.Item1, + Description = defaultData.Item2, + UpdatedOn = DateTime.UtcNow, + UpdatedBy = "system", + CreatedOn = DateTime.UtcNow, + CreatedBy = "system" + }); + db.SaveChanges(); + } } + + //log.Debug("Getting settings from database. {0}", string.Join(" ", list.Select(s => string.Format("{0}:{1}", s.Name,s.Value)))); + + return list; } public void Save(List settings, string userName) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + DbSet existing = db.Settings; + + foreach (Setting setting in settings) { - DbSet existing = db.Settings; + SettingEntity dbSetting = existing.SingleOrDefault(s => s.Id == setting.Id); - foreach (Setting setting in settings) + if (dbSetting != null && dbSetting.Value != setting.Value) { - Entities.SettingEntity dbSetting = existing.SingleOrDefault(s => s.Id == setting.Id); - - if (dbSetting != null && dbSetting.Value != setting.Value) - { - dbSetting.Value = setting.Value; - dbSetting.UpdatedOn = DateTime.UtcNow; - dbSetting.UpdatedBy = userName; - } + dbSetting.Value = setting.Value; + dbSetting.UpdatedOn = DateTime.UtcNow; + dbSetting.UpdatedBy = userName; } - - db.SaveChanges(); } + + db.SaveChanges(); } } diff --git a/CCM.Data/Repositories/SipAccountRepository.cs b/CCM.Data/Repositories/SipAccountRepository.cs index cadaa8d5..8c675fe4 100644 --- a/CCM.Data/Repositories/SipAccountRepository.cs +++ b/CCM.Data/Repositories/SipAccountRepository.cs @@ -27,8 +27,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Data.Entity; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; @@ -41,10 +41,15 @@ public class SipAccountRepository : BaseRepository, ISipAccountRepository { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - public SipAccountRepository(IAppCache cache) : base(cache) + public SipAccountRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } + public void Save(SipAccount item) + { + throw new NotImplementedException(); + } + public void Create(SipAccount account) { if (account == null) @@ -52,11 +57,26 @@ public void Create(SipAccount account) throw new ArgumentNullException(nameof(account)); } - using (var db = GetDbContext()) + if (GetByUserName(account.UserName) != null) { - var dbAccount = new SipAccountEntity(); - SetEntityFromSipAccount(db, account, dbAccount); - db.SipAccounts.Add(dbAccount); + log.Warn("Can't create user. Username {0} already exists in CCM database", account.UserName); + // TODO: make sure to do this in the frontend as well + throw new ApplicationException("User name already exists."); + } + + var dbAccount = new SipAccountEntity(); + SetEntityFromSipAccount(_ccmDbContext, account, dbAccount); + _ccmDbContext.SipAccounts.Add(dbAccount); + _ccmDbContext.SaveChanges(); + } + + public void Update(SipAccount ccmUser) + { + var db = _ccmDbContext; + SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == ccmUser.Id); + if (dbUser != null) + { + SetEntityFromSipAccount(db, ccmUser, dbUser); db.SaveChanges(); } } @@ -68,132 +88,125 @@ public void Delete(Guid id) throw new ArgumentNullException(nameof(id)); } - using (var db = GetDbContext()) + SipAccountEntity account = _ccmDbContext.SipAccounts.SingleOrDefault(u => u.Id == id); + + if (account != null) + { + account.RegisteredSips?.Clear(); + _ccmDbContext.SipAccounts.Remove(account); + _ccmDbContext.SaveChanges(); + } + else { - SipAccountEntity account = db.SipAccounts.SingleOrDefault(u => u.Id == id); - - if (account != null) - { - account.RegisteredSips?.Clear(); - db.SipAccounts.Remove(account); - db.SaveChanges(); - } - else - { - log.Info("Could not find user {0}", id); - } + log.Info($"Could not find user '{id}' to delete"); } } - public SipAccount GetById(Guid id) + public bool DeleteWithResult(Guid id) { - using (var db = GetDbContext()) + if (id == null) { - SipAccountEntity dbAccount = db.SipAccounts.SingleOrDefault(u => u.Id == id); - return MapToSipAccount(dbAccount); + throw new ArgumentNullException(nameof(id)); } - } - public SipAccount GetByRegisteredSipId(Guid registeredSipId) - { - using (var db = GetDbContext()) + SipAccountEntity account = _ccmDbContext.SipAccounts.SingleOrDefault(u => u.Id == id); + + if (account != null) { - var regSip = db.RegisteredSips - .Include(s => s.User) - .SingleOrDefault(s => s.Id == registeredSipId); - return MapToSipAccount(regSip?.User); + account.RegisteredSips?.Clear(); + _ccmDbContext.SipAccounts.Remove(account); + return _ccmDbContext.SaveChanges() == 1; } + return false; } - public List GetAllIncludingRelations() + public SipAccount GetById(Guid id) { - using (var db = GetDbContext()) - { - var users = db.SipAccounts - .Include(u => u.Owner) - .Include(u => u.CodecType) - .ToList(); + var db = _ccmDbContext; + SipAccountEntity dbAccount = db.SipAccounts + .Include(x => x.Owner) + .Include(x => x.CodecType) + .SingleOrDefault(u => u.Id == id); + return MapToSipAccount(dbAccount); + } - return users.Select(MapToSipAccount).OrderBy(u => u.UserName).ToList(); - } + public SipAccount GetByRegisteredSipId(Guid registeredSipId) + { + var db = _ccmDbContext; + var regSip = db.RegisteredCodecs + .Include(s => s.User) + .SingleOrDefault(s => s.Id == registeredSipId); + return MapToSipAccount(regSip?.User); } public List GetAll() { - using (var db = GetDbContext()) - { - return db.SipAccounts.ToList().Select(MapToSipAccount).OrderBy(u => u.UserName).ToList(); - } + return _ccmDbContext.SipAccounts + .Include(u => u.Owner) + .Include(u => u.CodecType) + .ToList() + .Select(MapToSipAccount) + .OrderBy(u => u.UserName) + .ToList(); } public List Find(string startsWith) { - using (var db = GetDbContext()) - { - var users = db.SipAccounts - .Where(u => u.UserName.Contains(startsWith)) - .ToList(); - return users.Select(MapToSipAccount).OrderBy(u => u.UserName).ToList(); - } + var db = _ccmDbContext; + var users = db.SipAccounts + .Where(u => u.UserName.Contains(startsWith)) + .ToList(); + return users.Select(MapToSipAccount).OrderBy(u => u.UserName).ToList(); } public SipAccount GetByUserName(string userName) { - using (var db = GetDbContext()) - { - SipAccountEntity user = db.SipAccounts.SingleOrDefault(u => u.UserName == userName); - return MapToSipAccount(user); - } + SipAccountEntity user = _ccmDbContext.SipAccounts.SingleOrDefault(u => u.UserName.ToLower() == userName); + return MapToSipAccount(user); } - public void Update(SipAccount ccmUser) + public void UpdateComment(Guid id, string comment) { - using (var db = GetDbContext()) + var db = _ccmDbContext; + SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == id); + + if (dbUser != null) { - SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == ccmUser.Id); - if (dbUser != null) - { - SetEntityFromSipAccount(db, ccmUser, dbUser); - db.SaveChanges(); - } + dbUser.Comment = comment; + db.SaveChanges(); } } - public void UpdateComment(Guid id, string comment) + public void UpdateSipAccountQuick(Guid id, string presentationName, string externalReference) { - using (var db = GetDbContext()) - { - SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == id); + var db = _ccmDbContext; + SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == id); - if (dbUser != null) - { - dbUser.Comment = comment; - db.SaveChanges(); - } + if (dbUser != null) + { + dbUser.DisplayName = presentationName; + dbUser.ExternalReference = externalReference; + db.SaveChanges(); } } public void UpdatePassword(Guid id, string password) { - using (var db = GetDbContext()) - { - SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == id); + var db = _ccmDbContext; + SipAccountEntity dbUser = db.SipAccounts.SingleOrDefault(u => u.Id == id); - if (dbUser != null) - { - dbUser.Password = password; - db.SaveChanges(); - } + if (dbUser != null) + { + dbUser.Password = password; + db.SaveChanges(); } } public async Task AuthenticateAsync(string username, string password) { - using (var db = GetDbContext()) - { - var user = await db.SipAccounts.FirstOrDefaultAsync(u => u.UserName == username && u.Password == password); - return user != null; - } + var db = _ccmDbContext; + var user = await db.SipAccounts.FirstOrDefaultAsync(u => u.UserName == username && u.Password == password); + return user != null; } private SipAccount MapToSipAccount(SipAccountEntity dbAccount) @@ -207,23 +220,15 @@ private SipAccount MapToSipAccount(SipAccountEntity dbAccount) ExtensionNumber = dbAccount.ExtensionNumber, AccountLocked = dbAccount.AccountLocked, AccountType = dbAccount.AccountType, + LastKnownAddress = dbAccount.LastKnownAddress, + LastUsed = dbAccount.LastUsed, + LastUserAgent = dbAccount.LastUserAgent, + ExternalReference = dbAccount.ExternalReference, Owner = MapToOwner(dbAccount.Owner), - CodecType = MaptoCodecType(dbAccount.CodecType) + CodecType = MapToCodecType(dbAccount.CodecType) }; } - private Owner MapToOwner(OwnerEntity dbOwner) - { - return dbOwner != null ? new Owner { Id = dbOwner.Id, Name = dbOwner.Name } : null; - } - - private CodecType MaptoCodecType(CodecTypeEntity dbCodecType) - { - return dbCodecType != null - ? new CodecType { Id = dbCodecType.Id, Name = dbCodecType.Name, Color = dbCodecType.Color } - : null; - } - private void SetEntityFromSipAccount(CcmDbContext cxt, SipAccount account, SipAccountEntity dbAccount) { dbAccount.Id = account.Id; @@ -235,6 +240,11 @@ private void SetEntityFromSipAccount(CcmDbContext cxt, SipAccount account, SipAc dbAccount.CodecType = account.CodecType != null ? cxt.CodecTypes.SingleOrDefault(c => c.Id == account.CodecType.Id) : null; dbAccount.AccountLocked = account.AccountLocked; dbAccount.AccountType = account.AccountType; + // INFO: Info make sure that this is not needed to be set here + //dbAccount.LastKnownAddress = account.LastKnownAddress; + //dbAccount.LastUsed = account.LastUsed; + //dbAccount.LastUserAgent = account.LastUserAgent; + dbAccount.ExternalReference = account.ExternalReference; if (!string.IsNullOrEmpty(account.Password)) { @@ -242,5 +252,16 @@ private void SetEntityFromSipAccount(CcmDbContext cxt, SipAccount account, SipAc } } + private Owner MapToOwner(OwnerEntity dbOwner) + { + return dbOwner != null ? new Owner { Id = dbOwner.Id, Name = dbOwner.Name } : null; + } + + private CodecType MapToCodecType(CodecTypeEntity dbCodecType) + { + return dbCodecType != null + ? new CodecType { Id = dbCodecType.Id, Name = dbCodecType.Name, Color = dbCodecType.Color } + : null; + } } } diff --git a/CCM.Data/Repositories/StudioRepository.cs b/CCM.Data/Repositories/StudioRepository.cs deleted file mode 100644 index a7bea01a..00000000 --- a/CCM.Data/Repositories/StudioRepository.cs +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using AutoMapper; -using CCM.Core.Entities; -using CCM.Core.Interfaces.Repositories; -using CCM.Data.Entities; -using LazyCache; - -namespace CCM.Data.Repositories -{ - public class StudioRepository : BaseRepository, IStudioRepository - { - public StudioRepository(IAppCache cache) : base(cache) - { - } - - public void Save(Studio studio) - { - using (var db = GetDbContext()) - { - StudioEntity dbStudio; - var timeStamp = DateTime.UtcNow; - - if (studio.Id != Guid.Empty) - { - dbStudio = db.Studios.SingleOrDefault(g => g.Id == studio.Id); - - if (dbStudio == null) - { - throw new Exception("Studio could not be found"); - } - } - else - { - dbStudio = new StudioEntity() - { - Id = Guid.NewGuid(), - CreatedBy = studio.CreatedBy, - CreatedOn = timeStamp, - }; - - studio.Id = dbStudio.Id; - studio.CreatedOn = dbStudio.CreatedOn; - db.Studios.Add(dbStudio); - } - - - dbStudio.Name = studio.Name; - dbStudio.CodecSipAddress = studio.CodecSipAddress; - dbStudio.CameraAddress = studio.CameraAddress; - dbStudio.CameraActive = studio.CameraActive; - dbStudio.CameraUsername = studio.CameraUsername; - dbStudio.CameraPassword = studio.CameraPassword; - dbStudio.CameraVideoUrl = studio.CameraVideoUrl; - dbStudio.CameraImageUrl = studio.CameraImageUrl; - dbStudio.CameraPlayAudioUrl = studio.CameraPlayAudioUrl; - dbStudio.AudioClipNames = studio.AudioClipNames; - dbStudio.InfoText = studio.InfoText; - dbStudio.MoreInfoUrl = studio.MoreInfoUrl; - dbStudio.NrOfAudioInputs = studio.NrOfAudioInputs; - dbStudio.AudioInputNames = studio.AudioInputNames; - dbStudio.AudioInputDefaultGain = studio.AudioInputDefaultGain; - dbStudio.NrOfGpos = studio.NrOfGpos; - dbStudio.GpoNames = studio.GpoNames; - dbStudio.InactivityTimeout = studio.InactivityTimeout; - dbStudio.UpdatedBy = studio.UpdatedBy; - studio.UpdatedOn = dbStudio.UpdatedOn = timeStamp; - - db.SaveChanges(); - } - } - - public void Delete(Guid id) - { - using (var db = GetDbContext()) - { - var dbStudio = db.Studios.SingleOrDefault(g => g.Id == id); - if (dbStudio != null) - { - db.Studios.Remove(dbStudio); - db.SaveChanges(); - } - } - } - - public Studio GetById(Guid id) - { - using (var db = GetDbContext()) - { - var dbStudio = db.Studios.SingleOrDefault(g => g.Id == id); - return MapToStudio(dbStudio); - } - } - - public List GetAll() - { - using (var db = GetDbContext()) - { - var dbStudios = db.Studios.ToList(); - return dbStudios.Select(MapToStudio).OrderBy(g => g.Name).ToList(); - } - } - - public List FindStudios(string search) - { - using (var db = GetDbContext()) - { - search = (search ?? string.Empty).ToLower(); - var dbStudios = db.Studios.Where(r => r.Name.ToLower().Contains(search)).ToList(); - return dbStudios.Select(MapToStudio).OrderBy(g => g.Name).ToList(); - } - } - - private Studio MapToStudio(StudioEntity dbStudio) - { - return Mapper.Map(dbStudio); - } - } -} diff --git a/CCM.Data/Repositories/UserAgentRepository.cs b/CCM.Data/Repositories/UserAgentRepository.cs index 4b2446fb..0f178524 100644 --- a/CCM.Data/Repositories/UserAgentRepository.cs +++ b/CCM.Data/Repositories/UserAgentRepository.cs @@ -28,7 +28,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using CCM.Core.Entities; using CCM.Core.Interfaces.Repositories; using CCM.Data.Entities; @@ -38,208 +38,207 @@ namespace CCM.Data.Repositories { public class UserAgentRepository : BaseRepository, IUserAgentRepository { - public UserAgentRepository(IAppCache cache) : base(cache) + public UserAgentRepository(IAppCache cache, CcmDbContext ccmDbContext) : base(cache, ccmDbContext) { } public void Save(UserAgent userAgent) { - using (var db = GetDbContext()) + UserAgentEntity dbUserAgent; + + if (userAgent.Id != Guid.Empty) { - UserAgentEntity dbUserAgent = null; + dbUserAgent = _ccmDbContext.UserAgents + .Include(ua => ua.OrderedProfiles) + .SingleOrDefault(a => a.Id == userAgent.Id); - if (userAgent.Id != Guid.Empty) + if (dbUserAgent == null) { - dbUserAgent = db.UserAgents - .Include(ua => ua.OrderedProfiles) - .SingleOrDefault(a => a.Id == userAgent.Id); + throw new Exception("UserAgent could not be found"); } - if (dbUserAgent == null) + dbUserAgent.OrderedProfiles?.Clear(); + } + else + { + dbUserAgent = new UserAgentEntity() { - dbUserAgent = new UserAgentEntity() - { - Id = Guid.NewGuid(), - CreatedBy = userAgent.CreatedBy, - CreatedOn = DateTime.UtcNow - }; - userAgent.Id = dbUserAgent.Id; - userAgent.CreatedOn = dbUserAgent.CreatedOn; - db.UserAgents.Add(dbUserAgent); - } + Id = Guid.NewGuid(), + CreatedBy = userAgent.CreatedBy, + CreatedOn = DateTime.UtcNow + }; + userAgent.Id = dbUserAgent.Id; + userAgent.CreatedOn = dbUserAgent.CreatedOn; + _ccmDbContext.UserAgents.Add(dbUserAgent); + } + + dbUserAgent.Height = userAgent.Height; + dbUserAgent.Identifier = userAgent.Identifier; + dbUserAgent.Image = userAgent.Image; + dbUserAgent.Name = userAgent.Name; + dbUserAgent.Width = userAgent.Width; + dbUserAgent.MatchType = userAgent.MatchType; + dbUserAgent.UpdatedBy = userAgent.UpdatedBy; + dbUserAgent.UpdatedOn = DateTime.UtcNow; + dbUserAgent.Api = userAgent.Api; + dbUserAgent.UserInterfaceLink = userAgent.UserInterfaceLink; + dbUserAgent.Comment = userAgent.Comment; + dbUserAgent.UserInterfaceIsOpen = userAgent.UserInterfaceIsOpen; + dbUserAgent.UseScrollbars = userAgent.UseScrollbars; + + // Category + dbUserAgent.Category = userAgent.Category != null && userAgent.Category.Id != Guid.Empty + ? _ccmDbContext.Categories.SingleOrDefault(c => c.Id == userAgent.Category.Id) + : null; + dbUserAgent.Category_Id = dbUserAgent.Category?.Id ?? null; - if (dbUserAgent.OrderedProfiles != null) + userAgent.UpdatedOn = DateTime.UtcNow; + + //SetEntityFromProfile(_ccmDbContext, dbUserAgent, userAgent.Profiles); + + // Profiles + dbUserAgent.OrderedProfiles ??= new Collection(); + dbUserAgent.OrderedProfiles.Clear(); + + int sortIndex = 0; + + foreach (ProfileCodec profile in userAgent.Profiles) + { + var dbProfile = _ccmDbContext.Profiles.SingleOrDefault(p => p.Id == profile.Id); + if (dbProfile == null) { - dbUserAgent.OrderedProfiles.Clear(); + continue; } - dbUserAgent.Ax = userAgent.Ax; - dbUserAgent.Height = userAgent.Height; - dbUserAgent.Identifier = userAgent.Identifier; - dbUserAgent.Image = userAgent.Image; - dbUserAgent.Name = userAgent.Name; - dbUserAgent.Width = userAgent.Width; - dbUserAgent.MatchType = userAgent.MatchType; - dbUserAgent.UpdatedBy = userAgent.UpdatedBy; - dbUserAgent.UpdatedOn = DateTime.UtcNow; - dbUserAgent.Api = userAgent.Api; - dbUserAgent.Lines = userAgent.Lines; - dbUserAgent.Inputs = userAgent.Inputs; - dbUserAgent.NrOfGpos = userAgent.NrOfGpos; - dbUserAgent.MaxInputDb = userAgent.InputMaxDb; - dbUserAgent.MinInputDb = userAgent.InputMinDb; - dbUserAgent.UserInterfaceLink = userAgent.UserInterfaceLink; - dbUserAgent.Comment = userAgent.Comment; - dbUserAgent.InputGainStep = userAgent.InputGainStep; - dbUserAgent.GpoNames = userAgent.GpoNames; - dbUserAgent.UserInterfaceIsOpen = userAgent.UserInterfaceIsOpen; - dbUserAgent.UseScrollbars = userAgent.UseScrollbars; - - userAgent.UpdatedOn = dbUserAgent.UpdatedOn; - - GetProfileEntitiesFromProfiles(db, dbUserAgent, userAgent.Profiles); - GetDbCodecPresetsFromCodecPresets(db, dbUserAgent, userAgent.CodecPresets); - - db.SaveChanges(); + dbUserAgent.OrderedProfiles.Add(new UserAgentProfileOrderEntity() + { + Profile = dbProfile, + UserAgent = dbUserAgent, + ProfileSortIndexForUserAgent = sortIndex + }); + + sortIndex++; } + + _ccmDbContext.SaveChanges(); } public void Delete(Guid id) { - using (var db = GetDbContext()) + var userAgent = _ccmDbContext.UserAgents.SingleOrDefault(a => a.Id == id); + if (userAgent != null) { - var userAgent = db.UserAgents.SingleOrDefault(a => a.Id == id); - - if (userAgent != null) - { - db.UserAgents.Remove(userAgent); - db.SaveChanges(); - } + _ccmDbContext.UserAgents.Remove(userAgent); + _ccmDbContext.SaveChanges(); } } public UserAgent GetById(Guid id) { - using (var db = GetDbContext()) - { - var dbUserAgent = db.UserAgents.SingleOrDefault(a => a.Id == id); - return dbUserAgent == null ? null : MapToUserAgent(dbUserAgent); - } + var dbUserAgent = _ccmDbContext.UserAgents + .Include(ca => ca.Category) + .Include(ua => ua.OrderedProfiles) + .ThenInclude(op => op.Profile) + .SingleOrDefault(a => a.Id == id); + + return dbUserAgent == null ? null : MapToUserAgent(dbUserAgent); } public List GetAll() { - using (var db = GetDbContext()) - { - var dbUserAgents = db.UserAgents - .Include(ua => ua.OrderedProfiles.Select(o => o.Profile)) - .Include(ua => ua.CodecPresets) - .ToList(); + var dbUserAgents = _ccmDbContext.UserAgents + .Include(ca => ca.Category) + .Include(ua => ua.OrderedProfiles) + .ThenInclude(p => p.Profile) + .ToList(); - return dbUserAgents.Select(MapToUserAgent).OrderBy(a => a.Name).ToList(); - } + return dbUserAgents.Select(MapToUserAgent) + .OrderByDescending(ua => ua.Identifier.Length) + .ThenBy(ua => ua.Identifier) + .ToList(); } public Dictionary GetUserAgentsTypesAndProfiles() { - using (var db = GetDbContext()) + var result = _ccmDbContext.UserAgents + .Include(ca => ca.Category) + .Include(ua => ua.OrderedProfiles) + .ThenInclude(op => op.Profile) + .OrderByDescending(ua => ua.Identifier.Length) + .ThenBy(ua => ua.Identifier) + .Select(x => + new + { + Id = x.Id, + Name = x.Name, + Identifier = x.Identifier, + MatchType = x.MatchType, + Image = x.Image, + UserInterfaceLink = x.UserInterfaceLink, + Width = x.Width, + Height = x.Height, + Comment = x.Comment, + Api = x.Api, + UserInterfaceIsOpen = x.UserInterfaceIsOpen, + UseScrollbars = x.UseScrollbars, + OrderedProfiles = x.OrderedProfiles, + Category = x.Category + }) + .ToList(); + + return result.ToDictionary(u => u.Id, x => { - var result = db.UserAgents - .OrderBy(y => y.Name) - .Select(x => - new + return new UserAgentAndProfiles( + id: x.Id, + name: x.Name, + identifier: x.Identifier, + matchType: x.MatchType, + imagePath: x.Image, + userInterfaceLink: x.UserInterfaceLink, + width: x.Width, + height: x.Height, + comment: x.Comment, + apiType: x.Api, + userInterfaceIsOpen: x.UserInterfaceIsOpen, + useScrollbars: x.UseScrollbars, + profiles: x.OrderedProfiles + .OrderBy(y => y.ProfileSortIndexForUserAgent) + .Select(z => new ProfileCodec { - Id = x.Id, - Name = x.Name, - Identifier = x.Identifier, - MatchType = x.MatchType, - Image = x.Image, - UserInterfaceLink = x.UserInterfaceLink, - Ax = x.Ax, - Width = x.Width, - Height = x.Height, - Comment = x.Comment, - Api = x.Api, - Lines = x.Lines, - Inputs = x.Inputs, - NrOfGpos = x.NrOfGpos, - InputMinDb = x.MinInputDb, - InputMaxDb = x.MaxInputDb, - InputGainStep = x.InputGainStep, - GpoNames = x.GpoNames, - UserInterfaceIsOpen = x.UserInterfaceIsOpen, - UseScrollbars = x.UseScrollbars, - OrderedProfiles = x.OrderedProfiles - }) - .ToList(); - - return result.ToDictionary(u => u.Id, x => - { - return new UserAgentAndProfiles( - id: x.Id, - name: x.Name, - identifier: x.Identifier, - matchType: x.MatchType, - imagePath: x.Image, - userInterfaceLink: x.UserInterfaceLink, - activeX: x.Ax, - width: x.Width, - height: x.Height, - comment: x.Comment, - apiType: x.Api, - connectionLines: x.Lines, - inputs: x.Inputs, - outputs: 0, - nrOfGpos: x.NrOfGpos, - inputMinDb: x.InputMinDb, - inputMaxDb: x.InputMinDb, - inputGainStep: x.InputGainStep, - gpoNames: x.GpoNames, - userInterfaceIsOpen: x.UserInterfaceIsOpen, - useScrollbars: x.UseScrollbars, - profiles: x.OrderedProfiles - .OrderBy(y => y.SortIndex) - .Select(z => - { - return new Profile - { - Id = z.Profile.Id, - Name = z.Profile.Name, - Description = z.Profile.Description, - Sdp = z.Profile.Sdp - }; - }).ToList() - ); - }); - } + Id = z.Profile.Id, + Name = z.Profile.Name, + Description = z.Profile.Description, + LongDescription = z.Profile.LongDescription, + Sdp = z.Profile.Sdp + }).ToList() + ); + }); } public List Find(string search) { - using (var db = GetDbContext()) - { - var dbUserAgents = db.UserAgents - .Include(ua => ua.OrderedProfiles.Select(o => o.Profile)) - .Include(ua => ua.CodecPresets) - .Where(u => u.Name.ToLower().Contains(search.ToLower()) || - u.Identifier.ToLower().Contains(search.ToLower())) - .ToList(); - - return dbUserAgents.Select(MapToUserAgent).OrderBy(a => a.Name).ToList(); - } + var dbUserAgents = _ccmDbContext.UserAgents + .Include(ca => ca.Category) + .Include(ua => ua.OrderedProfiles) + .ThenInclude(op => op.Profile) + .Where(u => u.Name.ToLower().Contains(search.ToLower()) || + u.Identifier.ToLower().Contains(search.ToLower())) + .OrderByDescending(y => y.Name) + .ToList(); + + return dbUserAgents.Select(MapToUserAgent).OrderBy(a => a.Name).ToList(); } private UserAgent MapToUserAgent(UserAgentEntity dbUserAgent) { return new UserAgent() { - Ax = dbUserAgent.Ax, + Id = dbUserAgent.Id, + Name = dbUserAgent.Name, UserInterfaceLink = dbUserAgent.UserInterfaceLink, Height = dbUserAgent.Height, - Id = dbUserAgent.Id, Identifier = dbUserAgent.Identifier, Image = dbUserAgent.Image, - Name = dbUserAgent.Name, Width = dbUserAgent.Width, MatchType = dbUserAgent.MatchType, CreatedBy = dbUserAgent.CreatedBy, @@ -247,91 +246,54 @@ private UserAgent MapToUserAgent(UserAgentEntity dbUserAgent) UpdatedBy = dbUserAgent.UpdatedBy, UpdatedOn = dbUserAgent.UpdatedOn, Api = dbUserAgent.Api, - Lines = dbUserAgent.Lines, - Inputs = dbUserAgent.Inputs, - NrOfGpos = dbUserAgent.NrOfGpos, - InputMaxDb = dbUserAgent.MaxInputDb, - InputMinDb = dbUserAgent.MinInputDb, Comment = dbUserAgent.Comment, - InputGainStep = dbUserAgent.InputGainStep, - GpoNames = dbUserAgent.GpoNames, UserInterfaceIsOpen = dbUserAgent.UserInterfaceIsOpen, UseScrollbars = dbUserAgent.UseScrollbars, - Profiles = GetProfilesFromProfiles(dbUserAgent.OrderedProfiles), - CodecPresets = dbUserAgent.CodecPresets.Select(MapToCodecPreset).ToList() + Profiles = MapToProfiles(dbUserAgent.OrderedProfiles), + Category = MapToCategory(dbUserAgent.Category) }; } - private List GetProfilesFromProfiles(IEnumerable orderedProfiles) - { - var profiles = orderedProfiles.OrderBy(o => o.SortIndex).Select(o => o.Profile).ToList(); - return profiles.Select(MapProfile).ToList(); - } - - private static Profile MapProfile(ProfileEntity profile) + private List MapToProfiles(IEnumerable orderedProfiles) { - return new Profile - { - Description = profile.Description, - Id = profile.Id, - Name = profile.Name, - Sdp = profile.Sdp - }; + return orderedProfiles.OrderBy(o => o.ProfileSortIndexForUserAgent) + .Select(x => new ProfileCodec { + Description = x.Profile.Description, + Id = x.Profile.Id, + Name = x.Profile.Name, + Sdp = x.Profile.Sdp + }).ToList(); } - private static CodecPreset MapToCodecPreset(CodecPresetEntity dbCodecPreset) + private Category MapToCategory(CategoryEntity dbCategory) { - return new CodecPreset() - { - Id = dbCodecPreset.Id, - CreatedBy = dbCodecPreset.CreatedBy, - CreatedOn = dbCodecPreset.CreatedOn, - Name = dbCodecPreset.Name, - UpdatedBy = dbCodecPreset.UpdatedBy, - UpdatedOn = dbCodecPreset.UpdatedOn - }; + return dbCategory != null ? new Category { Id = dbCategory.Id, Name = dbCategory.Name } : null; } - private void GetProfileEntitiesFromProfiles(CcmDbContext db, UserAgentEntity userAgent, IEnumerable profiles) - { - userAgent.OrderedProfiles = userAgent.OrderedProfiles ?? new Collection(); - userAgent.OrderedProfiles.Clear(); - - int sortIndex = 0; - - foreach (Profile profile in profiles) - { - var dbProfile = db.Profiles.SingleOrDefault(p => p.Id == profile.Id); - if (dbProfile == null) - { - continue; - } + //private void SetEntityFromProfile(CcmDbContext db, UserAgentEntity userAgent, IEnumerable profiles) + //{ + // userAgent.OrderedProfiles ??= new Collection(); + // userAgent.OrderedProfiles.Clear(); - userAgent.OrderedProfiles.Add(new UserAgentProfileOrderEntity() - { - Profile = dbProfile, - UserAgent = userAgent, - SortIndex = sortIndex - }); + // int sortIndex = 0; - sortIndex++; - } - } + // foreach (ProfileCodec profile in profiles) + // { + // var dbProfile = db.Profiles.SingleOrDefault(p => p.Id == profile.Id); + // if (dbProfile == null) + // { + // continue; + // } - private void GetDbCodecPresetsFromCodecPresets(CcmDbContext db, UserAgentEntity userAgent, IEnumerable codecPresets) - { - userAgent.CodecPresets = userAgent.CodecPresets ?? new Collection(); - userAgent.CodecPresets.Clear(); + // userAgent.OrderedProfiles.Add(new UserAgentProfileOrderEntity() + // { + // Profile = dbProfile, + // UserAgent = userAgent, + // ProfileSortIndexForUserAgent = sortIndex + // }); - foreach (var codecPreset in codecPresets) - { - var dbCodecPreset = db.CodecPresets.SingleOrDefault(c => c.Id == codecPreset.Id); - if (dbCodecPreset == null) - { - continue; - } - userAgent.CodecPresets.Add(dbCodecPreset); - } - } + // sortIndex++; + // } + //} } } diff --git a/CCM.Data/app.config b/CCM.Data/app.config deleted file mode 100644 index 8c6cb671..00000000 --- a/CCM.Data/app.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.Data/packages.config b/CCM.Data/packages.config deleted file mode 100644 index df2ecee5..00000000 --- a/CCM.Data/packages.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.DiscoveryApi/App_Start/WebApiConfig.cs b/CCM.DiscoveryApi/App_Start/WebApiConfig.cs deleted file mode 100644 index 3ec0ae70..00000000 --- a/CCM.DiscoveryApi/App_Start/WebApiConfig.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Web.Http; -using System.Web.Http.Cors; - -namespace CCM.DiscoveryApi -{ - public static class WebApiConfig - { - public static void Register(HttpConfiguration config) - { - // Web API configuration and services - GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; - - config.Formatters.XmlFormatter.UseXmlSerializer = true; - config.Formatters.XmlFormatter.WriterSettings.OmitXmlDeclaration = false; - config.Formatters.XmlFormatter.Indent = true; - - config.EnableCors(new EnableCorsAttribute("*","*","*")); - config.MapHttpAttributeRoutes(); - - config.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{id}", - defaults: new {id = RouteParameter.Optional} - ); - } - } -} diff --git a/CCM.DiscoveryApi/Infrastructure/AuthenticationHelper.cs b/CCM.DiscoveryApi/Authentication/AuthenticationHelper.cs similarity index 97% rename from CCM.DiscoveryApi/Infrastructure/AuthenticationHelper.cs rename to CCM.DiscoveryApi/Authentication/AuthenticationHelper.cs index 667e282f..23102391 100644 --- a/CCM.DiscoveryApi/Infrastructure/AuthenticationHelper.cs +++ b/CCM.DiscoveryApi/Authentication/AuthenticationHelper.cs @@ -27,7 +27,7 @@ using System; using System.Text; -namespace CCM.DiscoveryApi.Infrastructure +namespace CCM.DiscoveryApi.Authentication { public class AuthenticationHelper { diff --git a/CCM.DiscoveryApi/Authentication/BasicPreAuthenticationAttribute.cs b/CCM.DiscoveryApi/Authentication/BasicPreAuthenticationAttribute.cs deleted file mode 100644 index 893a48c4..00000000 --- a/CCM.DiscoveryApi/Authentication/BasicPreAuthenticationAttribute.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.Security.Claims; -using System.Security.Principal; -using System.Threading; -using System.Threading.Tasks; -using CCM.WebCommon.Authentication; - -namespace CCM.DiscoveryApi.Authentication -{ - public class BasicPreAuthenticationAttribute : BasicAuthenticationAttributeBase - { - // Used by Discovery v2 - // Performs preauthentication by checking that request contains basic authentication credentials. - // Actual user authentication is deferred to CCM web api. - - protected override async Task AuthenticateAsync(string userName, string password, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List(), AuthenticationTypes.Basic)); - return await Task.FromResult(claimsPrincipal); - } - } -} diff --git a/CCM.DiscoveryApi/Authentication/DiscoveryAuthenticationAttribute.cs b/CCM.DiscoveryApi/Authentication/DiscoveryAuthenticationAttribute.cs deleted file mode 100644 index 5ec9e756..00000000 --- a/CCM.DiscoveryApi/Authentication/DiscoveryAuthenticationAttribute.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Security.Claims; -using System.Threading; -using System.Threading.Tasks; -using System.Web.Http.Filters; -using System.Web.Http.Results; -using CCM.DiscoveryApi.Infrastructure; -using CCM.WebCommon.Authentication; -using NLog; - -namespace CCM.DiscoveryApi.Authentication -{ - /// - /// Performs preauthentication of a SR Discovery request - /// - /// Checks that the request contains SR Discovery authentication parameters - /// and converts then to basic authentication HTTP header - /// - /// Based on code / example from - /// http://www.asp.net/web-api/overview/security/authentication-filters - /// - public class DiscoveryAuthenticationAttribute : Attribute, IAuthenticationFilter - { - // SIP account authentication for SR Discovery - - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - - public bool AllowMultiple => false; - - public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) - { - HttpRequestMessage request = context.Request; - - try - { - if (request.Content.Headers.ContentType.MediaType != "application/x-www-form-urlencoded") - { - context.ErrorResult = new AuthenticationFailureResult("Wrong content type", request, HttpStatusCode.BadRequest); - return; - } - - // Make sure we're reading from beginning of stream - Stream stream = await request.Content.ReadAsStreamAsync(); - stream.Seek(0, SeekOrigin.Begin); - - NameValueCollection formData = await request.Content.ReadAsFormDataAsync(cancellationToken); - - var userName = formData["username"]; - var pwdhash = formData["pwdhash"]; - - if (userName == null || pwdhash == null) - { - context.ErrorResult = new AuthenticationFailureResult("Missing user name or password", request, HttpStatusCode.BadRequest); - return; - } - - // Convert SR Discovery special authentication to Basic Authentication - var authString = AuthenticationHelper.GetAuthString(userName, pwdhash); - request.Headers.Authorization = new AuthenticationHeaderValue(AuthenticationSchemes.Basic.ToString(), authString); - - var claims = new List { new Claim(ClaimTypes.Name, userName) }; - context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, AuthenticationTypes.Basic)); - - if (log.IsDebugEnabled) - { - log.Debug( - "Request to {0} params. User name:'{1}' Password:{2}", - request.RequestUri.OriginalString, - userName, - string.IsNullOrEmpty(pwdhash) ? "" : "********" - ); - } - } - catch (Exception) - { - context.ErrorResult = new InternalServerErrorResult(request); - } - } - - public virtual Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) - { - return Task.FromResult(0); - } - - } -} diff --git a/CCM.DiscoveryApi/Authentication/DiscoveryParameterParserAttribute.cs b/CCM.DiscoveryApi/Authentication/DiscoveryParameterParserAttribute.cs deleted file mode 100644 index 0ed5c713..00000000 --- a/CCM.DiscoveryApi/Authentication/DiscoveryParameterParserAttribute.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Web.Http.Filters; -using System.Web.Http.Results; -using CCM.DiscoveryApi.Models; -using CCM.WebCommon.Authentication; -using NLog; - -namespace CCM.DiscoveryApi.Authentication -{ - /// - /// Checks that the request contains valid SR Discovery parameters - /// - public class DiscoveryParameterParserAttribute : Attribute, IAuthenticationFilter - { - protected static readonly Logger log = LogManager.GetCurrentClassLogger(); - - // These parameters are not filter parameters - private readonly IEnumerable _nonFilterKeys = new List {"username", "pwdhash", "caller", "callee", "includeCodecsInCall"}.Select(i => i.ToLower()); - - public bool AllowMultiple => false; - - public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) - { - HttpRequestMessage request = context.Request; - - try - { - if (request.Content.Headers.ContentType.MediaType != "application/x-www-form-urlencoded") - { - context.ErrorResult = new AuthenticationFailureResult("Wrong content type", request, HttpStatusCode.BadRequest); - return; - } - - // Make sure we're reading from beginning of stream - Stream stream = await request.Content.ReadAsStreamAsync(); - stream.Seek(0, SeekOrigin.Begin); - - NameValueCollection formData = await request.Content.ReadAsFormDataAsync(cancellationToken); - - // Get SR Discovery parameters - var parameters = GetSrDiscoveryParameters(formData); - request.Properties.Add("SRDiscoveryParameters", parameters); - - if (log.IsDebugEnabled) - { - log.Debug( - "Request to {0} params. Caller:'{1}' Callee:'{2}' Filters: {3}", - request.RequestUri.OriginalString, - string.IsNullOrEmpty(parameters.Caller) ? "" : parameters.Caller, - string.IsNullOrEmpty(parameters.Callee) ? "" : parameters.Callee, - string.Join(", ", parameters.Filters.Select(f => $"{f.Key}={f.Value}")) ); - } - } - catch (Exception) - { - context.ErrorResult = new InternalServerErrorResult(request); - } - } - - private SrDiscoveryParameters GetSrDiscoveryParameters(NameValueCollection formData) - { - IList> filters = formData.AllKeys - .Where(k => !_nonFilterKeys.Contains(k.ToLower())) - .Select(key => new KeyValuePair(key, formData[key])) - .ToList(); - - bool.TryParse(formData["includeCodecsInCall"], out var includeCodecsInCall); - - return new SrDiscoveryParameters - { - Caller = formData["caller"] ?? string.Empty, - Callee = formData["callee"] ?? string.Empty, - IncludeCodecsInCall = includeCodecsInCall, - Filters = filters - }; - } - - public virtual Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) - { - return Task.FromResult(0); - } - - } -} diff --git a/CCM.DiscoveryApi/Authentication/DiscoveryV1BasicAuthenticationHandler.cs b/CCM.DiscoveryApi/Authentication/DiscoveryV1BasicAuthenticationHandler.cs new file mode 100644 index 00000000..73c90886 --- /dev/null +++ b/CCM.DiscoveryApi/Authentication/DiscoveryV1BasicAuthenticationHandler.cs @@ -0,0 +1,121 @@ +#region copyright +/* + * Copyright (c) 2022 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#endregion copyright + +using System; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using NLog; +using Claim = System.Security.Claims.Claim; +using ClaimsIdentity = System.Security.Claims.ClaimsIdentity; +using ClaimsPrincipal = System.Security.Claims.ClaimsPrincipal; +using ClaimTypes = System.Security.Claims.ClaimTypes; + +namespace CCM.DiscoveryApi.Authentication +{ + /// + /// Used by DiscoveryController + /// Performs pre-authentication of a SR Discovery request by checking that + /// the request contains authentication credentials.The parameters are + /// converted to a basic authentication HTTP header and forwarded. + /// + /// Actual user authentication is deferred to CCM web api. + /// + public class DiscoveryV1BasicAuthenticationHandler: AuthenticationHandler + { + protected static readonly Logger log = LogManager.GetCurrentClassLogger(); + + public DiscoveryV1BasicAuthenticationHandler( + IOptionsMonitor options, + ILoggerFactory logger, + UrlEncoder encoder, + ISystemClock clock) + : base(options, logger, encoder, clock) + { + + } + + [Consumes("application/x-www-form-urlencoded")] + [Produces("application/xml")] + protected override async Task HandleAuthenticateAsync() + { + try + { + if (Request.ContentType != "application/x-www-form-urlencoded") + { + return AuthenticateResult.Fail("Wrong content type, expecting 'application/x-www-form-urlencoded'"); + } + + IFormCollection formData = Request.Form; + + if (formData == null) + { + return AuthenticateResult.Fail("Missing authentication"); + } + + var userName = formData["username"]; + var pwdHash = formData["pwdhash"]; + + if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(pwdHash)) + { + return AuthenticateResult.Fail("Missing user name or password"); + } + + // Convert SR Discovery special authentication to Basic Authentication + var authString = AuthenticationHelper.GetBasicAuthorizationString(userName, pwdHash); + Request.Headers["Authorization"] = authString; + + // Setting up some claims + // TODO: See if things are actually still forwarded + var claims = new[] { + new Claim(ClaimTypes.Role, "Discovery V1 endpoint verified"), + new Claim(ClaimTypes.Name, userName), + }; + var identity = new ClaimsIdentity(claims, "Basic"); + // Claims principal, an array of Claim Identities or Claims (Many authorities can say how you are) + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, "Basic"); + + if (log.IsDebugEnabled) + { + log.Debug($"Request to {Request.Path.Value} params. User name:'{userName}' Password:{(string.IsNullOrEmpty(pwdHash) ? "" : " * *******")}"); + } + return AuthenticateResult.Success(ticket); + } + catch (Exception ex) + { + log.Error(ex, "Could not authenticate"); + return AuthenticateResult.Fail("Exception in authentication"); + } + } + } +} \ No newline at end of file diff --git a/CCM.DiscoveryApi/Authentication/DiscoveryV2BasicAuthenticationHandler.cs b/CCM.DiscoveryApi/Authentication/DiscoveryV2BasicAuthenticationHandler.cs new file mode 100644 index 00000000..ad5e6b09 --- /dev/null +++ b/CCM.DiscoveryApi/Authentication/DiscoveryV2BasicAuthenticationHandler.cs @@ -0,0 +1,113 @@ +#region copyright +/* + * Copyright (c) 2022 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#endregion copyright + +using System; +using System.Net.Http.Headers; +using System.Security.Claims; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using CCM.Core.Authentication; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using NLog; + +namespace CCM.DiscoveryApi.Authentication +{ + /// + /// Used by DiscoveryV2Controller + /// Performs pre-authentication of a SR Discovery request by checking that + /// the request contains basic authentication credentials. + /// + /// Actual user authentication is deferred to CCM web api. + /// + public class DiscoveryV2BasicAuthenticationHandler: AuthenticationHandler + { + protected static readonly Logger log = LogManager.GetCurrentClassLogger(); + + public DiscoveryV2BasicAuthenticationHandler( + IOptionsMonitor options, + ILoggerFactory logger, + UrlEncoder encoder, + ISystemClock clock) + : base(options, logger, encoder, clock) + { + + } + + protected override async Task HandleAuthenticateAsync() + { + AuthenticationHeaderValue header; + try + { + header = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); + } + catch(Exception e) + { + return AuthenticateResult.Fail(e.Message); + } + + if (string.IsNullOrEmpty(header.Parameter)) + { + // No authentication was attempted (for this authentication method). + // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error). + log.Debug("No authentication header in request for {0}", new Uri(Request.GetDisplayUrl()).ToString()); + return AuthenticateResult.Fail("Missing authorization header"); + } + + if (header.Scheme.StartsWith("basic", StringComparison.OrdinalIgnoreCase) == false) + { + // No authentication was attempted (for this authentication method). + // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error). + log.Debug("Not a Basic authentication header in request for {0}", new Uri(Request.GetDisplayUrl()).ToString()); + return AuthenticateResult.Fail("Not using basic authorization scheme"); + } + + AuthenticationCredentials authenticationCredentials = BasicAuthenticationHelper.ParseCredentials(header.Parameter); + if (authenticationCredentials == null) + { + // Authentication was attempted but failed. Set ErrorResult to indicate an error. + log.Debug("No username and password in request for {0}", new Uri(Request.GetDisplayUrl()).ToString()); + return AuthenticateResult.Fail("Missing or invalid credentials"); + } + + // Setting up some claims + var claims = new[] { + new Claim(ClaimTypes.Role, "Discovery endpoint verified"), + new Claim(ClaimTypes.NameIdentifier, authenticationCredentials.Username), + }; + var identity = new ClaimsIdentity(claims, Scheme.Name); + // Claims principal, an array of Claim Identities or Claims (Many authorities can say how you are) + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, Scheme.Name); + + return AuthenticateResult.Success(ticket); + } + } +} \ No newline at end of file diff --git a/CCM.DiscoveryApi/CCM.DiscoveryApi.csproj b/CCM.DiscoveryApi/CCM.DiscoveryApi.csproj index 199fb76a..f16b108e 100644 --- a/CCM.DiscoveryApi/CCM.DiscoveryApi.csproj +++ b/CCM.DiscoveryApi/CCM.DiscoveryApi.csproj @@ -1,206 +1,19 @@ - - - + + - Debug - AnyCPU - - - 2.0 - {7298F672-7243-4478-827C-B6D5F238C282} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - CCM.DiscoveryApi - CCM.DiscoveryApi - v4.6.2 - false - true - - - - - ..\ - true - - - + netcoreapp3.1 + false - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - False - ..\packages\Microsoft.AspNet.Identity.Core.1.0.0\lib\net45\Microsoft.AspNet.Identity.Core.dll - - - - ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\packages\NLog.4.5.3\lib\net45\NLog.dll - - - - - - - - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.4\lib\net45\System.Net.Http.Formatting.dll - - - - - ..\packages\Microsoft.AspNet.Cors.5.2.3\lib\net45\System.Web.Cors.dll - True - - - - - - - ..\packages\Microsoft.AspNet.WebApi.Core.5.2.4\lib\net45\System.Web.Http.dll - - - ..\packages\Microsoft.AspNet.WebApi.Cors.5.2.3\lib\net45\System.Web.Http.Cors.dll - True - - - False - ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll - - - - - - - - - True - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - - - - - + - - - - Code - - - - - - - - - - - - - - - - - - Global.asax - - - - - - - - - - - - - + + - - - - Designer - - - Web.config - - - Web.config - Designer - + + + + + - - - {2b04cc56-7dfe-40f0-ba17-21d8b93e0b75} - CCM.Core - - - {5b5a87fa-3f5b-49e7-a685-89d463698e42} - CCM.WebCommon - - - - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - true - bin\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - - - - - - - - - True - - - - - - - - \ No newline at end of file + diff --git a/CCM.DiscoveryApi/Controllers/Api/LogLevelController.cs b/CCM.DiscoveryApi/Controllers/Api/LogLevelController.cs index 65c576c8..232f6eed 100644 --- a/CCM.DiscoveryApi/Controllers/Api/LogLevelController.cs +++ b/CCM.DiscoveryApi/Controllers/Api/LogLevelController.cs @@ -24,9 +24,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System.Web.Http; using CCM.Core.Managers; using NLog; +using Microsoft.AspNetCore.Mvc; namespace CCM.DiscoveryApi.Controllers.Api { @@ -35,8 +35,8 @@ public class LevelModel public string LogLevel { get; set; } } - [RoutePrefix("api/loglevel")] - public class LogLevelController : ApiController + [Route("api/loglevel")] + public class LogLevelController : ControllerBase { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); @@ -46,23 +46,5 @@ public LevelModel Get() log.Info("Log level is '{0}' for CCM Discovery", currentLevel.Name); return new LevelModel { LogLevel = currentLevel.Name }; } - - public LevelModel Post(LevelModel levelModel) - { - if (levelModel != null) - { - var isSet = LogLevelManager.SetLogLevel(levelModel.LogLevel); - if (isSet) - { - log.Info("Log level changed to '{0}' for CCM Discovery", levelModel.LogLevel); - } - else - { - log.Info("Log level was NOT changed to '{0}' for CCM Discovery", levelModel.LogLevel); - } - } - - return Get(); - } } } diff --git a/CCM.DiscoveryApi/Controllers/DiscoveryController.cs b/CCM.DiscoveryApi/Controllers/DiscoveryController.cs index e5a965df..3e1636e5 100644 --- a/CCM.DiscoveryApi/Controllers/DiscoveryController.cs +++ b/CCM.DiscoveryApi/Controllers/DiscoveryController.cs @@ -24,78 +24,82 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Web.Http; +using System; using CCM.Core.Entities.Discovery; -using CCM.DiscoveryApi.Authentication; -using CCM.DiscoveryApi.Infrastructure; -using CCM.DiscoveryApi.Models; -using CCM.DiscoveryApi.Models.DiscoveryModels; using CCM.DiscoveryApi.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using NLog; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CCM.DiscoveryApi.Models.Discovery; +using Microsoft.AspNetCore.Http; namespace CCM.DiscoveryApi.Controllers { - [DiscoveryControllerConfig] - [DiscoveryAuthentication] - [Authorize] - public class DiscoveryController : ApiController + [Produces("application/xml")] + [Authorize("BasicAuthenticationDiscoveryV1")] + public class DiscoveryController : ControllerBase { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); private readonly IDiscoveryHttpService _discoveryService; - public DiscoveryController() + public DiscoveryController(IDiscoveryHttpService discoveryHttpService) { - _discoveryService = new DiscoveryHttpService(); + _discoveryService = discoveryHttpService; } [Route("~/filters")] [HttpPost] - public async Task Filters() + public async Task Filters() { log.Trace("Discovery API - requesting 'filters'"); var filterDtos = await _discoveryService.GetFiltersAsync(Request); - var filters = filterDtos.Select(f => new Filter + var filters = filterDtos.Select(f => new DiscoveryFilter { Name = f.Name, - FilterOptions = f.Options.Select(o => new FilterOption { Name = o }).ToList() + FilterOptions = f.Options.Select(o => new DiscoveryFilterOption { Name = o }).ToList() }).ToList(); - return new SrDiscovery { Filters = filters }; + return new DiscoveryResponse { Filters = filters }; } [Route("~/profiles")] [HttpPost] - public async Task Profiles() + public async Task Profiles() { log.Trace("Discovery API - requesting 'profiles'"); var profileDtos = await _discoveryService.GetProfilesAsync(Request); var profiles = profileDtos - .Select(p => new Profile { Name = p.Name, Sdp = p.Sdp }) + .Select(p => new DiscoveryProfile { Name = p.Name, Sdp = p.Sdp }) .ToList(); - return new SrDiscovery { Profiles = profiles }; + return new DiscoveryResponse { Profiles = profiles }; } [Route("~/useragents")] [HttpPost] - [DiscoveryParameterParser] - public async Task UserAgents() + public async Task UserAgents([FromForm] DiscoveryUserAgentRequest reqFormData) { - var parameters = (SrDiscoveryParameters)Request.Properties["SRDiscoveryParameters"]; + if (Request.ContentType != "application/x-www-form-urlencoded") + { + log.Warn("Wrong content type, expecting 'application/x-www-form-urlencoded'"); + } + + // Since nested filter choices does not work with flat keys, special parsing is done + DiscoveryUserAgentRequest srDiscoveryParameters = ParseDiscoveryParameters(Request.Form); var searchParams = new UserAgentSearchParamsDto { - Caller = parameters.Caller, - Callee = parameters.Callee, - IncludeCodecsInCall = parameters.IncludeCodecsInCall, - Filters = parameters.Filters + Caller = srDiscoveryParameters.Caller, + Callee = srDiscoveryParameters.Callee, + IncludeCodecsInCall = srDiscoveryParameters.IncludeCodecsInCall, + Filters = srDiscoveryParameters.Filters }; log.Trace("Discovery API - requesting 'useragents'", searchParams); @@ -105,23 +109,49 @@ public async Task UserAgents() if (uaResult == null) { log.Info("No user agents returned for DiscoveryV1"); - return new SrDiscovery(); + return new DiscoveryResponse(); } - var profiles = uaResult.Profiles?.Select(p => new Profile() { Name = p.Name, Sdp = p.Sdp }).ToList() ?? new List(); + var profiles = uaResult.Profiles?.Select(p => new DiscoveryProfile() { Name = p.Name, Sdp = p.Sdp }).ToList() ?? new List(); - var userAgents = uaResult.UserAgents?.Select(ua => new UserAgent() + var userAgents = uaResult.UserAgents?.Select(ua => new DiscoveryUserAgent() { SipId = ua.SipId, ConnectedTo = ua.ConnectedTo, - ProfileRec = ua.Profiles.Select(p => new UserAgentProfileRef { Name = p }).ToList(), - MetaData = ua.MetaData.Select(m => new UserAgentMetaData() { Key = m.Key, Value = m.Value }).ToList() - }).ToList() ?? new List(); + ProfileRec = ua.Profiles.Select(p => new DiscoveryUserAgentProfileRef { Name = p }).ToList(), + MetaData = ua.MetaData.Select(m => new DiscoveryUserAgentMetaData() { Key = m.Key, Value = m.Value }).ToList() + }).ToList() ?? new List(); log.Debug("Discovery V1 Returning {0} useragents and {1} profiles", uaResult.UserAgents?.Count ?? 0, uaResult.Profiles?.Count ?? 0); - return new SrDiscovery { UserAgents = userAgents, Profiles = profiles }; + return new DiscoveryResponse { UserAgents = userAgents, Profiles = profiles }; } + /// + /// These parameters are not filter parameters + /// + private readonly IEnumerable _nonFilterKeys = new List { "username", "pwdhash", "caller", "callee", "includeCodecsInCall" }.Select(i => i.ToLower()); + + private DiscoveryUserAgentRequest ParseDiscoveryParameters(IFormCollection formData) + { + if (formData == null) + { + return new DiscoveryUserAgentRequest(); + } + IList> filters = formData.Keys + .Where(k => !_nonFilterKeys.Contains(k.ToLower())) + .Select(key => new KeyValuePair(key, formData[key])) + .ToList(); + + bool.TryParse(formData["includeCodecsInCall"], out var includeCodecsInCall); + + return new DiscoveryUserAgentRequest + { + Caller = formData["caller"], + Callee = formData["callee"], + IncludeCodecsInCall = includeCodecsInCall, + Filters = filters + }; + } } } diff --git a/CCM.DiscoveryApi/Controllers/DiscoveryV2Controller.cs b/CCM.DiscoveryApi/Controllers/DiscoveryV2Controller.cs index c9d004be..af1df20e 100644 --- a/CCM.DiscoveryApi/Controllers/DiscoveryV2Controller.cs +++ b/CCM.DiscoveryApi/Controllers/DiscoveryV2Controller.cs @@ -24,46 +24,45 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using System.Web.Http; using CCM.Core.Entities.Discovery; -using CCM.DiscoveryApi.Authentication; -using CCM.DiscoveryApi.Models.DiscoveryV2Models.Filters; -using CCM.DiscoveryApi.Models.DiscoveryV2Models.Profiles; -using CCM.DiscoveryApi.Models.DiscoveryV2Models.UserAgents; using CCM.DiscoveryApi.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using NLog; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CCM.DiscoveryApi.Models.DiscoveryV2; namespace CCM.DiscoveryApi.Controllers { - [BasicPreAuthentication] - [Authorize] - public class DiscoveryV2Controller : ApiController + [Authorize("BasicAuthenticationDiscoveryV2")] + public class DiscoveryV2Controller : Controller { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); private readonly IDiscoveryHttpService _discoveryService; - public DiscoveryV2Controller() + public DiscoveryV2Controller(IDiscoveryHttpService discoveryHttpService) { - _discoveryService = new DiscoveryHttpService(); + _discoveryService = discoveryHttpService; } [HttpGet] [Route("~/v2/filters")] - public async Task> Filters() + public async Task> Filters() { log.Trace("Discovery V2 API - requesting 'filters'"); List filterDtos = await _discoveryService.GetFiltersAsync(Request); - var filters = filterDtos.Select(f => new FilterV2 + var filters = filterDtos.Select(f => new DiscoveryV2Filter { Name = f.Name, - Options = f.Options.Select(o => new FilterOptionV2 {Name = o}).ToList() + Options = f.Options.Select(o => new DiscoveryV2FilterOption + { + Name = o + }).ToList() }).ToList(); return filters; @@ -71,14 +70,18 @@ public async Task> Filters() [HttpGet] [Route("~/v2/profiles")] - public async Task> Profiles() + public async Task> Profiles() { log.Trace("Discovery V2 API - requesting 'profiles'"); var profileDtos = await _discoveryService.GetProfilesAsync(Request); var profiles = profileDtos - .Select(p => new ProfileDtoV2() { Name = p.Name, Sdp = p.Sdp }) + .Select(p => new DiscoveryV2Profile() + { + Name = p.Name, + Sdp = p.Sdp + }) .ToList(); return profiles; @@ -86,14 +89,14 @@ public async Task> Profiles() [HttpPost] [Route("~/v2/useragents")] - public async Task UserAgents(UserAgentSearchParamsV2 searchParams) + public async Task UserAgents([FromBody]DiscoveryV2UserAgentRequest searchParams) { - log.Trace("Discovery V2 API - requesting 'useragents'", searchParams); + log.Trace("Discovery V2 API - requesting 'useragents'", searchParams); // old return UserAgentsResultV2 if (searchParams == null) { log.Debug("Requesting useragents from Discovery V2, but search params is null"); - throw new HttpResponseException(HttpStatusCode.BadRequest); + searchParams = new DiscoveryV2UserAgentRequest(); } var searchParamsDto = new UserAgentSearchParamsDto @@ -106,22 +109,21 @@ public async Task UserAgents(UserAgentSearchParamsV2 searchP UserAgentsResultDto uaResult = await _discoveryService.GetUserAgentsAsync(searchParamsDto, Request); - log.Debug("Returning {0} useragents and {1} profiles (V2).", uaResult.UserAgents?.Count ?? 0, uaResult.Profiles?.Count ?? 0); + log.Error("Returning {0} useragents and {1} profiles (V2).", uaResult.UserAgents?.Count ?? 0, uaResult.Profiles?.Count ?? 0); - var result = new UserAgentsResultV2 + var result = new DiscoveryV2UserAgentsResponse { - Profiles = uaResult?.Profiles?.Select(p => new ProfileDtoV2 { Name = p.Name, Sdp = p.Sdp }).ToList() ?? new List(), - UserAgents = uaResult?.UserAgents?.Select(ua => new UserAgentDtoV2 + Profiles = uaResult?.Profiles?.Select(p => new DiscoveryV2Profile { Name = p.Name, Sdp = p.Sdp }).ToList() ?? new List(), + UserAgents = uaResult?.UserAgents?.Select(ua => new DiscoveryV2UserAgent { SipId = ua.SipId, ConnectedTo = ua.ConnectedTo, Profiles = ua.Profiles, - MetaData = ua.MetaData?.Select(m => new KeyValuePairDtoV2(m.Key, m.Value)).ToList() ?? new List() - }).ToList() ?? new List() + MetaData = ua.MetaData?.Select(m => new DiscoveryV2UserAgentMetaData(m.Key, m.Value)).ToList() ?? new List() + }).ToList() ?? new List() }; - return result; + return Ok(result); } - } } diff --git a/CCM.Web/App_Start/FilterConfig.cs b/CCM.DiscoveryApi/Controllers/HealthController.cs similarity index 81% rename from CCM.Web/App_Start/FilterConfig.cs rename to CCM.DiscoveryApi/Controllers/HealthController.cs index d55c8337..59487e10 100644 --- a/CCM.Web/App_Start/FilterConfig.cs +++ b/CCM.DiscoveryApi/Controllers/HealthController.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden * * Redistribution and use in source and binary forms, with or without @@ -24,17 +24,20 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System.Web.Mvc; -using CCM.Web.Infrastructure.MvcFilters; +using Microsoft.AspNetCore.Mvc; -namespace CCM.Web +namespace CCM.DiscoveryApi.Controllers { - public class FilterConfig + /// + /// For health checks (used during deploy process for verification) + /// + public class HealthController : Controller { - public static void RegisterGlobalFilters(GlobalFilterCollection filters) + [HttpGet] + [Route("/health")] + public IActionResult Health() { - filters.Add(new LogErrorsAttribute()); - filters.Add(new ElapsedTimeFilter()); + return Ok(); } } -} +} \ No newline at end of file diff --git a/CCM.DiscoveryApi/Controllers/HomeController.cs b/CCM.DiscoveryApi/Controllers/HomeController.cs index 5831f50b..b5bfc4ff 100644 --- a/CCM.DiscoveryApi/Controllers/HomeController.cs +++ b/CCM.DiscoveryApi/Controllers/HomeController.cs @@ -24,23 +24,36 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System.Net.Http; -using System.Net.Http.Headers; -using System.Reflection; -using System.Web.Http; -using CCM.DiscoveryApi.Infrastructure; +using CCM.Core.Helpers; +using CCM.DiscoveryApi.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace CCM.DiscoveryApi.Controllers { - public class HomeController : ApiController + /// + /// Some basic information about the Discovery Api + /// + public class HomeController : Controller { + protected ILogger _logger; + private readonly ApplicationSettingsDiscovery _configuration; + private readonly ApplicationBuildInformation _buildInformation; + + public HomeController(ILogger logger, IOptions configuration, IOptions buildInformation) + { + _logger = logger; + _configuration = configuration.Value; + _buildInformation = buildInformation.Value; + } + [HttpGet] - [Route("")] - public HttpResponseMessage Index() + [Route("~/", Name = "default")] + public IActionResult Index() { - var version = Assembly.GetExecutingAssembly().GetName().Version.ToString(3); - var buildDate = ApplicationSettings.BuildDate; - var deployServer = ApplicationSettings.Server; + var version = _buildInformation.Version; + var releaseDate = _buildInformation.ReleaseDate; var html = @" @@ -54,13 +67,14 @@ public HttpResponseMessage Index() margin: 0; padding: 0; height: 100%; - background-color: #2fd7c7 !important; + background-color: #3a4cb7 !important; font-family: Arial, Helvetica, sans-serif !important; + font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif !important; -webkit-font-smoothing: subpixel-antialiased; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; line-height: 1; - color: #fdf525; + color: #251f81; } .container { padding: 4vh 1vw 2vh 1vw; @@ -69,23 +83,27 @@ public HttpResponseMessage Index() width: 95vw; } h1 { - border-top: 2vh solid #FFEB3B; + border-top: 15px solid #ffc107; padding-top: 7vh; + padding-bottom: 36vh; + font-size: 6rem; + font-weight: 200; }

IRIS
Discovery

-

Version: " + version + @"
Build date: " + buildDate + @"

+

Version: " + version + @"
Build date: " + releaseDate + @"

"; - var htmlContent = new StringContent(html); - htmlContent.Headers.ContentType = new MediaTypeHeaderValue("text/html"); - return new HttpResponseMessage { Content = htmlContent }; + return new ContentResult() + { + Content = html, + ContentType = "text/html" + }; } - } } diff --git a/CCM.DiscoveryApi/Global.asax b/CCM.DiscoveryApi/Global.asax deleted file mode 100644 index 4b727449..00000000 --- a/CCM.DiscoveryApi/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="CCM.DiscoveryApi.WebApiApplication" Language="C#" %> diff --git a/CCM.DiscoveryApi/Global.asax.cs b/CCM.DiscoveryApi/Global.asax.cs deleted file mode 100644 index 2c0bee07..00000000 --- a/CCM.DiscoveryApi/Global.asax.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Web.Http; -using CCM.WebCommon.Infrastructure.WebApi; - -namespace CCM.DiscoveryApi -{ - - public class WebApiApplication : System.Web.HttpApplication - { - protected void Application_Start() - { - GlobalConfiguration.Configuration.Filters.Add(new StopwatchAttribute()); - GlobalConfiguration.Configuration.Filters.Add(new ApiExceptionFilter()); - GlobalConfiguration.Configure(WebApiConfig.Register); - } - } -} diff --git a/CCM.DiscoveryApi/Infrastructure/ApplicationSettings.cs b/CCM.DiscoveryApi/Infrastructure/ApplicationSettings.cs deleted file mode 100644 index a8c3df1b..00000000 --- a/CCM.DiscoveryApi/Infrastructure/ApplicationSettings.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Configuration; - -namespace CCM.DiscoveryApi.Infrastructure -{ - public static class ApplicationSettings - { - // URL to CCM Web, so that the internal REST call calls the actual server, used in Discovery service - public static Uri CcmHost => new Uri(ConfigurationManager.AppSettings["CCMHost"]); - public static string DiscoveryUsername => ConfigurationManager.AppSettings["DiscoveryUsername"]; // TODO: Is this really in use anymore? - public static string DiscoveryPassword => ConfigurationManager.AppSettings["DiscoveryPassword"]; // TODO: Is this really in use anymore? - public static string BuildDate => ConfigurationManager.AppSettings["BuildDate"]; - public static string Server => ConfigurationManager.AppSettings["Server"]; - public static string LogFolder => ConfigurationManager.AppSettings["LogFolderDiscovery"]; - } -} diff --git a/CCM.DiscoveryApi/Infrastructure/DiscoveryControllerConfigAttribute.cs b/CCM.DiscoveryApi/Infrastructure/DiscoveryControllerConfigAttribute.cs deleted file mode 100644 index 9be1b97c..00000000 --- a/CCM.DiscoveryApi/Infrastructure/DiscoveryControllerConfigAttribute.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Net.Http.Formatting; -using System.Web.Http.Controllers; - -namespace CCM.DiscoveryApi.Infrastructure -{ - [AttributeUsage(AttributeTargets.Class)] - public class DiscoveryControllerConfigAttribute : Attribute, IControllerConfiguration - { - public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) - { - // Only allow XML in the discovery controllers - XmlMediaTypeFormatter globalXmlFormatterInstance = controllerSettings.Formatters.XmlFormatter; - controllerSettings.Formatters.Clear(); - controllerSettings.Formatters.Add(globalXmlFormatterInstance); - } - } -} diff --git a/CCM.DiscoveryApi/Models/ApplicationSettingsDiscovery.cs b/CCM.DiscoveryApi/Models/ApplicationSettingsDiscovery.cs new file mode 100644 index 00000000..7118cb06 --- /dev/null +++ b/CCM.DiscoveryApi/Models/ApplicationSettingsDiscovery.cs @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace CCM.DiscoveryApi.Models +{ + public class ApplicationSettingsDiscovery + { + /// + /// URL to CCM Web, so that the internal REST call calls the actual server, used in Discovery service + /// + public string CcmHost { get; set; } + } +} diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/Filter.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryFilter.cs similarity index 88% rename from CCM.DiscoveryApi/Models/DiscoveryModels/Filter.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryFilter.cs index f52507ce..97ba3bd5 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/Filter.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryFilter.cs @@ -27,17 +27,17 @@ using System.Collections.Generic; using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { - public class Filter + public class DiscoveryFilter { [XmlAttribute("name")] public string Name { get; set; } [XmlElement("localised-name")] - public LocalisedName LocalisedName { get; set; } + public DiscoveryLocalisedName LocalisedName { get; set; } [XmlElement("option")] - public List FilterOptions { get; set; } + public List FilterOptions { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/FilterOption.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryFilterOption.cs similarity index 91% rename from CCM.DiscoveryApi/Models/DiscoveryModels/FilterOption.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryFilterOption.cs index 1b93b842..0636c667 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/FilterOption.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryFilterOption.cs @@ -26,14 +26,14 @@ using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { - public class FilterOption + public class DiscoveryFilterOption { [XmlAttribute("name")] public string Name { get; set; } [XmlElement("localised-name")] - public LocalisedName LocalisedName { get; set; } + public DiscoveryLocalisedName LocalisedName { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/LocalisedName.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryLocalisedName.cs similarity index 95% rename from CCM.DiscoveryApi/Models/DiscoveryModels/LocalisedName.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryLocalisedName.cs index c30896ef..034e7478 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/LocalisedName.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryLocalisedName.cs @@ -26,9 +26,9 @@ using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { - public class LocalisedName + public class DiscoveryLocalisedName { [XmlText] public string Value { get; set; } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/Profile.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryProfile.cs similarity index 92% rename from CCM.DiscoveryApi/Models/DiscoveryModels/Profile.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryProfile.cs index e790ebb3..f764e670 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/Profile.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryProfile.cs @@ -26,12 +26,12 @@ using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { /// /// Profile entity /// - public class Profile + public class DiscoveryProfile { [XmlAttribute("name")] public string Name { get; set; } @@ -40,6 +40,6 @@ public class Profile public string Sdp { get; set; } [XmlElement("localised-name")] - public LocalisedName LocalisedName { get; set; } + public DiscoveryLocalisedName LocalisedName { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/SrDiscovery.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryResponse.cs similarity index 87% rename from CCM.DiscoveryApi/Models/DiscoveryModels/SrDiscovery.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryResponse.cs index 919e43eb..37eae675 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/SrDiscovery.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryResponse.cs @@ -27,24 +27,24 @@ using System.Collections.Generic; using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { /// /// SR Discovery entity /// [XmlRoot("sr-discovery", Namespace = "", IsNullable = false)] - public class SrDiscovery + public class DiscoveryResponse { [XmlArray("profiles")] [XmlArrayItem("profile", IsNullable = false)] - public List Profiles { get; set; } + public List Profiles { get; set; } [XmlArray("filters")] [XmlArrayItem("filter", IsNullable = false)] - public List Filters { get; set; } + public List Filters { get; set; } [XmlArray("user-agents")] [XmlArrayItem("user-agent")] - public List UserAgents { get; set; } + public List UserAgents { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/UserAgent.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgent.cs similarity index 89% rename from CCM.DiscoveryApi/Models/DiscoveryModels/UserAgent.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgent.cs index 86a74f2d..b5347f15 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/UserAgent.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgent.cs @@ -27,9 +27,9 @@ using System.Collections.Generic; using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { - public class UserAgent + public class DiscoveryUserAgent { [XmlAttribute("sip-id")] public string SipId { get; set; } @@ -39,10 +39,10 @@ public class UserAgent [XmlArray("profile-rec")] [XmlArrayItem("profile-ref")] - public List ProfileRec { get; set; } + public List ProfileRec { get; set; } [XmlArray("meta-data")] [XmlArrayItem("data")] - public List MetaData { get; set; } + public List MetaData { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/UserAgentMetaData.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentMetaData.cs similarity index 91% rename from CCM.DiscoveryApi/Models/DiscoveryModels/UserAgentMetaData.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentMetaData.cs index 906259ac..54c40cfa 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/UserAgentMetaData.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentMetaData.cs @@ -26,12 +26,12 @@ using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { - public class UserAgentMetaData + public class DiscoveryUserAgentMetaData { [XmlElement("localised-value")] - public LocalisedName LocalisedName { get; set; } + public DiscoveryLocalisedName LocalisedName { get; set; } [XmlAttribute("key")] public string Key { get; set; } diff --git a/CCM.DiscoveryApi/Models/DiscoveryModels/UserAgentProfileRef.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentProfileRef.cs similarity index 94% rename from CCM.DiscoveryApi/Models/DiscoveryModels/UserAgentProfileRef.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentProfileRef.cs index 27ee61cc..e50cb3be 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryModels/UserAgentProfileRef.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentProfileRef.cs @@ -26,9 +26,9 @@ using System.Xml.Serialization; -namespace CCM.DiscoveryApi.Models.DiscoveryModels +namespace CCM.DiscoveryApi.Models.Discovery { - public class UserAgentProfileRef + public class DiscoveryUserAgentProfileRef { [XmlAttribute("name")] public string Name { get; set; } diff --git a/CCM.DiscoveryApi/Models/SrDiscoveryParameters.cs b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentRequest.cs similarity index 95% rename from CCM.DiscoveryApi/Models/SrDiscoveryParameters.cs rename to CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentRequest.cs index 6f038460..41ec551b 100644 --- a/CCM.DiscoveryApi/Models/SrDiscoveryParameters.cs +++ b/CCM.DiscoveryApi/Models/Discovery/DiscoveryUserAgentRequest.cs @@ -26,9 +26,9 @@ using System.Collections.Generic; -namespace CCM.DiscoveryApi.Models +namespace CCM.DiscoveryApi.Models.Discovery { - public class SrDiscoveryParameters + public class DiscoveryUserAgentRequest { public string Caller { get; set; } public string Callee { get; set; } diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/Filters/FilterV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2Filter.cs similarity index 91% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/Filters/FilterV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2Filter.cs index 640cc355..9c7b01fc 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/Filters/FilterV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2Filter.cs @@ -27,14 +27,14 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.Filters +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class FilterV2 + public class DiscoveryV2Filter { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("options")] - public List Options { get; set; } + public List Options { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/Filters/FilterOptionV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2FilterOption.cs similarity index 94% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/Filters/FilterOptionV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2FilterOption.cs index a9614f01..081f0353 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/Filters/FilterOptionV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2FilterOption.cs @@ -26,9 +26,9 @@ using Newtonsoft.Json; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.Filters +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class FilterOptionV2 + public class DiscoveryV2FilterOption { [JsonProperty("name")] public string Name { get; set; } diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/Profiles/ProfileDtoV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2Profile.cs similarity index 94% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/Profiles/ProfileDtoV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2Profile.cs index 84f1c690..9052b6b8 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/Profiles/ProfileDtoV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2Profile.cs @@ -26,12 +26,13 @@ using Newtonsoft.Json; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.Profiles +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class ProfileDtoV2 + public class DiscoveryV2Profile { [JsonProperty("name")] public string Name { get; set; } + [JsonProperty("sdp")] public string Sdp { get; set; } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentDtoV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgent.cs similarity index 92% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentDtoV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgent.cs index 5fc5281e..53175751 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentDtoV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgent.cs @@ -27,9 +27,9 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.UserAgents +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class UserAgentDtoV2 + public class DiscoveryV2UserAgent { [JsonProperty("sipId")] public string SipId { get; set; } @@ -41,6 +41,6 @@ public class UserAgentDtoV2 public List Profiles { get; set; } [JsonProperty("metadata")] - public List MetaData { get; set; } + public List MetaData { get; set; } } } diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/KeyValuePairDtoV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentMetaData.cs similarity index 91% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/KeyValuePairDtoV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentMetaData.cs index e7bca4c5..58acfa67 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/KeyValuePairDtoV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentMetaData.cs @@ -26,16 +26,17 @@ using Newtonsoft.Json; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.UserAgents +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class KeyValuePairDtoV2 + public class DiscoveryV2UserAgentMetaData { [JsonProperty("key")] public string Key { get; set; } + [JsonProperty("value")] public string Value { get; set; } - public KeyValuePairDtoV2(string key, string value) + public DiscoveryV2UserAgentMetaData(string key, string value) { Key = key; Value = value; diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentSearchParamsV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentRequest.cs similarity index 94% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentSearchParamsV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentRequest.cs index f8d5ad44..54f02b46 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentSearchParamsV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentRequest.cs @@ -26,9 +26,9 @@ using System.Collections.Generic; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.UserAgents +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class UserAgentSearchParamsV2 + public class DiscoveryV2UserAgentRequest { public string Caller { get; set; } public string Callee { get; set; } diff --git a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentsResultV2.cs b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentsResponse.cs similarity index 85% rename from CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentsResultV2.cs rename to CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentsResponse.cs index d1c231d3..072ff53f 100644 --- a/CCM.DiscoveryApi/Models/DiscoveryV2Models/UserAgents/UserAgentsResultV2.cs +++ b/CCM.DiscoveryApi/Models/DiscoveryV2/DiscoveryV2UserAgentsResponse.cs @@ -25,17 +25,16 @@ */ using System.Collections.Generic; -using CCM.DiscoveryApi.Models.DiscoveryV2Models.Profiles; using Newtonsoft.Json; -namespace CCM.DiscoveryApi.Models.DiscoveryV2Models.UserAgents +namespace CCM.DiscoveryApi.Models.DiscoveryV2 { - public class UserAgentsResultV2 + public class DiscoveryV2UserAgentsResponse { [JsonProperty("profiles")] - public List Profiles { get; set; } + public List Profiles { get; set; } [JsonProperty("userAgents")] - public List UserAgents { get; set; } + public List UserAgents { get; set; } } } diff --git a/CCM.DiscoveryApi/Program.cs b/CCM.DiscoveryApi/Program.cs new file mode 100644 index 00000000..10580146 --- /dev/null +++ b/CCM.DiscoveryApi/Program.cs @@ -0,0 +1,58 @@ +using System; +using System.Security.Authentication; +using CCM.DiscoveryApi.Models; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using NLog; +using NLog.Extensions.Logging; +using NLog.Web; + +namespace CCM.DiscoveryApi +{ + public class Program + { + public static void Main(string[] args) + { + var config = new ConfigurationBuilder() + .SetBasePath(System.IO.Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build(); + LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog")); + + var logger = NLogBuilder.ConfigureNLog(LogManager.Configuration).GetCurrentClassLogger(); + try + { + logger.Info("Starting application Discovery"); + CreateHostBuilder(args).Build().Run(); + } + catch (Exception exception) + { + logger.Error(exception, "Stopped Discovery because of exception"); + throw; + } + finally + { + // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) + NLog.LogManager.Shutdown(); + } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + // Bind application settings from appsettings.json + services.Configure(hostContext.Configuration.GetSection("App")); + }) + .ConfigureAppConfiguration(config => + { + //config.AddJsonFile("appsettings.json").AddCommandLine(args, replacement) + config.AddJsonFile("buildinformation.json"); + }) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/CCM.DiscoveryApi/Properties/AssemblyInfo.cs b/CCM.DiscoveryApi/Properties/AssemblyInfo.cs deleted file mode 100644 index ebb46268..00000000 --- a/CCM.DiscoveryApi/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("CCM.DiscoveryApi")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Sveriges Radio AB")] -[assembly: AssemblyProduct("CCM.DiscoveryApi")] -[assembly: AssemblyCopyright("Copyright © Sveriges Radio AB 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("1ff56742-8ca8-4017-8933-860c7db75d6b")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CCM.DiscoveryApi/Properties/launchSettings.json b/CCM.DiscoveryApi/Properties/launchSettings.json new file mode 100644 index 00000000..520d1ba5 --- /dev/null +++ b/CCM.DiscoveryApi/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:49605", + "sslPort": 44342 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "CCM.DiscoveryApi": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/CCM.DiscoveryApi/Services/DiscoveryHttpService.cs b/CCM.DiscoveryApi/Services/DiscoveryHttpService.cs index 5d3f6416..f50be550 100644 --- a/CCM.DiscoveryApi/Services/DiscoveryHttpService.cs +++ b/CCM.DiscoveryApi/Services/DiscoveryHttpService.cs @@ -30,73 +30,102 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; -using System.Web.Http; +using Microsoft.AspNetCore.Mvc; using CCM.Core.Entities.Discovery; -using CCM.DiscoveryApi.Infrastructure; -using Newtonsoft.Json; using NLog; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; +using System.Text.Json; +using System.Net.Http.Headers; +using CCM.DiscoveryApi.Models; namespace CCM.DiscoveryApi.Services { /// - /// Retreives discovery data via CCM's REST service + /// Retrieves discovery data via CCM's REST service /// - public class DiscoveryHttpService : ApiController, IDiscoveryHttpService + public class DiscoveryHttpService : ControllerBase, IDiscoveryHttpService { protected static readonly Logger log = LogManager.GetCurrentClassLogger(); + private readonly ApplicationSettingsDiscovery _configuration; + + public DiscoveryHttpService(IOptions configuration) + { + _configuration = configuration.Value; + } + private Uri GetUrl(string action) { - return new Uri(ApplicationSettings.CcmHost, $"api/authenticateddiscovery/{action}"); + return new Uri($"{_configuration.CcmHost}/api/authenticateddiscovery/{action}"); } - public async Task> GetFiltersAsync(HttpRequestMessage originalRequest) + public async Task> GetFiltersAsync(HttpRequest originalRequest) { var url = GetUrl("filters"); return await Send>(url, HttpMethod.Get, originalRequest); } - public async Task> GetProfilesAsync(HttpRequestMessage originalRequest) + public async Task> GetProfilesAsync(HttpRequest originalRequest) { var url = GetUrl("profiles"); return await Send>(url, HttpMethod.Get, originalRequest); } - public async Task GetUserAgentsAsync(UserAgentSearchParamsDto searchParams, HttpRequestMessage originalRequest) + public async Task GetUserAgentsAsync(UserAgentSearchParamsDto searchParams, HttpRequest originalRequest) { var url = GetUrl("useragents"); return await Send(url, HttpMethod.Post, originalRequest, searchParams); } - private async Task Send(Uri url, HttpMethod method, HttpRequestMessage originalRequest, object data = null) + private async Task Send(Uri url, HttpMethod method, HttpRequest originalRequest, object data = null) { log.Debug("Getting discovery data from {0}", url); - using (var client = new HttpClient()) + var authReqHeader = AuthenticationHeaderValue.Parse(originalRequest.Headers["Authorization"]); + + if (string.IsNullOrEmpty(authReqHeader.Parameter)) { - HttpContent content = data != null ? - new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json") : null; + throw new Exception("No authorization for discovery"); + } + var request = new HttpRequestMessage(method, url); + request.Headers.Add("Accept", "application/json"); + + HttpContent content = data != null ? new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json") : null; + request.Content = content; + + HttpClientHandler handler = new HttpClientHandler(); + handler.AllowAutoRedirect = false; + HttpClient client = new HttpClient(handler); + + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(AuthenticationSchemes.Basic.ToString(), authReqHeader.Parameter); + + var response = await client.SendAsync(request); - var request = new HttpRequestMessage(method, url) {Content = content}; - request.Headers.Authorization = originalRequest.Headers.Authorization; + if (!response.IsSuccessStatusCode) + { + log.Debug("Failed to get discovery data. Response: {0} {1}", response.StatusCode, response.ReasonPhrase); + throw new Exception($"Failed to get discovery data. Response: {response.StatusCode} {response.ReasonPhrase}"); + } - HttpResponseMessage response = await client.SendAsync(request); + if (response.Content is object && response.Content.Headers.ContentType.MediaType == "application/json") + { + var contentStream = await response.Content.ReadAsStreamAsync(); - if (!response.IsSuccessStatusCode) + try { - if (response.StatusCode == HttpStatusCode.Forbidden) - { - log.Debug("Failed to get discovery data. Response: {0} {1}", response.StatusCode, response.ReasonPhrase); - } - else - { - log.Warn("Failed to get discovery data. Response: {0} {1}", response.StatusCode, response.ReasonPhrase); - } - throw new HttpResponseException(response); + return await JsonSerializer.DeserializeAsync(contentStream, new JsonSerializerOptions { IgnoreNullValues = true, PropertyNameCaseInsensitive = true }); + } + catch (JsonException) // Invalid JSON + { + Console.WriteLine("Invalid JSON."); } - - return await response.Content.ReadAsAsync(); } - } + else + { + Console.WriteLine("HTTP Response was invalid and cannot be deserialised."); + } + return default(T); + } } } diff --git a/CCM.DiscoveryApi/Services/IDiscoveryHttpService.cs b/CCM.DiscoveryApi/Services/IDiscoveryHttpService.cs index 2f52b2c4..b54d7785 100644 --- a/CCM.DiscoveryApi/Services/IDiscoveryHttpService.cs +++ b/CCM.DiscoveryApi/Services/IDiscoveryHttpService.cs @@ -25,16 +25,16 @@ */ using System.Collections.Generic; -using System.Net.Http; using System.Threading.Tasks; using CCM.Core.Entities.Discovery; +using Microsoft.AspNetCore.Http; namespace CCM.DiscoveryApi.Services { public interface IDiscoveryHttpService { - Task> GetFiltersAsync(HttpRequestMessage originalRequest); - Task> GetProfilesAsync(HttpRequestMessage originalRequest); - Task GetUserAgentsAsync(UserAgentSearchParamsDto searchParams, HttpRequestMessage originalRequest); + Task> GetFiltersAsync(HttpRequest originalRequest); + Task> GetProfilesAsync(HttpRequest originalRequest); + Task GetUserAgentsAsync(UserAgentSearchParamsDto searchParams, HttpRequest originalRequest); } } diff --git a/CCM.DiscoveryApi/Startup.cs b/CCM.DiscoveryApi/Startup.cs new file mode 100644 index 00000000..c59ada34 --- /dev/null +++ b/CCM.DiscoveryApi/Startup.cs @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018 Sveriges Radio AB, Stockholm, Sweden + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Linq; +using CCM.Core.Helpers; +using CCM.DiscoveryApi.Authentication; +using CCM.DiscoveryApi.Services; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Serialization; + +namespace CCM.DiscoveryApi +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + /// + public void ConfigureServices(IServiceCollection services) + { + // Application deploy information + services.Configure(Configuration.GetSection("Build")); + + // Add Cross Origin support + services.AddCors(); + + // Authentication and authorization (Basic) + // The registered authentication handlers and their configuration options are called "schemes". + // An authentication scheme is named when the authentication service is configured during authentication. + services.AddAuthentication("BasicAuthenticationDiscoveryV2") // Default + .AddScheme("BasicAuthenticationDiscoveryV2", null) + .AddScheme("BasicAuthenticationDiscoveryV1", null); + + services.AddAuthorization(opt => + { + opt.AddPolicy("BasicAuthenticationDiscoveryV2", policy => + { + policy.AddAuthenticationSchemes("BasicAuthenticationDiscoveryV2"); + policy.RequireAuthenticatedUser(); + }); + opt.AddPolicy("BasicAuthenticationDiscoveryV1", policy => + { + policy.AddAuthenticationSchemes("BasicAuthenticationDiscoveryV1"); + policy.RequireAuthenticatedUser(); + }); + }); + + services.AddControllers(options => + { + options.RespectBrowserAcceptHeader = true; // false by default + + //var xmlWriterSettings = options.OutputFormatters + // .OfType() + // .Single() + // .WriterSettings; + + //xmlWriterSettings.Indent = false; + }) + .AddNewtonsoftJson(options => + { + options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + }) + .AddXmlSerializerFormatters() + .AddXmlDataContractSerializerFormatters(); + + // Used to forward requests to the Discovery API's + services.AddHttpClient(); + + // Register dependency injection + services.AddScoped(); + } + + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// + /// + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger logger) + { + logger.LogInformation($"#################### CCM Discovery starting up..."); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Home/Error"); + app.UseHsts(); + } + + //app.UseHttpsRedirection(); + + // Set global CORS policy + app.UseCors(x => x + .AllowAnyMethod() + .AllowAnyHeader() + .SetIsOriginAllowed(origin => true) + .AllowCredentials()); + + // Who are you? (Basic authentication) + app.UseAuthentication(); + + // Find out routing + app.UseRouting(); + + //Are you allowed? + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + + // Default route + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); + + // Api routes + endpoints.MapControllerRoute( + name: "DiscoveryApi", + pattern: "api/{controller=Home}/{action=Index}/{id?}"); + }); + } + } +} diff --git a/CCM.DiscoveryApi/Web.Debug.config b/CCM.DiscoveryApi/Web.Debug.config deleted file mode 100644 index 8e9a3d10..00000000 --- a/CCM.DiscoveryApi/Web.Debug.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/CCM.DiscoveryApi/Web.Release.config b/CCM.DiscoveryApi/Web.Release.config deleted file mode 100644 index c1e7efe9..00000000 --- a/CCM.DiscoveryApi/Web.Release.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/CCM.DiscoveryApi/Web.config b/CCM.DiscoveryApi/Web.config deleted file mode 100644 index 451289ba..00000000 --- a/CCM.DiscoveryApi/Web.config +++ /dev/null @@ -1,93 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.DiscoveryApi/appsettings.json b/CCM.DiscoveryApi/appsettings.json new file mode 100644 index 00000000..a16469b1 --- /dev/null +++ b/CCM.DiscoveryApi/appsettings.json @@ -0,0 +1,51 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "App": { + "CcmHost": "" + }, + "NLog": { + "internalLogLevel": "Info", + "internalLogFile": "/var/log/internal-discovery-nlog.log", + "extensions": { + "NLog.Web.AspNetCore": { + "assembly": "NLog.Web.AspNetCore" + } + }, + "targets": { + "allfile": { + "type": "File", + "fileName": "/var/log/discovery-all-${shortdate}.log", + "layout": "${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" + }, + "ownFile-web": { + "type": "File", + "fileName": "/var/log/discovery-own-${shortdate}.log", + "layout": "${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" + } + }, + "rules": [ + { + "logger": "*", + "minLevel": "Trace", + "writeTo": "allfile" + }, + { + "logger": "Microsoft.*", + "maxLevel": "Info", + "final": "true" + }, + { + "logger": "*", + "minLevel": "Trace", + "writeTo": "ownFile-web" + } + ] + } +} diff --git a/CCM.DiscoveryApi/buildinformation.json b/CCM.DiscoveryApi/buildinformation.json new file mode 100644 index 00000000..f0779f11 --- /dev/null +++ b/CCM.DiscoveryApi/buildinformation.json @@ -0,0 +1,9 @@ +{ + "Build": { + "Name": "APP_NAME", + "ReleaseDate": "APP_RELEASE_DATE", + "Version": "APP_VERSION", + "Environment": "APP_ENVIRONMENT", + "Server": "APP_SERVER" + } +} diff --git a/CCM.DiscoveryApi/favicon.ico b/CCM.DiscoveryApi/favicon.ico deleted file mode 100644 index a3a79998..00000000 Binary files a/CCM.DiscoveryApi/favicon.ico and /dev/null differ diff --git a/CCM.DiscoveryApi/logs/web.config b/CCM.DiscoveryApi/logs/web.config deleted file mode 100644 index 881cd834..00000000 --- a/CCM.DiscoveryApi/logs/web.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.DiscoveryApi/packages.config b/CCM.DiscoveryApi/packages.config deleted file mode 100644 index 3d22989f..00000000 --- a/CCM.DiscoveryApi/packages.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CCM.Frontpage/package.json b/CCM.Frontpage/package.json new file mode 100644 index 00000000..39f2ca0c --- /dev/null +++ b/CCM.Frontpage/package.json @@ -0,0 +1,31 @@ +{ + "name": "ccm-frontpage", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "build": "webpack --mode=development --watch", + "release": "webpack --mode=production", + "publish": "npm run release && dotnet publish -c Release" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@microsoft/signalr": "^5.0.0", + "@microsoft/signalr-protocol-msgpack": "^5.0.0", + "d3": "^7.0.0" + }, + "devDependencies": { + "@types/node": "^14.14.31", + "clean-webpack-plugin": "3.0.0", + "css-loader": "^5.2.6", + "file-loader": "^6.2.0", + "less": "^4.1.1", + "less-loader": "7.3.0", + "mini-css-extract-plugin": "^1.6.0", + "ts-loader": "6.2.1", + "typescript": "3.7.5", + "webpack": "4.41.5", + "webpack-cli": "3.3.10" + } +} diff --git a/CCM.Frontpage/src/ccm-form.ts b/CCM.Frontpage/src/ccm-form.ts new file mode 100644 index 00000000..387b4ac0 --- /dev/null +++ b/CCM.Frontpage/src/ccm-form.ts @@ -0,0 +1,100 @@ +// import AnimationView from "./service/Animation"; +// import AudioPlayer from "./service/AudioInterface"; +// import AnimationView from "./service/AnimationView"; +import { ColorPicker } from "./utils/ColorPicker"; +import Events from "./utils/Events"; +import { FilterList } from "./utils/FilterList"; +import PasswordGenerator from "./utils/PasswordGenerator"; +import { SessionDescription } from "./utils/SessionDescriptionProtocolUtil"; +import { Sortable } from "./utils/Sortable"; +import Tool from './utils/Tools'; + +export class Application { + // private listener: AnimationView; + // private audio: AudioPlayer; + // private animation: AnimationView; + + private event: Events = new Events(); + + constructor() { + console.log("Initiated application"); + + // this.listener = AnimationView.getInstance(); + + try { + Sortable("sortable-selection", function(items) { + if (!items) { + return; + } + for (let i = 0; i < items.length; i++) { + const element = items[i].getElementsByClassName("sortIndex")[0]; + if (element) { + element.setAttribute("value", `${i}`); + } + } + }); + } catch(error) { + console.warn(error); + } + + try { + FilterList("filterable-selection"); + } catch(error) { + console.warn(error); + } + + try { + ColorPicker("colorpicker-selection", "colorpicker-preview"); + } catch(error) { + console.warn(error); + } + + const pass = new PasswordGenerator(); + try { + const userPwButton = Tool.$dom("pwGen"); + if (userPwButton) { + Tool.$event(userPwButton, "click", () => { + const password = pass.generateUserPassword(); + (Tool.$dom("Password") as any).value = password; + (Tool.$dom("PasswordConfirm") as any).value = password; + (Tool.$dom("generatedPassword") as any).value = password; + Tool.$dom("generatedWrapper").classList.remove("hidden"); + }); + } + } catch(error) { + console.warn(error); + } + + try { + this.SessionDescriptionParse("sdp-field"); + } catch(error) { + console.warn(error); + } + } + + private SessionDescriptionParse(targetId: string) { + const sdpElement = document.getElementById(targetId); + if (sdpElement == null) { + throw new Error(`Could not bind any SDP fields '.${targetId}'`); + } + + sdpElement.addEventListener("keyup", function(ev: any) { + const text = ev.target.value; + console.log({ev, text}); + + const ret = SessionDescription.parse(text); + console.log(ret); + console.dir(ret.parsed) + }); + + } +} + +export default class Main { + public static load() { + console.log("Initiated form Main"); + const app = new Application(); + } +} + +Main.load(); diff --git a/CCM.Frontpage/src/ccm-main.ts b/CCM.Frontpage/src/ccm-main.ts new file mode 100644 index 00000000..6b00f8a2 --- /dev/null +++ b/CCM.Frontpage/src/ccm-main.ts @@ -0,0 +1,243 @@ +import Tool from './utils/Tools'; + +export class Application { + constructor() { + console.log("Initiated application"); + + // try { + // // Mobile sized menu system + // Tool.$eventByClass("navbar-toggle", "click", (e) => { + // console.log("Pressed: ", e); + // const elements = document.getElementsByClassName("ccm-top-navbar-container"); + // for(let i = 0; i < elements.length; i++) { + // elements[i].classList.toggle("ccm-top-navbar-container--expanded"); + // } + // }); + // } catch(error) { + // console.error(error); + // } + + try { + // Dropdowns and accordions + let accordions = document.querySelectorAll("[data-toggle]"); + accordions.forEach((item) => { + if ((item as any).dataset.toggle == "dropdown") { + Tool.$event(item, "click", (e) => { + e.preventDefault(); + e.stopPropagation(); + if (e.target.parentNode) { + e.target.parentNode.classList.toggle("open"); + } + }); + } else { + Tool.$event(item, "click", (eve) => { + eve.preventDefault(); + eve.stopPropagation(); + if ((item as any).getAttribute("href")) { + const col = (item as any).href; + const idd = col.substr(col.indexOf("#") + 1, col.lenght); + if (idd) { + Tool.$dom(idd).classList.toggle("open"); + eve.target.classList.toggle("open"); + } + } + }); + } + }); + } catch(error) { + console.error(error); + } + + this.setupStartpage(); + + this.setupMenu(); + + this.setupTabs(); + + (function() { + const searchbar = Tool.$dom("searchField"); + if (searchbar) { + searchbar.focus(); + } + })(); + } + + private setupStartpage() { + try { + Tool.$event("tab-region-btn", "click", (eve) => { + Tool.$dom("tab-codectype-filter").style.display = "none"; + Tool.$dom("tab-category-filter").style.display = "none"; + Tool.$dom("tab-region-filter").style.display = "block"; + + Tool.$dom("tab-region-btn").classList.add("active"); + Tool.$dom("tab-category-btn").classList.remove("active"); + Tool.$dom("tab-codectype-btn").classList.remove("active"); + }); + + Tool.$event("tab-codectype-btn", "click", (eve) => { + Tool.$dom("tab-codectype-filter").style.display = "block"; + Tool.$dom("tab-category-filter").style.display = "none"; + Tool.$dom("tab-region-filter").style.display = "none"; + + Tool.$dom("tab-region-btn").classList.remove("active"); + Tool.$dom("tab-category-btn").classList.remove("active"); + Tool.$dom("tab-codectype-btn").classList.add("active"); + }); + + Tool.$event("tab-category-btn", "click", (eve) => { + Tool.$dom("tab-codectype-filter").style.display = "none"; + Tool.$dom("tab-region-filter").style.display = "none"; + Tool.$dom("tab-category-filter").style.display = "block"; + + Tool.$dom("tab-codectype-btn").classList.remove("active"); + Tool.$dom("tab-region-btn").classList.remove("active"); + Tool.$dom("tab-category-btn").classList.add("active"); + }); + + } catch(error) { + console.error(error) + } + } + + private setupMenu() { + + function collapseSection(element) { + // get the height of the element's inner content, regardless of its actual size + const sectionHeight = element.scrollHeight; + + // temporarily disable all css transitions + const elementTransition = element.style.transition; + element.style.transition = ""; + + // on the next frame (as soon as the previous style change has taken effect), + // explicitly set the element's height to its current pixel height, so we + // aren't transitioning out of 'auto' + requestAnimationFrame(function() { + element.style.height = sectionHeight + "px"; + element.style.transition = elementTransition; + + // on the next frame (as soon as the previous style change has taken effect), + // have the element transition to height: 0 + requestAnimationFrame(function() { + element.style.height = 0 + "px"; + }); + }); + + // mark the section as "currently collapsed" + element.setAttribute("data-collapsed", "true"); + + window.removeEventListener("scroll", clickOutsideMenu, false); + Tool.$dom("admin-menu-cover").classList.remove("open"); + } + + function clickOutsideMenu(ev: any) { + const section = document.querySelector(".section.collapsible"); + collapseSection(section); + } + + function expandSection(element) { + // get the height of the element's inner content, regardless of its actual size + const sectionHeight = element.scrollHeight + 80; + + // have the element transition to the height of its inner content + element.style.height = sectionHeight + "px"; + + // when the next css transition finishes (which should be the one we just triggered) + element.addEventListener("transitionend", function(e) { + // remove this event listener so it only gets triggered once + console.log(arguments[0]) + element.removeEventListener("transitionend", arguments[0].callee); + + // remove "height" from the element's inline styles, so it can return to its initial value + //element.style.height = null; + }); + + // mark the section as "currently not collapsed" + element.setAttribute("data-collapsed", "false"); + + // determine if the menu is filling the whole screen then disable scroll + if (window.innerHeight >= sectionHeight) { + window.addEventListener("scroll", clickOutsideMenu, false); + } + + Tool.$dom("admin-menu-cover").classList.add("open"); + } + + function clickOnAdminMenu(e) { + const section = document.querySelector(".section.collapsible"); + const isCollapsed = section.getAttribute("data-collapsed") === "true"; + + if (isCollapsed) { + expandSection(section) + section.setAttribute("data-collapsed", "false") + } else { + collapseSection(section) + } + } + + let collapsableSection = document.querySelector(".section.collapsible"); + if (collapsableSection) { + collapsableSection.setAttribute("data-collapsed", "true"); + } + + let navigationAdminBtn = document.querySelector("#admin-navigation-btn"); + if (navigationAdminBtn) { + //navigationAdminBtn.addEventListener("click", clickOnAdminMenu); + Tool.$event(navigationAdminBtn, "click", clickOnAdminMenu); + } + + Tool.$event("admin-menu-cover", "click", clickOutsideMenu); + } + + private setupTabs() { + const tabs = Array.from(document.querySelectorAll('[data-target-tab]')); + if (!tabs || tabs.length === 0) { + console.warn("No tabs found on this page"); + return; + } + + tabs.forEach((tab) => { + Tool.$event(tab, "click", function(el) { + try { + const tabId = this.dataset.targetTab; + if (!tabId) { + console.warn(`No target tab could be found to display for '${tabId}'`); + return; + } + + const parent = Array.from(this.parentNode.parentNode.children); + if (!parent) { + console.warn("Could not find parent tab pane"); + return; + } + + parent.forEach((lm) => { + const li = (lm as any).querySelector("a").dataset.targetTab; + if (!li) { + console.warn("No parent li element"); + return; + } + if (li === tabId) { + (lm as any).classList.add("active"); + Tool.$dom(li).classList.add("active"); + } else { + (lm as any).classList.remove("active"); + Tool.$dom(li).classList.remove("active"); + } + }); + } catch(err) { + console.error(err) + } + }); + }); + } +} + +export default class Main { + public static load() { + console.log("Initiated main"); + const app = new Application(); + } +} + +Main.load(); diff --git a/CCM.Frontpage/src/ccm-statistics.ts b/CCM.Frontpage/src/ccm-statistics.ts new file mode 100644 index 00000000..9c2a3205 --- /dev/null +++ b/CCM.Frontpage/src/ccm-statistics.ts @@ -0,0 +1,458 @@ +import Tool from "./utils/Tools"; +import * as d3 from "d3"; + +export class StatisticsView { + constructor() { + + // $('#startdatetimepicker').datetimepicker({ format: 'YYYY-MM-DD', date: startDate.toISOString() }); + // $('#enddatetimepicker').datetimepicker({ format: 'YYYY-MM-DD', date: endDate.toISOString() }); + + // $("#startdatetimepicker").on("dp.change", function (e) { + // $('#enddatetimepicker').data("DateTimePicker").minDate(e.date); + // }); + // $("#enddatetimepicker").on("dp.change", function (e) { + // $('#startdatetimepicker').data("DateTimePicker").maxDate(e.date); + // }); + + this.setDatePickers(); + + Tool.$event("locationSearchBtn", "click", this.locationSearch.bind(this)); + Tool.$event("regionSearchBtn", "click", this.regionSearch.bind(this)); + Tool.$event("sipAccountsSearchBtn", "click", this.sipAccountsSearch.bind(this)); + Tool.$event("codecTypesSearchBtn", "click", this.codecTypesSearch.bind(this)); + Tool.$event("categorySearchBtn", "click", this.categorySearch.bind(this)); + } + + setDatePickers() { + let endDate = new Date(); + endDate.setHours(0); + endDate.setMinutes(0); + endDate.setSeconds(0); + endDate.setMilliseconds(0); + + let startDate = new Date(endDate.toISOString()); + startDate.setDate(startDate.getDate() - 30); + + let adjustedEndDate = endDate.toString().split(/\+|-/)[0]; + + Tool.$dom("startDate").value = startDate.toISOString().split('T')[0]; + Tool.$dom("endDate").value = new Date(adjustedEndDate).toISOString().split('T')[0]; + + Tool.$event("startDate", "change", (event) => { + console.log({event}) + }); + } + + locationSearch() { + Tool.$dom("locationSearchBtn").setAttribute("disabled", "true"); + + const queryParams = { + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + regionId: Tool.$dom("Regions").value, + ownerId: Tool.$dom("Owners").value, + codecTypeId: Tool.$dom("CodecTypes").value + }; + + const sim24HourParams = { + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + regionId: Tool.$dom("Regions").value, + locationId: "00000000-0000-0000-0000-000000000000" + }; + + Tool.$dom("locationNumberOfCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/LocationNumberOfCallsView", queryParams).then((content) => { + Tool.$dom("locationNumberOfCallsChartDiv").innerHTML = content; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("locationNumberOfCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }); + + Tool.$dom("locationTotalTimeForCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/LocationTotalTimeForCallsView", queryParams).then((content) => { + Tool.$dom("locationTotalTimeForCallsChartDiv").innerHTML = content; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("locationTotalTimeForCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }); + + Tool.$dom("locationMaxSimultaneousCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/LocationMaxSimultaneousCallsView", queryParams).then((content) => { + Tool.$dom("locationMaxSimultaneousCallsChartDiv").innerHTML = content; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("locationMaxSimultaneousCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }); + + Tool.$dom("locationSim24HourChartDiv").innerHTML = `
`; + Tool.$dom("locationSim24HourChartDataDiv").innerHTML = ""; + Tool.$fetchView("/Statistics/LocationSim24HourView", sim24HourParams).then((content) => { + Tool.$dom("locationSim24HourChartDiv").innerHTML = content; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + + Tool.$event("locationSim24HourSelect", "change", this.sim24HourSearch.bind(this)); + }).catch((error) => { + Tool.$dom("locationSim24HourChartDiv").innerHTML = `
${error}
`; + Tool.$dom("locationSearchBtn").removeAttribute("disabled"); + }); + } + + sim24HourSearch() { + Tool.$dom("locationSim24HourSelect").setAttribute("disabled", "true"); + + const sim24HourParams = { + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + regionId: Tool.$dom("Regions").value, + locationId: Tool.$dom("locationSim24HourSelect").value + }; + + Tool.$dom("locationSim24HourChartDataDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/LocationSim24HourViewData", sim24HourParams).then((content) => { + Tool.$dom("locationSim24HourChartDataDiv").innerHTML = content; + Tool.$dom("locationSim24HourSelect").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("locationSim24HourChartDataDiv").innerHTML = `
${error}
`; + Tool.$dom("locationSim24HourSelect").removeAttribute("disabled"); + }); + } + + regionSearch() { + Tool.$dom("regionSearchBtn").setAttribute("disabled", "true"); + + const queryParamsCalls = { + filterType: "Regions", + chartType: "NumberOfCalls", + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + filterId: Tool.$dom("regionRegions").value + }; + + Tool.$dom("regionNumberOfCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/RegionNumberOfCallsView", queryParamsCalls).then((content) => { + Tool.$dom("regionNumberOfCallsChartDiv").innerHTML = content; + Tool.$dom("regionSearchBtn").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("regionNumberOfCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("regionSearchBtn").removeAttribute("disabled"); + }); + } + + sipAccountsSearch() { + Tool.$dom("sipAccountsSearchBtn").setAttribute("disabled", "true"); + + const queryParamsCalls = { + filterType: "SipAccounts", + chartType: "NumberOfCalls", + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + filterId: Tool.$dom("sipAccountsAccounts").value + }; + + Tool.$dom("sipAccountsNumberOfCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/SipAccountNumberOfCallsView", queryParamsCalls).then((content) => { + Tool.$dom("sipAccountsNumberOfCallsChartDiv").innerHTML = content; + Tool.$dom("sipAccountsSearchBtn").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("sipAccountsNumberOfCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("sipAccountsSearchBtn").removeAttribute("disabled"); + }); + } + + codecTypesSearch() { + Tool.$dom("codecTypesSearchBtn").setAttribute("disabled", "true"); + + const queryParamsCalls = { + filterType: "CodecTypes", + chartType: "NumberOfCalls", + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + filterId: Tool.$dom("codecTypesCodecTypes").value + }; + + Tool.$dom("codecTypeNumberOfCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/CodecTypeNumberOfCallsView", queryParamsCalls).then((content) => { + Tool.$dom("codecTypeNumberOfCallsChartDiv").innerHTML = content; + Tool.$dom("codecTypesSearchBtn").removeAttribute("disabled"); + }).catch((error) => { + Tool.$dom("codecTypeNumberOfCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("codecTypesSearchBtn").removeAttribute("disabled"); + }); + } + + async categorySearch() { + + + const queryParamsCalls = { + filterType: "Categories", + chartType: "NumberOfCalls", + startDate: Tool.$dom("startDate").value, + endDate: Tool.$dom("endDate").value, + filterId: "" + }; + + // Number of call combinations per category itneraction + Tool.$dom("categoryNumberOfCallsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/CategoryCallNumberOfCallsView", queryParamsCalls).then(async (content) => { + Tool.$dom("categoryNumberOfCallsChartDiv").innerHTML = content; + Tool.$dom("categorySearchBtn").removeAttribute("disabled"); + + try { + const parameters = new URLSearchParams({ + startTime: Tool.$dom("startDate").value, + endTime: Tool.$dom("endDate").value + }); + const data = await fetch("/Statistics/GetCategoryStatistics?" + parameters.toString(), { + method: "POST", + body: JSON.stringify(parameters) + }); + const messenger = await data.json(); + console.log(messenger); + this.CreateBarChart(messenger); + //this.CreatePieChart(messenger); + //this.CreateTreeMap(messenger); + } catch(err) { + console.error(err); + } + }).catch((error) => { + Tool.$dom("categoryNumberOfCallsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("categorySearchBtn").removeAttribute("disabled"); + }); + + // Separated category items + Tool.$dom("categoryNumberOfItemsChartDiv").innerHTML = `
`; + Tool.$fetchView("/Statistics/CategoryNumberOfCallsView", queryParamsCalls).then(async (content) => { + Tool.$dom("categoryNumberOfItemsChartDiv").innerHTML = content; + Tool.$dom("categorySearchBtn").removeAttribute("disabled"); + + try { + const parameters = new URLSearchParams({ + startTime: Tool.$dom("startDate").value, + endTime: Tool.$dom("endDate").value + }); + // const data = await fetch("/Statistics/GetCategoryStatistics?" + parameters.toString(), { + // method: "POST", + // body: JSON.stringify(parameters) + // }); + // const messenger = await data.json(); + // console.log(messenger); + // // this.CreateBarChart(messenger); + // this.CreatePieChart(messenger); + } catch(err) { + console.error(err); + } + }).catch((error) => { + Tool.$dom("categoryNumberOfItemsChartDiv").innerHTML = `
${error}
`; + Tool.$dom("categorySearchBtn").removeAttribute("disabled"); + }); + + } + + CreatePieChart(data) { + var svg = d3.select("#bar-chart"); + svg.selectAll("*").remove(); + document.getElementById('errormessage').innerHTML = ""; + + if (data.length === 0) { + return document.getElementById('errormessage').innerHTML = '

' + "No data" + '

'; + } + var width = 450, height = 450, radius = Math.min(width, height) / 2; + + svg = d3.select("#bar-chart") + .attr("width", width) + .attr("height", height); + + var g = svg.append("g") + .attr("transform", "translate(" + width / 2 + "," + height / 1.8 + ")"); + + var color = d3.scaleOrdinal(d3.schemeCategory10); + + var pie = d3.pie().value(function (d) { + const objValue = Object.values(d); + return objValue[1]; + }); + + var path = d3.arc() + .outerRadius(radius - 50) + .innerRadius(0); + + var label = d3.arc() + .outerRadius(radius - 60) + .innerRadius(radius); + + var arc = g.selectAll(".arc") + .data(pie(data)) + .enter() + .append("g") + .attr("class", "arc"); + + arc.append("path") + .attr("d", path) + .attr("fill", function (d) { + console.log(d) + const first = Object.values(d.data); + const amount = Object.values(d.data); + return color(Object.values(first[0]) + " " + amount[1]) + }); + + arc.append("text") + .attr("transform", function (d) { + return "translate(" + label.centroid(d) + ")"; + }) + .text(function (d) { + const second = Object.values(d.data) + const amount = Object.values(d.data); + return (second[0] + " " + amount[1]); + }) + + let res = (Object.keys(data[0])[1]) + svg.append("g") + .attr("transform", "translate(" + (width / 2 - 120) + "," + 20 + ")") + .append("text") + .text(res) + .attr("class", "title") + .style("fill", "green") + .style("font-size", "23"); + } + + CreateTreeMap(data) { + + // set the dimensions and margins of the graph + var margin = {top: 10, right: 10, bottom: 10, left: 10}, + width = 445 - margin.left - margin.right, + height = 445 - margin.top - margin.bottom; + + // append the svg object to the body of the page + var svg = d3.select("#bar-chart") + .append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", + "translate(" + margin.left + "," + margin.top + ")"); + + // Give the data to this cluster layout: + var root = d3.hierarchy(data).sum(function(d){ return d.numberOfCalls }); + // Here the size of each leave is given in the 'value' field in input data + + // Then d3.treemap computes the position of each element of the hierarchy + d3.treemap() + .size([width, height]) + .padding(2) + (root) + + // use this information to add rectangles: + svg + .selectAll("rect") + .data(root.leaves()) + .enter() + .append("rect") + .attr('x', function (d) { return d.x0; }) + .attr('y', function (d) { return d.y0; }) + .attr('width', function (d) { return d.x1 - d.x0; }) + .attr('height', function (d) { return d.y1 - d.y0; }) + .style("stroke", "black") + .style("fill", "slateblue") + + // and to add the text labels + svg + .selectAll("text") + .data(root.leaves()) + .enter() + .append("text") + .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) + .attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower) + .text(function(d){ return d.data.name }) + .attr("font-size", "15px") + .attr("fill", "white") + + } + + CreateBarChart(dataset) { + var svg = d3.select("#bar-chart"); + + const margin = { + top: 20, + right: 50, + bottom: 80, + left: 50 + }; + + let width = +svg.attr("width") - margin.left - margin.right; + let height = +svg.attr("height") - margin.top - margin.bottom; + + svg.attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) + + var g = svg + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + var x = d3.scaleBand() + .rangeRound([0, width]) + .padding(0.1); + + var y = d3.scaleLinear() + .rangeRound([height, 0]); + + x.domain(dataset.map(function (d) { + console.log("x", d); + return d.category; + })) + + y.domain([0, d3.max(dataset, function (d) { + console.log("Num", d); + return Number(d.numberOfCalls); + })]); + + g.append("g") + .attr("transform", "translate(0," + height + ")") + .call(d3.axisBottom(x)) + .selectAll("text") + .style("text-anchor", "end") + .attr("dx", "-.8em") + .attr("dy", "-.55em") + .attr("transform", "rotate(-90)"); + + g.append("g") + .call(d3.axisLeft(y)) + .append("text") + .attr("fill", "#000") + .attr("transform", "rotate(-90)") + .attr("y", 6) + .attr("dy", "0.71em") + .attr("text-anchor", "end") + .text("NumberOfCalls"); + + g.selectAll(".bar") + .data(dataset) + .enter() + .append("rect") + .attr("class", "bar") + .attr("x", function (d) { + return x(d.category); + }) + .attr("y", function (d) { + return y(Number(d.numberOfCalls)); + }) + .attr("width", x.bandwidth()) + .attr("height", function (d) { + console.log("ddddddd", height, "#", d, "¤", y(Number(d.numberOfCalls)) ) + return height - y(Number(d.numberOfCalls)); + }); + } +} + +export default class Statistics { + public static load() { + console.log("Initiated Statistics"); + const app = new StatisticsView(); + } +} + +Statistics.load(); diff --git a/CCM.Frontpage/src/constants/signalrConnectionLevels.ts b/CCM.Frontpage/src/constants/signalrConnectionLevels.ts new file mode 100644 index 00000000..b9b4e3a9 --- /dev/null +++ b/CCM.Frontpage/src/constants/signalrConnectionLevels.ts @@ -0,0 +1,9 @@ +export enum SignalRConnectionLevels { + Unknown = 0, + Connecting = 0, + Connected = 1, + Reconnecting = 2, + Disconnected = 4, + Starting = 5, + Slow = 1, +} \ No newline at end of file diff --git a/CCM.Frontpage/src/service/Animation.ts b/CCM.Frontpage/src/service/Animation.ts new file mode 100644 index 00000000..45df6694 --- /dev/null +++ b/CCM.Frontpage/src/service/Animation.ts @@ -0,0 +1,19 @@ +// import Events from '../utils/Events'; + +// export default class AnimationView { + +// private event: Events = new Events(); + +// private static instance: AnimationView; +// public static getInstance(): AnimationView { +// if (AnimationView.instance == null) { +// AnimationView.instance = new AnimationView(); +// } +// return AnimationView.instance; +// } + +// private constructor() { +// const self = this; +// } + +// } diff --git a/CCM.Frontpage/src/service/NetCoreHubListener.ts b/CCM.Frontpage/src/service/NetCoreHubListener.ts new file mode 100644 index 00000000..76ffb645 --- /dev/null +++ b/CCM.Frontpage/src/service/NetCoreHubListener.ts @@ -0,0 +1,132 @@ +import * as signalR from "@microsoft/signalr"; +// const signalRMsgPack = require("@microsoft/signalr-protocol-msgpack"); +import { SignalRConnectionLevels } from "../constants/signalrConnectionLevels"; +import StringUtil from "../utils/StringUtil"; + +export default abstract class AspNetCoreHubListener { + + public connection: signalR.HubConnection; + public abstract readonly connectionOpenEventType: string; + + private hubName: string; + private serverUrl: string; + private hubReconnectDelay: number = 3000; + + private subscriptions: any[] = []; + + public onConnected: () => void; + public onDisconnected: () => void; + + constructor(serverUrlArg: string, hubNameArg: string) { + if (StringUtil.isNotNullOrEmpty(serverUrlArg) && StringUtil.isNotNullOrEmpty(hubNameArg)) { + this.initiate(serverUrlArg, hubNameArg); + } + } + + public initiate(serverUrlArg: string = "", hubNameArg: string = "") { + this.hubName = hubNameArg; + this.serverUrl = serverUrlArg; + + console.info("AspNetCoreHubListener for hub " + this.hubName + " on " + this.serverUrl); + + // Hub options + // serverTimeoutInMilliseconds: Timeout for server activity. If the server + // hasn't sent a message in this interval, the client considers the server + // disconnected and triggers the onclose event. This value must be large + // enough for a ping message to be sent from the server and received by the + // client within the timeout interval. The recommended value is a number at + // least double the server's KeepAliveInterval value to allow time for pings to arrive. + + // keepAliveIntervalInMilliseconds: Determines the interval at which the + // client sends ping messages. Sending any message from the client resets + // the timer to the start of the interval. If the client hasn't sent a message + // in the ClientTimeoutInterval set on the server, the server considers the + // client disconnected. + + let hubOptions = { + transport: signalR.HttpTransportType.WebSockets, + }; + + this.connection = new signalR.HubConnectionBuilder() + .withUrl(this.serverUrl + "/" + this.hubName, hubOptions) + // .configureLogging(signalR.LogLevel.Trace) + // .withHubProtocol(new MessagePackHubProtocol()) + .build(); + + this.connection.serverTimeoutInMilliseconds = 20000; + this.connection.keepAliveIntervalInMilliseconds = 6000; + + this.connection.onclose(() => { + console.info("AspNetCoreHub connection closes"); + + console.log(this.connectionOpenEventType, { + isOpen: false, + state: SignalRConnectionLevels.Disconnected, + status: "connection closed", + }); + + if (this.onDisconnected) { + this.onDisconnected(); + } + + // Restart connection after x seconds + setTimeout(() => { + this.startConnection().then(() => { + console.info(`AspNetCoreHub initiated a reconnect ${this.hubName} on ${this.serverUrl}`); + }).catch((error: any) => { + console.error(error); + }); + }, this.hubReconnectDelay); + }); + } + + public addHubEventListener(eventName: string, callback: any) { + if (this.connection) { + console.info("AspNetCoreHub added event listener: " + eventName); + this.connection.on(eventName, (data: any) => { + console.debug(`AspNetCoreHub event ${eventName} received data`, data); + if (callback) { + callback(data); + } + }); + } else { + console.warn("AspNetCoreHub no connection object to initiate listener " + this.hubName + " on " + this.serverUrl + " for " + eventName); + this.subscriptions.push({ eventName, callback}); + } + } + + public startConnection(): Promise { + if (!this.connection) { + return Promise.reject(`Can't start connection to ${this.hubName} on ${this.serverUrl}`); + } + + return Promise.resolve(this.connection.start() + .then(() => { + console.log(`AspNetCoreHub connected to ${this.hubName}` + + ` on ${this.serverUrl}` + + ` with state ${this.connection.state}` + + ` serverTimeout ${this.connection.serverTimeoutInMilliseconds}ms` + + ` keepAliveInterval ${this.connection.keepAliveIntervalInMilliseconds}ms`); + + console.log(this.connectionOpenEventType, { + isOpen: true, + state: SignalRConnectionLevels.Connected, + status: "connected", + }); + + if (this.onConnected) { + this.onConnected(); + } + }) + .catch((error: any) => { + console.error(`AspNetCoreHub error ${this.hubName} on ${this.serverUrl}`); + console.error(error); + console.log(this.connectionOpenEventType, { + isOpen: false, + state: SignalRConnectionLevels.Disconnected, + status: "connection failed", + }); + return console.error(error.toString()); + })); + } +} \ No newline at end of file diff --git a/CCM.Frontpage/src/utils/ArrayUtil.ts b/CCM.Frontpage/src/utils/ArrayUtil.ts new file mode 100644 index 00000000..0db6acf3 --- /dev/null +++ b/CCM.Frontpage/src/utils/ArrayUtil.ts @@ -0,0 +1,20 @@ +export default class ArrayUtil { + + /** + * Makes sure the object is an array. + * Returnes the object if it's an array, otherwise an + * array with the object as the only element. + * @param o Input object + */ + public static toArray(o: any): Array { + if (!o) { + return Array(); + } + if (o instanceof Array) { + return o; + } else { + return [o]; + } + } + +} diff --git a/CCM.Frontpage/src/utils/ColorPicker.ts b/CCM.Frontpage/src/utils/ColorPicker.ts new file mode 100644 index 00000000..3d824986 --- /dev/null +++ b/CCM.Frontpage/src/utils/ColorPicker.ts @@ -0,0 +1,43 @@ +import Tools from "./Tools"; + +/** + * Set up a color picker for an input field + * + * @example ColorPicker("color-picker"); + * + * @param {string} - Color picker HTMLElement class + */ +export function ColorPicker(targetClass: string, previewClass: string = null) { + const targets = document.getElementsByClassName(targetClass); + if (targets == null || targets.length === 0) { + throw new Error(`Could not bind color picker to target class '.${targetClass}'`); + } + + for (var index = 0; index < targets.length; index++) { + console.log({targ: targets[index]}); + + const currentColor = targets[index].getAttribute("value"); + console.log(currentColor); + if(currentColor.indexOf("#") > -1) { + console.log("All good with the hash"); + } else { + targets[index].setAttribute("value", `#${currentColor}`); + } + Tools.$event(targets[index], "input", (key) => { + let elem = previewClass != null ? document.getElementById(previewClass) : document.getElementsByTagName("body")[0]; + elem.style.backgroundColor = key.target.value; + }); + let elem = previewClass != null ? document.getElementById(previewClass) : document.getElementsByTagName("body")[0]; + elem.style.backgroundColor = targets[index].getAttribute("value"); + } + + // Background adjustment + // let color1 = Math.floor((Math.random() * 256)); + // let color2 = Math.floor((Math.random() * 256)); + // let color3 = Math.floor((Math.random() * 256)); + // let color = "#" + color1.toString(16) + color2.toString(16) + color3.toString(16); + // let colorText = "#" + (255 - color1).toString(16) + (255 - color2).toString(16) + (255 - color3).toString(16); + // let elem = document.getElementsByTagName("body")[0]; + // elem.style.backgroundColor = color; + // elem.style.color = colorText; +} \ No newline at end of file diff --git a/CCM.Frontpage/src/utils/Events.ts b/CCM.Frontpage/src/utils/Events.ts new file mode 100644 index 00000000..eedf8fb9 --- /dev/null +++ b/CCM.Frontpage/src/utils/Events.ts @@ -0,0 +1,53 @@ +export default class Events { + private topics = {}; + + private static instance: Events; + + constructor() { + if (Events.instance) { + return Events.instance; + } + + Events.instance = this; + } + + private parseTopic(topic: string): string[] { + let split = topic.split(' '); + if (split.length >= 3) { + console.warn(`The published topic contains too many identifiers: '${topic}', will publish on '${split[1]}'`); + return [split[0], split[1]]; + } else if(split.length >= 2) { + return split; + } else { + return [topic, topic]; + } + } + + /** + * Publish messages or objects with a topic. Any subscribers to that topic will receive the data in callback + * @param topic publish topic identifier + * @param args the data to send + * @returns returns true if anyone is subscribing to the topic + */ + public pub = function (topic: string, ...args: any): boolean { + if (!this.topics[topic]) return false; + + this.topics[topic].forEach((x: any) => { + x(...args); + }); + return true; + }; + + /** + * Subscribe to any topic with a callback function that is triggered on published messages. + * @param topic topic to subscribe to + * @param fn callback function with corresponding arguments + */ + public on = function (topic: string, fn: any) { + if (!this.topics[topic]) { + this.topics[topic] = [fn]; + } else { + this.topics[topic].push(fn); + } + }; +} diff --git a/CCM.Frontpage/src/utils/FilterList.ts b/CCM.Frontpage/src/utils/FilterList.ts new file mode 100644 index 00000000..70325846 --- /dev/null +++ b/CCM.Frontpage/src/utils/FilterList.ts @@ -0,0 +1,39 @@ +/** + * Set up a UL list and input for filtering function. User data attribute 'data-to-filter' and add 'id' for content list to filter. + * + * @example FilterList("sortlist"); + * + * @param {string} - List HTMLElement class + * @returns {void} - Listens to nothing + */ +export function FilterList(targetClass: string) { + const targets = document.getElementsByClassName(targetClass); + if (targets == null || targets.length === 0) { + throw new Error(`Could not bind filter lists to target class '.${targetClass}'`); + } + + for (let index = 0; index < targets.length; index++) { + console.log({targ: targets[index]}); + console.log(targets[index].getAttribute("data-to-filter")) + + const itemsId = targets[index].getAttribute("data-to-filter"); + if (!itemsId && !targets[index]) { + return; + } + const items = document.getElementById(itemsId).getElementsByTagName('li'); + targets[index].addEventListener('keyup', function(ev: any) { + const text = ev.target.value; + let pat = new RegExp(text, 'i'); + for (let i=0; i < items.length; i++) { + const item = items[i]; + if (pat.test(item.innerText)) { + item.classList.remove("hidden"); + } else { + item.classList.add("hidden"); + } + } + }); + + console.log(`Binding filtering input to list '${itemsId}'`); + } +} \ No newline at end of file diff --git a/CCM.Frontpage/src/utils/PasswordGenerator.ts b/CCM.Frontpage/src/utils/PasswordGenerator.ts new file mode 100644 index 00000000..6bc03084 --- /dev/null +++ b/CCM.Frontpage/src/utils/PasswordGenerator.ts @@ -0,0 +1,104 @@ +import Tools from "./Tools"; + +/** + * Set up a form support for generating passwords + * + * @example PasswordGenerator(); + * + * @param {string} - List HTMLElement class + * @returns {void} - Listens to nothing + */ +export default class PasswordGenerator { + + constructor() { + + Tools.$event("generatePasswordCheckBox", "change", (item) => { + let checked = item.target.checked || false; + this.showGeneratedPassword(checked); + }); + + Tools.$event("changePasswordCheckBox", "change", (item) => { + let checked = item.target.checked || false; + this.toggleChangePasswordFieldsVisibility(checked); + }); + + Tools.$event(window, "load", () => { + // Edit previous item + let checkBoxChangePwd = Tools.$dom("changePasswordCheckBox"); + if (checkBoxChangePwd) { + console.warn("You are editing, so nothing to show yet"); + this.toggleChangePasswordFieldsVisibility(false); + return; + } + + // Create new item + let checkBox = Tools.$dom("generatePasswordCheckBox"); + if (!checkBox) { + console.warn("No generate password check box"); + return; + } + + const isPasswordSet = (Tools.$dom("PasswordDefault") as any).value; + if (isPasswordSet === "") { + let check = (checkBox as any).checked || false; + checkBox.setAttribute("checked", "true"); + // checkBox.prop('checked', true).change(); + this.showGeneratedPassword(true); + console.log(checkBox, check) + } + }); + } + + private async generatePassword(onPasswordReceived) { + try { + const response = await fetch("/api/passwordgenerator"); + const data = await response.json(); + onPasswordReceived(data.password); + } catch(error) { + console.log(error); + } + } + + private showGeneratedPassword(checked) { + this.setGeneratedPasswordFieldVisibility(checked); + this.setPasswordFieldsVisibility(!checked); + + if (checked) { + this.generatePassword((password) => { + this.setPasswordFields(password); + }); + } else { + this.setPasswordFields(""); + } + } + + private setPasswordFields(password) { + Tools.$dom("PasswordDefault").setAttribute("value", password); + Tools.$dom("PasswordConfirm").setAttribute("value", password); + Tools.$dom("generatedPassword").setAttribute("value", password); + } + + private setGeneratedPasswordFieldVisibility(show) { + Tools.$dom("generatedPasswordWrapper").classList.toggle('hidden', !show); + } + + private setPasswordFieldsVisibility(show) { + Tools.$dom("passwordFieldsWrapper").classList.toggle('hidden', !show); + } + + private toggleChangePasswordFieldsVisibility(show) { + Tools.$dom("changePasswordFieldsWrapper").classList.toggle('hidden', !show); + } + + public generateUserPassword() { + const length = 13; + const alfabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#%"; + + let password = ""; + for (var i = 0; i < length; ++i) { + password += alfabet.charAt(Math.floor(Math.random() * alfabet.length)); + } + + return password; + } +} diff --git a/CCM.Frontpage/src/utils/SessionDescriptionProtocolUtil.ts b/CCM.Frontpage/src/utils/SessionDescriptionProtocolUtil.ts new file mode 100644 index 00000000..05c419e0 --- /dev/null +++ b/CCM.Frontpage/src/utils/SessionDescriptionProtocolUtil.ts @@ -0,0 +1,359 @@ + + + +export function hasProp(obj, value, ...keys) +{ + if (obj === undefined) + { + return false + } + + if ( keys.length == 0 && Object.prototype.hasOwnProperty.call(obj, value) ) + { + return true + } + + return this.hasProp(obj[value], ...keys) +} + +export function ParseSDPOld(rawsdp) +{ + let row = "", + tmpinner = "", + store = [], + objStore = {}; + + function addY(key, arr, value) { + if (!module.exports.hasProp(arr, key)) { + arr[key] = []; + arr[key].push(value); + } else { + arr[key].push(value); + } + } + + for (let i = 0; i < rawsdp.length; i++) { + if (rawsdp[i] == "\n" || rawsdp == "\n\r" || i == rawsdp.length-1) { + tmpinner = ""; + let multiPayloadType = false; + let hkey = ""; + let ikey = ""; + let rowPayloadType = ""; + + for (let x = 0; x < row.length; x++) { + if (multiPayloadType && row[x] == " ") { + multiPayloadType = false; + store.push({ key: ikey, data: tmpinner }) + addY(ikey, objStore, { data: tmpinner }); + hkey = tmpinner + rowPayloadType = tmpinner; + tmpinner = ""; + } + else if (row[x] == "=") { + hkey = tmpinner; + tmpinner = ""; + } + else if (row[x] == ";") { + store.push({ key: hkey.trim(), data: tmpinner, payloadType: rowPayloadType }) + addY(hkey.trim(), objStore, { data: tmpinner, payloadType: rowPayloadType }); + tmpinner = ""; + } + else if (row[x] == ":") { + multiPayloadType = true; + ikey = tmpinner; + tmpinner = ""; + } + else { + tmpinner += row[x]; + } + + if (x == row.length-1) { + let weightedKey = hkey; + //check if key is as first character.. use other key + if (row[0] == hkey && ikey != "") { + // Should be ikey unless that one is empty + weightedKey = ikey; + } + + store.push({ key: weightedKey, data: tmpinner }) + addY(weightedKey, objStore, { data: tmpinner }); + + tmpinner = ""; + } + } + row = ""; + } + else if (rawsdp[i] == "\r") { + // Dont do anything + } + else { + // code block + row += rawsdp[i]; + } + } + return objStore; +} + +export class SDPAttribute { + public mediaFormat: string; + public parameter: string; + public value: any; + public get isRelatedToMediaFormat(): boolean { + return this.mediaFormat !== null || this.mediaFormat !== ""; + } + public isAcip: boolean = false; + + constructor(parameter: string, value: any, formatId: string = null, isAcip = false) { + this.mediaFormat = formatId; + this.parameter = parameter; + this.value = value; + this.isAcip = isAcip; + } + + AsString() { + return `${this.mediaFormat} => ${this.parameter} ${this.isAcip ? "[acip attr]" : ""}`; + } +} + +export class SessionDescription { + public info: any; + public media: any; + public attr: SDPAttribute[] = []; + + public parsed: any; + + constructor() { + + } + + public static parse(raw: any): SessionDescription { + const sdp = new SessionDescription(); + sdp.parseSDP(raw); + return sdp; + } + + parseAttribute(data, key = "", fmt = null) { + switch(key) { + case "fmtp": + console.log("fmtp-------"); + data.split(";").map(attr => { + console.log(attr.trim()) + const pair = attr.trim().split("="); + if (pair.length == 2) { + this.attr.push(new SDPAttribute(pair[0], pair[1], fmt)) + } + return; + }); + return; + break; + case "ebuacip": + console.log("ebuacip -----"); + + // a=ebuacip:plength + // a=ebuacip:plength 98 4 + const regex1 = /(plength)\s{1}(\d{1,})\s{1}(\d{1,})/gm; + let m = regex1.exec(data); + if (m !== null && m.length == 4) { + // m.forEach((match, groupIndex) => { + // console.log(`Found match, group ${groupIndex}: ${match}`); + // }); + this.attr.push(new SDPAttribute("plength", m[3], m[2], true)); + return { + format: m[2], + plength: m[3] + }; + } + + // a=ebuacip:jb