Compare commits

..

42 Commits

Author SHA1 Message Date
Thomas Fransolet
369b789abb WIP add Agenda, pdf, puzzle objects 2023-12-09 23:53:31 +01:00
Thomas Fransolet
2866c12985 Add MQTT events 2023-12-05 15:40:51 +01:00
Thomas Fransolet
0b0b54c6af Add pinCode to TokenDTO 2023-12-05 14:08:00 +01:00
Thomas Fransolet
eb0263dee8 Fix mqtt credentials 2023-11-30 17:09:50 +01:00
Thomas Fransolet
1e31ebe094 Add pinCode to instance + endpoints 2023-11-30 15:42:18 +01:00
19d84b4417 Configurations orderBy date creation 2023-03-30 16:59:55 +02:00
eb50590684 Update file download (add file name) + update max audio and other file size 2023-03-10 19:46:37 +01:00
f5921180cf Clean GetAllBeaconsForInstance accept return empty list 2023-02-20 14:43:35 +01:00
33f782346b Add nullable int beaconId + ensure ressource has no duplicate 2023-02-17 16:53:24 +01:00
042949ec60 BeaconId string to int 2023-02-16 18:02:33 +01:00
ca1d71a846 Update for doc 2023-02-15 17:13:42 +01:00
74101d9939 Add sectionIds to ConfigurationDTO 2023-02-15 10:16:18 +01:00
a0b2d5ba9c Update encoding + add from query language 2023-02-10 17:33:59 +01:00
88ab87c9ee Add audio in export configuration 2023-02-10 17:06:23 +01:00
52ec413761 Add get beacons method 2023-01-28 01:23:35 +01:00
006aa541cd Fix image url not working 2023-01-27 21:10:15 +01:00
52d5467b85 Add watermark and shrink images only if fort 2023-01-26 17:09:48 +01:00
63654bdcf9 Allow all file size for image 2023-01-13 17:47:08 +01:00
bdab0dc286 Add support for Arab and Ukrainian 2023-01-12 16:19:51 +01:00
9e8109225a Clean code + add Beacon handling 2022-12-27 21:47:52 +01:00
fc9d38c3c1 Update article to handle multiple audioIds 2022-12-22 14:31:49 +01:00
85ca1368a2 Add resize image + small fixs 2022-12-20 17:34:15 +01:00
3e6439433e Update get ressources endpoint by adding types filter 2022-10-27 13:31:38 +02:00
5b56c677ef Update docker file 2022-10-26 22:18:11 +02:00
cf2d7759de Split resource in Resource and resourceData + Add Audio ResourceType 2022-10-26 17:11:45 +02:00
390852ce4f import => support instanceId + Delete resource, delete imageId and ref for configuration 2022-10-21 17:38:17 +02:00
499065bdb7 Add instanceId to ToSectionDTO and ToResourceDTO + update device controller for instanceId 2022-10-20 16:37:37 +02:00
79be291113 Add instanceId to config, section and resource 2022-10-20 16:09:34 +02:00
3b6c480cc6 Add instance model, dto, controller and service + update other objects and controllers 2022-10-06 17:07:11 +02:00
35e2d8296b Add password verification ! 2022-10-06 15:14:08 +02:00
9328318468 Docker compose mymuseum 2022-09-29 17:56:08 +02:00
ee021510c8 add docker file + change for prod 2022-09-29 16:54:44 +02:00
1725376623 Add title and image to configuration 2022-09-17 22:43:24 +02:00
afdd538a3b Fix Article default value when creation 2022-06-22 18:55:20 +02:00
4f1902984b Add IsTablet and remove Title and Description from Article 2022-06-22 17:01:09 +02:00
55a612fd0c Add new subsection ArticleDTO + add offline and mobile option 2022-06-11 20:58:43 +02:00
820de792a5 Release 2022-03-29 19:00:09 +02:00
8c2e276d1c Update export to download json file 2022-03-25 17:38:32 +01:00
e5bfed2ff6 Import and export quizzDTO to test ! 2022-03-24 21:47:14 +01:00
e157cd1cb0 Fix delete ressource for quizz 2022-03-24 21:39:35 +01:00
474e9ce719 New realease version 2022-03-23 20:54:40 +01:00
e61b334f02 Add quizz ! 2022-03-19 01:24:17 +01:00
200 changed files with 15271 additions and 121 deletions

View File

@ -22,20 +22,25 @@ namespace Manager.Framework.Business
_logger = logger;
}
public bool Authenticate(string email, string password)
public void TestPassword(string email, string userPassword, string password)
{
if (string.IsNullOrWhiteSpace(email))
{
_logger.LogError($"Authenticate error: No e-mail provided");
throw new UnauthorizedAccessException("Authentication error");
}
if (string.IsNullOrEmpty(password))
{
_logger.LogError($"Authenticate error: No password provided");
throw new UnauthorizedAccessException("Authentication error");
}
return true;
if (!PasswordUtils.Compare(userPassword, password, PasswordsPepper))
{
_logger.LogError($"Authenticate error: passwords doesn't match");
throw new UnauthorizedAccessException("Authentication error");
}
}
/// <summary>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@ -8,9 +8,20 @@ namespace Manager.Interfaces.DTO
{
public string id { get; set; }
public string label { get; set; }
public List<TranslationDTO> title { get; set; }
public string imageId { get; set; } // == ResourceId
public string imageSource { get; set; } // == Image url
public string primaryColor { get; set; }
public string secondaryColor { get; set; }
public List<string> languages { get; set; } // fr, en, de, nl => Sélection dans une liste déjà établie dans l'application !
public DateTime dateCreation { get; set; }
public bool isMobile { get; set; } // MyVisit - True if for mobile (MyVisit)
public bool isTablet { get; set; }
public bool isOffline { get; set; } // MyVisit - True if MyVisit is full offline
/*public string latitude { get; set; } // MyVisit - latitude of visit ? (MyVisit)
public string longitude { get; set; } // MyVisit - True if for mobile (MyVisit)*/
public string instanceId { get; set; }
public List<string> sectionIds { get; set; }
public int pinCode { get; set; } // 4 number
}
}

View File

@ -16,6 +16,7 @@ namespace Manager.Interfaces.DTO
public bool connected{ get; set; }
public DateTime dateCreation{ get; set; }
public DateTime dateUpdate { get; set; }
public string instanceId { get; set; }
}
public class DeviceDetailDTO : DeviceDTO

View File

@ -1,5 +1,4 @@
using DevExpress.Xpo;
using System;
using System;
using System.Collections.Generic;
namespace Manager.Interfaces.DTO

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.DTO
{
public class InstanceDTO
{
public string id { get; set; }
public string name { get; set; }
public DateTime dateCreation { get; set; }
public int? pinCode { get; set; }
}
}

View File

@ -10,7 +10,8 @@ namespace Manager.Interfaces.DTO
public string id { get; set; }
public ResourceType type { get; set; }
public string label { get; set; }
public DateTime dateCreation { get; set; }
public string data { get; set; }
public DateTime dateCreation { get; set; }
public string instanceId { get; set; }
}
}

View File

@ -20,5 +20,11 @@ namespace Manager.Interfaces.DTO
public string data { get; set; } // == Include section type info
public DateTime dateCreation { get; set; } // == Include section type info
public int order { get; set; } // Order to show
public string instanceId { get; set; }
public string latitude { get; set; } // MyVisit - Use to launch automatic content when current location is near
public string longitude { get; set; } // MyVisit - Use to launch automatic content when current location is near
public int? meterZoneGPS { get; set; } // MyVisit - Nbr of meters of the zone to launch content
public bool isBeacon { get; set; } // MyVisit - True if section use beacon, false otherwise
public int? beaconId { get; set; } // MyVisit - Beacon' identifier
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.DTO
{
public class AgendaDTO
{
//public string Title { get; set; } // Dictionary<string, object> with all languages
public string source { get; set; } // url to resource id (local) or on internet => JSON file
}
}

View File

@ -0,0 +1,16 @@
using Manager.Interfaces.Models;
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.DTO
{
public class ArticleDTO
{
public List<TranslationDTO> content { get; set; }
public bool isContentTop { get; set; } // MyVisit - True if content is displayed at top, false otherwise
public List<TranslationDTO> audioIds { get; set; }
public bool isReadAudioAuto { get; set; } // MyVisit - True for audio play when open the article / false otherwise
public List<ImageDTO> images { get; set; } // Will check if ok or if we need need type of image (simpler)
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.DTO
{
public class PdfDTO
{
//public string Title { get; set; } // Dictionary<string, object> with all languages
public string source { get; set; } // url to resource id (local) or on internet
}
}

View File

@ -0,0 +1,14 @@
using Manager.Interfaces.Models;
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.DTO
{
public class PuzzleDTO
{
public List<TranslationDTO> messageDebut { get; set; }
public List<TranslationDTO> messageFin { get; set; }
public ImageDTO image { get; set; }
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.DTO
{
public class QuizzDTO
{
public List<QuestionDTO> questions { get; set; }
public LevelDTO bad_level { get; set; }
public LevelDTO medium_level { get; set; }
public LevelDTO good_level { get; set; }
public LevelDTO great_level { get; set; }
}
public class QuestionDTO
{
public List<TranslationDTO> label { get; set; }
public List<ResponseDTO> responses { get; set; }
public string resourceId { get; set; } // question image
public string source { get; set; }
public int order { get; set; } // Order to show
}
public class ResponseDTO
{
public List<TranslationDTO> label { get; set; }
public bool isGood { get; set; }
public int order { get; set; } // Order to show
}
public class LevelDTO
{
public List<TranslationDTO> label { get; set; }
public string resourceId { get; set; } // level result image
public string source { get; set; }
}
}

View File

@ -10,5 +10,7 @@ namespace Manager.Interfaces.DTO
public string token_type { get; set; }
public int expires_in { get; set; }
public DateTimeOffset expiration { get; set; }
public string instanceId { get; set; }
public int? pinCode { get; set; }
}
}

View File

@ -1,11 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DevExpress.Xpo" Version="20.1.8" />
<PackageReference Include="MongoDB.Bson" Version="2.12.1" />
</ItemGroup>

View File

@ -2,6 +2,7 @@
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Manager.Interfaces.Models
@ -19,6 +20,16 @@ namespace Manager.Interfaces.Models
[BsonRequired]
public string Label { get; set; }
[BsonElement("Title")]
[BsonRequired]
public List<TranslationDTO> Title { get; set; }
[BsonElement("ImageId")]
public string ImageId { get; set; }
[BsonElement("ImageSource")]
public string ImageSource { get; set; }
[BsonElement("PrimaryColor")]
public string PrimaryColor { get; set; }
@ -31,16 +42,41 @@ namespace Manager.Interfaces.Models
[BsonElement("DateCreation")]
public DateTime DateCreation { get; set; }
public ConfigurationDTO ToDTO()
[BsonElement("IsMobile")]
public bool IsMobile { get; set; }
[BsonElement("IsTablet")]
public bool IsTablet { get; set; }
[BsonElement("IsOffline")]
public bool IsOffline { get; set; }
[BsonElement("InstanceId")]
[BsonRequired]
public string InstanceId { get; set; }
[BsonElement("PinCode")]
public int PinCode { get; set; }
public ConfigurationDTO ToDTO(List<string> sectionIds)
{
return new ConfigurationDTO()
{
id = Id,
label = Label,
title = Title,
imageId = ImageId,
imageSource = ImageSource,
dateCreation = DateCreation,
primaryColor = PrimaryColor,
languages = Languages,
secondaryColor = SecondaryColor
secondaryColor = SecondaryColor,
isMobile = IsMobile,
isTablet = IsTablet,
isOffline = IsOffline,
instanceId = InstanceId,
pinCode = PinCode,
sectionIds = sectionIds
};
}
@ -49,12 +85,21 @@ namespace Manager.Interfaces.Models
{
id = Id,
label = Label,
title= Title,
imageId = ImageId,
imageSource = ImageSource,
dateCreation = DateCreation,
primaryColor = PrimaryColor,
languages = Languages,
secondaryColor = SecondaryColor,
isMobile = IsMobile,
isTablet = IsTablet,
isOffline = IsOffline,
sections = sections,
resources = resources
resources = resources,
instanceId = InstanceId,
pinCode = PinCode,
sectionIds = sections.Select(s => s.id).ToList()
};
}
}

View File

@ -60,6 +60,9 @@ namespace Manager.Interfaces.Models
[BsonElement("LastConnectionLevel")]
public DateTime LastConnectionLevel { get; set; }
[BsonElement("InstanceId")]
[BsonRequired]
public string InstanceId { get; set; }
public DeviceDTO ToDTO()
{
@ -74,7 +77,8 @@ namespace Manager.Interfaces.Models
configuration = Configuration,
configurationId = ConfigurationId,
dateUpdate = DateUpdate,
dateCreation = DateCreation
dateCreation = DateCreation,
instanceId = InstanceId
};
}
@ -95,7 +99,8 @@ namespace Manager.Interfaces.Models
batteryLevel = BatteryLevel,
lastBatteryLevel = LastBatteryLevel,
dateUpdate = DateUpdate,
dateCreation = DateCreation
dateCreation = DateCreation,
instanceId = InstanceId
};
}
}

View File

@ -0,0 +1,40 @@
using Manager.Interfaces.DTO;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.Models
{
/// <summary>
/// Instance Information
/// </summary>
public class Instance
{
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
public string Id { get; set; }
[BsonElement("Name")]
[BsonRequired]
public string Name { get; set; } // UNIQUE !..
[BsonElement("DateCreation")]
public DateTime DateCreation { get; set; }
[BsonElement("PinCode")]
public int? PinCode { get; set; }
public InstanceDTO ToDTO()
{
return new InstanceDTO()
{
id = Id,
name = Name,
dateCreation = DateCreation,
pinCode = PinCode
};
}
}
}

View File

@ -27,19 +27,20 @@ namespace Manager.Interfaces.Models
[BsonElement("DateCreation")]
public DateTime DateCreation { get; set; }
[BsonElement("Data")]
[BsonElement("InstanceId")]
[BsonRequired]
public string Data { get; set; }
public string InstanceId { get; set; }
public ResourceDTO ToDTO(bool isExport = false)
public ResourceDTO ToDTO(string data = null) //
{
return new ResourceDTO()
{
id = Id,
label = Label,
type = Type,
data = isExport ? Data : null,
dateCreation = DateCreation
data = data,
dateCreation = DateCreation,
instanceId = InstanceId
};
}
}
@ -49,6 +50,9 @@ namespace Manager.Interfaces.Models
Image,
Video,
ImageUrl,
VideoUrl
VideoUrl,
Audio,
PDF,
JSON
}
}

View File

@ -0,0 +1,31 @@
using Manager.Interfaces.DTO;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.Text;
namespace Manager.Interfaces.Models
{
/// <summary>
/// Resource Information
/// </summary>
public class ResourceData
{
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
public string Id { get; set; }
[BsonElement("Data")]
[BsonRequired]
public string Data { get; set; }
[BsonElement("ResourceId")]
[BsonRequired]
public string ResourceId { get; set; }
[BsonElement("InstanceId")]
[BsonRequired]
public string InstanceId { get; set; }
}
}

View File

@ -61,6 +61,25 @@ namespace Manager.Interfaces.Models
[BsonRequired]
public string Data { get; set; } // Json encapsulated section info
[BsonElement("InstanceId")]
[BsonRequired]
public string InstanceId { get; set; }
[BsonElement("IsBeacon")]
public bool IsBeacon { get; set; }
[BsonElement("BeaconId")]
public int? BeaconId { get; set; }
[BsonElement("Latitude")]
public string Latitude { get; set; }
[BsonElement("Longitude")]
public string Longitude { get; set; }
[BsonElement("MeterZoneGPS")]
public int? MeterZoneGPS { get; set; }
public SectionDTO ToDTO()
{
return new SectionDTO()
@ -77,7 +96,13 @@ namespace Manager.Interfaces.Models
isSubSection = IsSubSection,
parentId = ParentId,
data = Data,
dateCreation = DateCreation
dateCreation = DateCreation,
instanceId = InstanceId,
isBeacon = IsBeacon,
beaconId = BeaconId,
latitude = Latitude,
longitude = Longitude,
meterZoneGPS = MeterZoneGPS,
};
}
}
@ -88,6 +113,11 @@ namespace Manager.Interfaces.Models
Slider,
Video,
Web,
Menu
Menu,
Quizz,
Article,
PDF,
Puzzle,
Agenda
}
}

View File

@ -38,6 +38,10 @@ namespace Manager.Interfaces.Models
[BsonElement("DateCreation")]
public DateTime DateCreation { get; set; }
[BsonElement("InstanceId")]
[BsonRequired]
public string InstanceId { get; set; }
public UserDetailDTO ToDTO()
{
return new UserDetailDTO()

View File

@ -51,16 +51,16 @@ namespace ManagerService.Service.Controllers
{
#if DEBUG
email = "test@email.be";
password = "W/7aj4NB60i3YFKJq50pbw=="; // password = "kljqsdkljqsd";
password = "kljqsdkljqsd"; // password = "kljqsdkljqsd"; // W/7aj4NB60i3YFKJq50pbw==
#endif
var token = _tokensService.Authenticate(email.ToLower(), password);
// Set user token ?
var user = _UserDatabaseService.GetByEmail(email.ToLower());
if (user == null)
throw new KeyNotFoundException("User not found");
var token = _tokensService.Authenticate(user, password);
MqttClientService.SetServices(_DeviceDatabaseService, _ConfigurationDatabaseService);
return new OkObjectResult(token);

View File

@ -1,13 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Manager.Helpers;
using Manager.Interfaces.DTO;
using Manager.Interfaces.Models;
using Manager.Services;
using ManagerService.Service.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Mqtt.Client.AspNetCore.Services;
using Newtonsoft.Json;
@ -21,34 +24,50 @@ namespace ManagerService.Controllers
public class ConfigurationController : ControllerBase
{
private ConfigurationDatabaseService _configurationService;
private InstanceDatabaseService _instanceService;
private SectionDatabaseService _sectionService;
private ResourceDatabaseService _resourceService;
private ResourceDataDatabaseService _resourceDataService;
private DeviceDatabaseService _deviceService;
private readonly ILogger<ConfigurationController> _logger;
private readonly IConfiguration _configuration;
public ConfigurationController(ILogger<ConfigurationController> logger, ConfigurationDatabaseService configurationService, SectionDatabaseService sectionService, ResourceDatabaseService resourceService, DeviceDatabaseService deviceService)
public ConfigurationController(IConfiguration configuration, ILogger<ConfigurationController> logger, ConfigurationDatabaseService configurationService, InstanceDatabaseService instanceService, SectionDatabaseService sectionService, ResourceDatabaseService resourceService, ResourceDataDatabaseService resourceDataService, DeviceDatabaseService deviceService)
{
_logger = logger;
_configuration = configuration;
_configurationService = configurationService;
_instanceService = instanceService;
_sectionService = sectionService;
_resourceService = resourceService;
_resourceDataService = resourceDataService;
_deviceService = deviceService;
}
/// <summary>
/// Get a list of all configuration (summary)
/// </summary>
/// <param name="id">id instance</param>
[AllowAnonymous]
[ProducesResponseType(typeof(List<ConfigurationDTO>), 200)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet]
public ObjectResult Get()
public ObjectResult Get([FromQuery] string instanceId)
{
try
{
List<Configuration> configurations = _configurationService.GetAll();
List<Configuration> configurations = _configurationService.GetAll(instanceId);
return new OkObjectResult(configurations.Select(r => r.ToDTO()));
List<ConfigurationDTO> configurationDTOs = new List<ConfigurationDTO>();
foreach(var configuration in configurations)
{
List<string> sectionIds = _sectionService.GetAllIdsFromConfiguration(configuration.Id);
ConfigurationDTO configurationDTO = configuration.ToDTO(sectionIds);
configurationDTOs.Add(configurationDTO);
}
return new OkObjectResult(configurationDTOs.OrderBy(c => c.dateCreation));
}
catch (Exception ex)
{
@ -56,6 +75,39 @@ namespace ManagerService.Controllers
}
}
/// <summary>
/// Get Confuguration list by instanceId' pincode
/// </summary>
/// <param name="pinCode">Code pin</param>
[AllowAnonymous]
[ProducesResponseType(typeof(List<ConfigurationDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("byPin")]
public ObjectResult GetConfigurationsByPinCode([FromQuery] int pinCode)
{
try
{
Instance instance = _instanceService.GetByPinCode(pinCode);
if (instance == null)
throw new KeyNotFoundException("None instance is linked to this pin code");
List<Configuration> configurations = _configurationService.GetAll(instance.Id);
List<ConfigurationDTO> configurationDTOs = new List<ConfigurationDTO>();
foreach (var configuration in configurations)
{
List<string> sectionIds = _sectionService.GetAllIdsFromConfiguration(configuration.Id);
configurationDTOs.Add(configuration.ToDTO(sectionIds));
}
return new OkObjectResult(configurationDTOs);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get a specific display configuration
@ -75,7 +127,9 @@ namespace ManagerService.Controllers
if (configuration == null)
throw new KeyNotFoundException("This configuration was not found");
return new OkObjectResult(configuration.ToDTO());
List<string> sectionIds = _sectionService.GetAllIdsFromConfiguration(id);
return new OkObjectResult(configuration.ToDTO(sectionIds));
}
catch (KeyNotFoundException ex)
{
@ -105,15 +159,27 @@ namespace ManagerService.Controllers
// Todo add some verification ?
Configuration configuration = new Configuration();
configuration.InstanceId = newConfiguration.instanceId;
configuration.Label = newConfiguration.label;
configuration.Title = new List<TranslationDTO>();
configuration.ImageId = newConfiguration.imageId;
configuration.ImageSource = newConfiguration.imageSource;
configuration.PrimaryColor = newConfiguration.primaryColor;
configuration.SecondaryColor = newConfiguration.secondaryColor;
configuration.Languages = new List<string> { "FR", "NL", "EN", "DE" }; // by default all languages
configuration.Languages = _configuration.GetSection("SupportedLanguages").Get<List<string>>();
//configuration.Languages = new List<string> { "FR", "NL", "EN", "DE" }; // by default all languages
configuration.Title = LanguageInit.Init("Title", configuration.Languages);
configuration.DateCreation = DateTime.Now;
configuration.IsMobile = newConfiguration.isMobile;
configuration.IsTablet = newConfiguration.isTablet;
configuration.IsOffline = newConfiguration.isOffline;
Configuration configurationCreated = _configurationService.Create(configuration);
return new OkObjectResult(configurationCreated.ToDTO());
return new OkObjectResult(configurationCreated.ToDTO(new List<string>())); // Empty list
}
catch (ArgumentNullException ex)
{
@ -152,16 +218,25 @@ namespace ManagerService.Controllers
throw new KeyNotFoundException("Configuration does not exist");
// Todo add some verification ?
configuration.InstanceId = updatedConfiguration.instanceId;
configuration.Label = updatedConfiguration.label;
configuration.Title = updatedConfiguration.title;
configuration.ImageId = updatedConfiguration.imageId;
configuration.ImageSource = updatedConfiguration.imageSource;
configuration.PrimaryColor = updatedConfiguration.primaryColor;
configuration.SecondaryColor = updatedConfiguration.secondaryColor;
configuration.Languages = updatedConfiguration.languages;
configuration.IsMobile = updatedConfiguration.isMobile;
configuration.IsTablet = updatedConfiguration.isTablet;
configuration.IsOffline = updatedConfiguration.isOffline;
Configuration configurationModified = _configurationService.Update(updatedConfiguration.id, configuration);
MqttClientService.PublishMessage($"config/{configurationModified.Id}", JsonConvert.SerializeObject(new PlayerMessageDTO() { configChanged = true }));
List<string> sectionIds = _sectionService.GetAllIdsFromConfiguration(configuration.Id);
return new OkObjectResult(configurationModified.ToDTO());
return new OkObjectResult(configurationModified.ToDTO(sectionIds));
}
catch (ArgumentNullException ex)
{
@ -228,17 +303,19 @@ namespace ManagerService.Controllers
}
}
/// <summary>
/// Export a configuration
/// </summary>
/// <param name="id">Id of configuration to export</param>
[ProducesResponseType(typeof(ExportConfigurationDTO), 200)]
/// <param name="language">Language to export</param>
[AllowAnonymous]
[ProducesResponseType(typeof(FileContentResult), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{id}/export")]
public ObjectResult Export(string id)
public FileContentResult Export(string id, [FromQuery] string language)
{
try
{
@ -246,12 +323,18 @@ namespace ManagerService.Controllers
throw new ArgumentNullException("Configuration param is null");
Configuration configuration = _configurationService.GetById(id);
if (configuration == null)
throw new KeyNotFoundException("Configuration does not exist");
List<SectionDTO> sectionDTOs = _sectionService.GetAllFromConfiguration(configuration.Id).Select(s => s.ToDTO()).ToList();
List<ResourceDTO> resourceDTOs = new List<ResourceDTO>();
if (configuration.ImageId != null)
{
addResourceToList(resourceDTOs, configuration.ImageId);
}
foreach (var section in sectionDTOs)
{
if (section.imageId != null) {
@ -286,6 +369,64 @@ namespace ManagerService.Controllers
}
}
break;
case SectionType.Quizz:
QuizzDTO quizzDTO = JsonConvert.DeserializeObject<QuizzDTO>(section.data);
foreach (var question in quizzDTO.questions)
{
if (question.resourceId != null)
{
addResourceToList(resourceDTOs, question.resourceId);
}
}
if (quizzDTO.bad_level != null)
{
if (quizzDTO.bad_level.resourceId != null)
{
addResourceToList(resourceDTOs, quizzDTO.bad_level.resourceId);
}
}
if (quizzDTO.medium_level != null)
{
if (quizzDTO.medium_level.resourceId != null)
{
addResourceToList(resourceDTOs, quizzDTO.medium_level.resourceId);
}
}
if (quizzDTO.good_level != null)
{
if (quizzDTO.good_level.resourceId != null)
{
addResourceToList(resourceDTOs, quizzDTO.good_level.resourceId);
}
}
if (quizzDTO.great_level != null)
{
if (quizzDTO.great_level.resourceId != null)
{
addResourceToList(resourceDTOs, quizzDTO.great_level.resourceId);
}
}
break;
case SectionType.Article:
ArticleDTO articleDTO = JsonConvert.DeserializeObject<ArticleDTO>(section.data);
foreach (var image in articleDTO.images)
{
if (image.resourceId != null)
{
addResourceToList(resourceDTOs, image.resourceId);
}
}
// If not a language is used for export in manager, if one is the myvisit app
var audios = language != null ? articleDTO.audioIds.Where(a => a.language == language) : articleDTO.audioIds;
foreach (var audio in audios)
{
if (audio.value != null)
{
addResourceToList(resourceDTOs, audio.value);
}
}
break;
case SectionType.Menu:
case SectionType.Web:
case SectionType.Video:
@ -293,21 +434,30 @@ namespace ManagerService.Controllers
break;
}
}
return new OkObjectResult(configuration.ToExportDTO(sectionDTOs, resourceDTOs));
ExportConfigurationDTO toDownload = configuration.ToExportDTO(sectionDTOs, resourceDTOs);
string jsonString = JsonConvert.SerializeObject(toDownload);
var fileName = $"{configuration.Label}.json";
var mimeType = "application/json";
var fileBytes = Encoding.UTF8.GetBytes(jsonString);
return new FileContentResult(fileBytes, mimeType)
{
FileDownloadName = fileName
};
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) { };
return null;
//return new BadRequestObjectResult(ex.Message) { };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
return null;
//return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
return null;
//return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
@ -334,11 +484,24 @@ namespace ManagerService.Controllers
configuration = new Configuration();
configuration.Id = exportConfiguration.id;
configuration.InstanceId = exportConfiguration.instanceId;
configuration.Label = exportConfiguration.label;
configuration.Title = exportConfiguration.title;
configuration.ImageId = exportConfiguration.imageId;
configuration.ImageSource = exportConfiguration.imageSource;
if (configuration.ImageId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == configuration.ImageId).FirstOrDefault());
}
configuration.DateCreation = exportConfiguration.dateCreation;
configuration.PrimaryColor = exportConfiguration.primaryColor;
configuration.SecondaryColor = exportConfiguration.secondaryColor;
configuration.Languages = exportConfiguration.languages;
configuration.IsMobile = exportConfiguration.isMobile;
configuration.IsTablet = exportConfiguration.isTablet;
configuration.IsOffline = exportConfiguration.isOffline;
_configurationService.Create(configuration);
@ -346,6 +509,7 @@ namespace ManagerService.Controllers
{
Section newSection = new Section();
newSection.Id = section.id;
newSection.InstanceId = section.instanceId;
newSection.Label = section.label;
newSection.Title = section.title;
newSection.Description = section.description;
@ -358,6 +522,11 @@ namespace ManagerService.Controllers
newSection.ParentId = section.parentId;
newSection.Data = section.data;
newSection.DateCreation = section.dateCreation;
newSection.IsBeacon = section.isBeacon;
newSection.BeaconId = section.beaconId;
newSection.Latitude = section.latitude;
newSection.Longitude = section.longitude;
newSection.MeterZoneGPS = section.meterZoneGPS;
if (newSection.ImageId != null)
{
@ -397,6 +566,54 @@ namespace ManagerService.Controllers
}
}
break;
case SectionType.Quizz:
QuizzDTO quizzDTO = JsonConvert.DeserializeObject<QuizzDTO>(section.data);
foreach (var question in quizzDTO.questions)
{
if (question.resourceId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == question.resourceId).FirstOrDefault());
}
}
if (quizzDTO.bad_level != null)
{
if(quizzDTO.bad_level.resourceId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == quizzDTO.bad_level.resourceId).FirstOrDefault());
}
}
if (quizzDTO.medium_level != null)
{
if (quizzDTO.medium_level.resourceId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == quizzDTO.medium_level.resourceId).FirstOrDefault());
}
}
if (quizzDTO.good_level != null)
{
if (quizzDTO.good_level.resourceId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == quizzDTO.good_level.resourceId).FirstOrDefault());
}
}
if (quizzDTO.great_level != null)
{
if (quizzDTO.great_level.resourceId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == quizzDTO.great_level.resourceId).FirstOrDefault());
}
}
break;
case SectionType.Article:
ArticleDTO articleDTO = JsonConvert.DeserializeObject<ArticleDTO>(section.data);
foreach (var image in articleDTO.images)
{
if (image.resourceId != null)
{
createResource(exportConfiguration.resources.Where(r => r.id == image.resourceId).FirstOrDefault());
}
}
break;
case SectionType.Menu:
case SectionType.Web:
case SectionType.Video:
@ -432,22 +649,32 @@ namespace ManagerService.Controllers
{
Resource resource = new Resource();
resource.Id = resourceExport.id;
resource.InstanceId = resourceExport.instanceId;
resource.Type = resourceExport.type;
resource.Label = resourceExport.label;
resource.DateCreation = resourceExport.dateCreation;
resource.Data = resourceExport.data;
//resource.Data = resourceExport.data;
ResourceData resourceData = new ResourceData();
resourceData.ResourceId = resourceExport.id;
resourceData.InstanceId = resourceExport.instanceId;
resourceData.Data = resourceExport.data;
if (!_resourceService.IsExist(resourceExport.id))
_resourceService.Create(resource);
if (!_resourceDataService.IsExist(resourceExport.id))
_resourceDataService.Create(resourceData);
}
}
private List<ResourceDTO> addResourceToList(List<ResourceDTO> resourceDTOs, string resourceId) {
if (!resourceDTOs.Select(r => r.id).Contains(resourceId)) {
Resource resource = _resourceService.GetById(resourceId);
ResourceData resourceData = _resourceDataService.GetByResourceId(resourceId);
if (resource != null) {
resourceDTOs.Add(resource.ToDTO(true));
if (resource != null && resourceData != null && !resourceDTOs.Any(r => r.id == resource.Id)) {
resourceDTOs.Add(resource.ToDTO(resourceData.Data));
}
}
return resourceDTOs;

View File

@ -37,14 +37,15 @@ namespace ManagerService.Controllers
/// <summary>
/// Get a list of all devices
/// </summary>
/// <param name="id">id instance</param>
[ProducesResponseType(typeof(List<DeviceDTO>), 200)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet]
public ObjectResult Get()
public ObjectResult Get([FromQuery] string instanceId)
{
try
{
List<Device> devices = _deviceService.GetAll();
List<Device> devices = _deviceService.GetAll(instanceId);
return new OkObjectResult(devices.Select(d => d.ToDTO()));
}
@ -121,6 +122,7 @@ namespace ManagerService.Controllers
device.DateCreation = DateTime.Now;
}
device.InstanceId = newDevice.instanceId;
device.Name = newDevice.name;
device.Configuration = configuration.Label;
device.ConfigurationId = newDevice.configurationId;
@ -178,6 +180,7 @@ namespace ManagerService.Controllers
// Todo add some verification ?
device.Name = updatedDevice.name;
device.InstanceId = updatedDevice.instanceId;
device.Identifier = updatedDevice.identifier;
device.IpAddressWLAN = updatedDevice.ipAddressWLAN;
device.IpAddressETH = updatedDevice.ipAddressETH;

View File

@ -0,0 +1,246 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Manager.Framework.Business;
using Manager.Interfaces.DTO;
using Manager.Interfaces.Models;
using Manager.Services;
using ManagerService.Service.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NSwag.Annotations;
namespace ManagerService.Controllers
{
[Authorize] // TODO Add ROLES (Roles = "Admin")
[ApiController, Route("api/[controller]")]
[OpenApiTag("Instance", Description = "Instance management")]
public class InstanceController : ControllerBase
{
private InstanceDatabaseService _instanceService;
private UserDatabaseService _userService;
private readonly ILogger<InstanceController> _logger;
private readonly ProfileLogic _profileLogic;
public InstanceController(ILogger<InstanceController> logger, InstanceDatabaseService instanceService, UserDatabaseService userService, ProfileLogic profileLogic)
{
_logger = logger;
_instanceService = instanceService;
_userService = userService;
_profileLogic = profileLogic;
}
/// <summary>
/// Get a list of instance
/// </summary>
[ProducesResponseType(typeof(List<Instance>), 200)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet]
public ObjectResult Get()
{
try
{
List<Instance> instances = _instanceService.GetAll();
return new OkObjectResult(instances);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get a specific instance
/// </summary>
/// <param name="id">id instance</param>
[ProducesResponseType(typeof(InstanceDTO), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{id}")]
public ObjectResult GetDetail(string id)
{
try
{
Instance instance = _instanceService.GetById(id);
if (instance == null)
throw new KeyNotFoundException("This instance was not found");
return new OkObjectResult(instance.ToDTO());
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create an instance
/// </summary>
/// <param name="newInstance">New instance info</param>
//[AllowAnonymous]
[ProducesResponseType(typeof(InstanceDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 409)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost]
public ObjectResult CreateInstance([FromBody] Instance newInstance)
{
try
{
if (newInstance == null)
throw new ArgumentNullException("instance param is null");
newInstance.DateCreation = DateTime.Now;
List<Instance> instances = _instanceService.GetAll();
if (instances.Select(i => i.Name).Contains(newInstance.Name))
throw new InvalidOperationException("This name is already used");
Instance instanceCreated = _instanceService.Create(newInstance);
return new OkObjectResult(instanceCreated.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (InvalidOperationException ex)
{
return new ConflictObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Update an instance
/// </summary>
/// <param name="updatedinstance">instance to update</param>
[ProducesResponseType(typeof(InstanceDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut]
public ObjectResult Updateinstance([FromBody] Instance updatedInstance)
{
try
{
if (updatedInstance == null)
throw new ArgumentNullException("instance param is null");
Instance instance = _instanceService.GetById(updatedInstance.Id);
if (instance == null)
throw new KeyNotFoundException("instance does not exist");
Instance instanceModified = _instanceService.Update(updatedInstance.Id, instance);
return new OkObjectResult(instanceModified.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get Instance by pincode
/// </summary>
/// <param name="pinCode">Code pin</param>
[AllowAnonymous]
[ProducesResponseType(typeof(InstanceDTO), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("byPin")]
public ObjectResult GetInstanceByPinCode([FromQuery] int pinCode)
{
try
{
Instance instance = _instanceService.GetByPinCode(pinCode);
if (instance == null)
throw new KeyNotFoundException("Instance was not found");
return new OkObjectResult(instance.ToDTO());
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Delete an instance
/// </summary>
/// <param name="id">Id of instance to delete</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("{id}")]
public ObjectResult DeleteInstance(string id)
{
try
{
if (id == null)
throw new ArgumentNullException("instance param is null");
Instance instance = _instanceService.GetById(id);
// Delete all user in instance
List<User> users = _userService.GetByInstanceId(instance.Id);
foreach(var user in users)
{
_userService.Remove(user.Id);
}
if (instance == null)
throw new KeyNotFoundException("instance does not exist");
_instanceService.Remove(id);
return new ObjectResult("The instance has been deleted") { StatusCode = 202 };
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
}
}

View File

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Manager.Interfaces.DTO;
using Manager.Interfaces.Models;
using Manager.Services;
using ManagerService.Helpers;
using ManagerService.Service.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -26,29 +27,61 @@ namespace ManagerService.Controllers
public class ResourceController : ControllerBase
{
private ResourceDatabaseService _resourceService;
private ResourceDataDatabaseService _resourceDataService;
private SectionDatabaseService _sectionService;
private ConfigurationDatabaseService _configurationService;
private readonly ILogger<ResourceController> _logger;
public ResourceController(ILogger<ResourceController> logger, ResourceDatabaseService resourceService, SectionDatabaseService sectionService)
private static int MaxWidth = 1024;
private static int MaxHeight = 1024;
public ResourceController(ILogger<ResourceController> logger, ResourceDatabaseService resourceService, ResourceDataDatabaseService resourceDataService, SectionDatabaseService sectionService, ConfigurationDatabaseService configurationService)
{
_logger = logger;
_resourceService = resourceService;
_resourceDataService = resourceDataService;
_sectionService = sectionService;
_configurationService = configurationService;
}
/// <summary>
/// Get a list of all resources (summary)
/// </summary>
/// <param name="id">id instance</param>
/// <param name="types">types of resource</param>
[ProducesResponseType(typeof(List<ResourceDTO>), 200)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet]
public ObjectResult Get()
public ObjectResult Get([FromQuery] string instanceId, [FromQuery] List<ResourceType> types)
{
try
{
List<Resource> resources = _resourceService.GetAll();
if (instanceId == null)
throw new ArgumentNullException("InstanceId needed");
List<Resource> resources = new List<Resource>();
if (types.Count > 0)
{
resources = _resourceService.GetAllByType(instanceId, types);
}
else
{
resources = _resourceService.GetAll(instanceId);
}
return new OkObjectResult(resources.Select(r => r.ToDTO(r.Type == ResourceType.ImageUrl)));
List<ResourceDTO> resourceDTOs = new List<ResourceDTO>();
foreach(var resource in resources)
{
ResourceDTO resourceDTO = new ResourceDTO();
resourceDTO = resource.ToDTO();
if(resource.Type == ResourceType.ImageUrl)
{
var resourceData = _resourceDataService.GetByResourceId(resource.Id);
resourceDTO.data = resourceData != null ? resourceData.Data : null;
}
resourceDTOs.Add(resourceDTO);
}
return new OkObjectResult(resourceDTOs.OrderByDescending(r => r.dateCreation));
}
catch (Exception ex)
{
@ -56,7 +89,6 @@ namespace ManagerService.Controllers
}
}
/// <summary>
/// Get a specific resource
/// </summary>
@ -74,8 +106,40 @@ namespace ManagerService.Controllers
if (resource == null)
throw new KeyNotFoundException("This resource was not found");
ResourceDTO resourceDTO = new ResourceDTO();
resourceDTO = resource.ToDTO();
ResourceData resourceData = _resourceDataService.GetByResourceId(id);
resourceDTO.data = resourceData.Data;
/*if (resource.Type == ResourceType.ImageUrl)
{
var resourceData = _resourceDataService.GetByResourceId(resource.Id);
resourceDTO.data = resourceData != null ? resourceData.Data : null;
}*/
return new OkObjectResult(resource.ToDTO(resource.Type == ResourceType.ImageUrl));
// RESIZE IMAGE
/*byte[] imageBytes = Convert.FromBase64String(resourceData.Data);
using (MemoryStream originalImageMemoryStream = new MemoryStream(imageBytes))
{
using (Image image = Image.FromStream(originalImageMemoryStream))
{
var width = image.Width;
var height = image.Height;
if (image.Width > MaxWidth || image.Height > MaxHeight)
{
Size newSize = ImageResizer.ResizeKeepAspect(image.Size, MaxWidth, MaxHeight);
byte[] resizedImage = ImageResizer.ResizeImage(image, newSize.Width, newSize.Height, image.Width, image.Height);
resourceData.Data = Convert.ToBase64String(resizedImage);
ResourceData resourceModified = _resourceDataService.Update(resourceData.Id, resourceData);
}
}
}*/
return new OkObjectResult(resourceDTO);
}
catch (KeyNotFoundException ex)
{
@ -101,19 +165,46 @@ namespace ManagerService.Controllers
try
{
Resource resource = _resourceService.GetById(id);
ResourceData resourceData = _resourceDataService.GetByResourceId(id);
if (resource == null)
if (resource == null || resourceData == null)
throw new KeyNotFoundException("This resource was not found");
var file = Convert.FromBase64String(resource.Data);
var file = Convert.FromBase64String(resourceData.Data);
// RESIZE IMAGE
/*using (MemoryStream originalImageMemoryStream = new MemoryStream(file))
{
using (Image image = Image.FromStream(originalImageMemoryStream))
{
var width = image.Width;
var height = image.Height;
if(image.Width > MaxWidth || image.Height > MaxHeight)
{
Size newSize = ImageResizer.ResizeKeepAspect(image.Size, MaxWidth, MaxHeight);
byte[] resizedImage = ImageResizer.ResizeImage(image, newSize.Width, newSize.Height, image.Width, image.Height);
resourceData.Data = Convert.ToBase64String(resizedImage);
ResourceData resourceModified = _resourceDataService.Update(resourceData.Id, resourceData);
}
}
}*/
if (resource.Type == ResourceType.Image)
{
return new FileContentResult(file, "image/png");
return new FileContentResult(file, "image/png")
{
FileDownloadName = resource.Label + ".png"
};
}
if (resource.Type == ResourceType.Video)
if (resource.Type == ResourceType.Video || resource.Type == ResourceType.Audio)
{
return new FileContentResult(file, "application/octet-stream");
return new FileContentResult(file, "application/octet-stream")
{
FileDownloadName = resource.Type == ResourceType.Audio ? resource.Label + ".mp3" : resource.Label + ".mp4",
};
}
return new FileContentResult(file, "image/png");
@ -135,16 +226,14 @@ namespace ManagerService.Controllers
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("upload"), DisableRequestSizeLimit]
public IActionResult Upload([FromForm] string label, [FromForm] string type) // Create but with local //[FromBody] ResourceDetailDTO uploadResource
public IActionResult Upload([FromForm] string label, [FromForm] string type, [FromForm] string instanceId) // Create but with local //[FromBody] ResourceDetailDTO uploadResource
{
try
{
if (label == null || type == null)
if (label == null || type == null || instanceId == null)
throw new ArgumentNullException("One of resource params is null");
ResourceDTO uploadResource = new ResourceDTO();
uploadResource.type = (ResourceType) Enum.Parse(typeof(ResourceType), type);
uploadResource.label = label;
var resourceType = (ResourceType)Enum.Parse(typeof(ResourceType), type);
List<Resource> resources = new List<Resource>();
foreach (var file in Request.Form.Files)
@ -152,23 +241,42 @@ namespace ManagerService.Controllers
if (file.Length > 0)
{
var stringResult = "";
if (file.Length > 0)
double fileSizeibMbs = (double) ((double)file.Length) / (1024*1024);
if (fileSizeibMbs <= 1.5 || resourceType == ResourceType.Image)
{
using (var ms = new MemoryStream())
{
file.CopyTo(ms);
var fileBytes = ms.ToArray();
if (resourceType == ResourceType.Image)
{
bool isFort = instanceId == "633ee379d9405f32f166f047"; // If fort saint heribert, TODO add watermark in configuration and model
if(isFort) // TODO We need to know for which purpose (mobile or tablet)
{
fileBytes = ImageHelper.ResizeAndAddWatermark(fileBytes, isFort, MaxWidth, MaxHeight);
}
}
stringResult = Convert.ToBase64String(fileBytes);
}
} else
{
throw new FileLoadException(message: "Fichier inexistant ou trop volumineux (max 4Mb)");
}
// Todo add some verification ?
Resource resource = new Resource();
resource.Label = uploadResource.label;
resource.Type = uploadResource.type;
resource.Label = label;
resource.Type = resourceType;
resource.DateCreation = DateTime.Now;
resource.Data = stringResult;
resource.InstanceId = instanceId;
Resource resourceCreated = _resourceService.Create(resource);
resources.Add(resourceCreated);
ResourceData resourceData = new ResourceData();
resourceData.Data = stringResult;
resourceData.ResourceId = resourceCreated.Id;
resourceData.InstanceId = stringResult;
ResourceData resourceDataCreated = _resourceDataService.Create(resourceData);
}
}
return Ok(resources.Select(r => r.ToDTO()));
@ -177,6 +285,10 @@ namespace ManagerService.Controllers
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (FileLoadException ex)
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (InvalidOperationException ex)
{
return new ConflictObjectResult(ex.Message) { };
@ -205,14 +317,25 @@ namespace ManagerService.Controllers
// Todo add some verification ?
Resource resource = new Resource();
resource.InstanceId = newResource.instanceId;
resource.Label = newResource.label;
resource.Type = newResource.type;
resource.DateCreation = DateTime.Now;
resource.Data = newResource.data;
//resource.Data = newResource.data;
resource.InstanceId = newResource.instanceId;
Resource resourceCreated = _resourceService.Create(resource);
return new OkObjectResult(resourceCreated.ToDTO(resource.Type == ResourceType.ImageUrl));
if(resource.Type == ResourceType.ImageUrl || resource.Type == ResourceType.VideoUrl)
{
ResourceData resourceData = new ResourceData();
resourceData.Data = newResource.data;
resourceData.ResourceId = resourceCreated.Id;
resourceData.InstanceId = newResource.instanceId;
ResourceData resourceDataCreated = _resourceDataService.Create(resourceData);
}
return new OkObjectResult(resourceCreated.ToDTO()); // WITHOUT DATA
}
catch (ArgumentNullException ex)
{
@ -251,9 +374,10 @@ namespace ManagerService.Controllers
throw new KeyNotFoundException("Resource does not exist");
// Todo add some verification ?
resource.InstanceId = updatedResource.instanceId;
resource.Label = updatedResource.label;
resource.Type = updatedResource.type;
resource.Data = updatedResource.data;
//resource.Data = updatedResource.data; // NOT ALLOWED
Resource resourceModified = _resourceService.Update(updatedResource.id, resource);
@ -290,12 +414,24 @@ namespace ManagerService.Controllers
if (id == null)
throw new ArgumentNullException("Resource param is null");
if (!_resourceService.IsExist(id))
var ressource = _resourceService.GetById(id);
var ressourceData = _resourceDataService.GetByResourceId(id);
if (ressource == null)
throw new KeyNotFoundException("Resource does not exist");
foreach (var configuration in _configurationService.GetAll(ressource.InstanceId))
{
if (configuration.ImageId == id)
{
configuration.ImageId = null;
configuration.ImageSource = null;
}
}
// Delete all resource occurence
foreach (var section in _sectionService.GetAll())
foreach (var section in _sectionService.GetAll(ressource.InstanceId))
{
if (section.ImageId == id)
{
@ -329,12 +465,55 @@ namespace ManagerService.Controllers
sliderDTO.images = imagesToKeep;
section.Data = JsonConvert.SerializeObject(sliderDTO);
break;
case SectionType.Quizz:
QuizzDTO quizzDTO = JsonConvert.DeserializeObject<QuizzDTO>(section.Data);
foreach (var question in quizzDTO.questions)
{
question.source = question.resourceId == id ? null : question.source;
question.resourceId = question.resourceId == id ? null : question.resourceId;
}
if (quizzDTO.bad_level != null) {
quizzDTO.bad_level.source = quizzDTO.bad_level.resourceId == id ? null : quizzDTO.bad_level.source;
quizzDTO.bad_level.resourceId = quizzDTO.bad_level.resourceId == id ? null : quizzDTO.bad_level.resourceId;
}
if (quizzDTO.medium_level != null)
{
quizzDTO.medium_level.source = quizzDTO.medium_level.resourceId == id ? null : quizzDTO.medium_level.source;
quizzDTO.medium_level.resourceId = quizzDTO.medium_level.resourceId == id ? null : quizzDTO.medium_level.resourceId;
}
if (quizzDTO.good_level != null)
{
quizzDTO.good_level.source = quizzDTO.good_level.resourceId == id ? null : quizzDTO.good_level.source;
quizzDTO.good_level.resourceId = quizzDTO.good_level.resourceId == id ? null : quizzDTO.good_level.resourceId;
}
if (quizzDTO.great_level != null)
{
quizzDTO.great_level.source = quizzDTO.great_level.resourceId == id ? null : quizzDTO.great_level.source;
quizzDTO.great_level.resourceId = quizzDTO.great_level.resourceId == id ? null : quizzDTO.great_level.resourceId;
}
section.Data = JsonConvert.SerializeObject(quizzDTO);
break;
case SectionType.Article:
ArticleDTO articleDTO = JsonConvert.DeserializeObject<ArticleDTO>(section.Data);
List<ImageDTO> imagesArticleToKeep = new List<ImageDTO>();
foreach (var image in articleDTO.images)
{
if (image.resourceId != id)
imagesArticleToKeep.Add(image);
}
articleDTO.images = imagesArticleToKeep;
section.Data = JsonConvert.SerializeObject(articleDTO);
break;
}
_sectionService.Update(section.Id, section);
}
_resourceService.Remove(id);
if (ressourceData != null)
{
_resourceDataService.Remove(ressourceData.Id);
}
return new ObjectResult("The resource has been deleted") { StatusCode = 202 };

View File

@ -1,8 +1,10 @@
using Manager.Interfaces.DTO;
using Manager.Helpers;
using Manager.Interfaces.DTO;
using Manager.Interfaces.Models;
using Manager.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Mqtt.Client.AspNetCore.Services;
using Newtonsoft.Json;
@ -21,10 +23,12 @@ namespace ManagerService.Controllers
private SectionDatabaseService _sectionService;
private ConfigurationDatabaseService _configurationService;
private readonly ILogger<SectionController> _logger;
private readonly IConfiguration _configuration;
public SectionController(ILogger<SectionController> logger, SectionDatabaseService sectionService, ConfigurationDatabaseService configurationService)
public SectionController(IConfiguration configuration, ILogger<SectionController> logger, SectionDatabaseService sectionService, ConfigurationDatabaseService configurationService)
{
_logger = logger;
_configuration = configuration;
_sectionService = sectionService;
_configurationService = configurationService;
}
@ -32,14 +36,35 @@ namespace ManagerService.Controllers
/// <summary>
/// Get a list of all section (summary)
/// </summary>
/// <param name="id">id instance</param>
[ProducesResponseType(typeof(List<SectionDTO>), 200)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet]
public ObjectResult Get()
public ObjectResult Get([FromQuery] string instanceId)
{
try
{
List<Section> sections = _sectionService.GetAll();
List<Section> sections = _sectionService.GetAll(instanceId);
/* CLEAN ARTICLE AUDIO - Init new field AudioIds */
/*foreach (var article in sections.Where(s => s.Type == SectionType.Article))
{
try
{
ArticleDTO articleDTO = JsonConvert.DeserializeObject<ArticleDTO>(article.Data);
List<string> languages = _configuration.GetSection("SupportedLanguages").Get<List<string>>();
articleDTO.audioIds = LanguageInit.Init("Audio", languages, true);
article.Data = JsonConvert.SerializeObject(articleDTO); // Include all info from specific section as JSON
Section sectionModified = _sectionService.Update(article.Id, article);
}
catch (Exception ex)
{
}
}*/
return new OkObjectResult(sections.Select(r => r.ToDTO()));
}
@ -205,6 +230,35 @@ namespace ManagerService.Controllers
}
}
/// <summary>
/// Get all section with beacon
/// </summary>
/// <param name="instanceId">Instance id</param>
[AllowAnonymous]
[ProducesResponseType(typeof(List<SectionDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("beacons/{instanceId}")]
public ObjectResult GetAllBeaconsForInstance(string instanceId)
{
try
{
List<Section> sections = _sectionService.GetAll(instanceId);
sections = sections.Where(s => s.IsBeacon && s.BeaconId != null).ToList();
return new OkObjectResult(sections.Select(s => s.ToDTO()));
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create a new section
/// </summary>
@ -229,6 +283,7 @@ namespace ManagerService.Controllers
// Todo add some verification ?
Section section = new Section();
section.InstanceId = newSection.instanceId;
section.Label = newSection.label;
section.ImageId = newSection.imageId;
section.ImageSource = newSection.imageSource;
@ -240,40 +295,59 @@ namespace ManagerService.Controllers
section.Title = new List<TranslationDTO>();
section.Description = new List<TranslationDTO>();
section.Order = _sectionService.GetAllFromConfiguration(newSection.configurationId).Count;
section.IsBeacon = newSection.isBeacon;
section.BeaconId = newSection.beaconId;
section.Latitude = newSection.latitude;
section.Longitude = newSection.longitude;
section.MeterZoneGPS = newSection.meterZoneGPS;
// Preparation
List<string> languages = new List<string> { "FR", "NL", "EN", "DE" };//_configurationService.GetById(newSection.ConfigurationId).Languages;
List<string> languages = _configuration.GetSection("SupportedLanguages").Get<List<string>>();
var contentArticle = new List<TranslationDTO>();
var mapDTO = new MapDTO(); // For menu dto
var sliderDTO = new SliderDTO(); // For menu dto
foreach (var language in languages)
section.Title = LanguageInit.Init("Title", languages);
section.Description = LanguageInit.Init("Description", languages);
contentArticle = LanguageInit.Init("Content", languages);
/*foreach (var language in languages)
{
TranslationDTO title = new TranslationDTO();
TranslationDTO description = new TranslationDTO();
TranslationDTO content = new TranslationDTO();
title.language = language.ToUpper();
description.language = language.ToUpper();
content.language = language.ToUpper();
switch (language.ToUpper())
{
case "FR":
title.value = "Titre en français";
description.value = "Description en français";
content.value = "Contenu en français";
break;
case "EN":
title.value = "Title in english";
description.value = "Description en anglais";
content.value = "Contenu en anglais";
break;
case "NL":
title.value = "Titre in dutch";
description.value = "Description en néerlandais";
content.value = "Contenu en néerlandais";
break;
case "DE":
title.value = "Titre en allemand";
description.value = "Description en allemand";
content.value = "Contenu en allemand";
break;
}
section.Title.Add(title);
section.Description.Add(description);
}
contentArticle.Add(content);
}*/
section.Title = section.Title.OrderBy(t => t.language).ToList();
section.Description = section.Description.OrderBy(d => d.language).ToList();
@ -333,6 +407,19 @@ namespace ManagerService.Controllers
menuDTO.Sections.Add(section1DTO);*/
section.Data = JsonConvert.SerializeObject(menuDTO); // Include all info from specific section as JSON
break;
case SectionType.Quizz:
QuizzDTO quizzDTO = new QuizzDTO();
quizzDTO.questions = new List<QuestionDTO>();
section.Data = JsonConvert.SerializeObject(quizzDTO); // Include all info from specific section as JSON
break;
case SectionType.Article:
ArticleDTO articleDTO = new ArticleDTO();
articleDTO.images = new List<ImageDTO>();
articleDTO.content = contentArticle;
articleDTO.audioIds = LanguageInit.Init("Audio", languages, true);
section.Data = JsonConvert.SerializeObject(articleDTO); // Include all info from specific section as JSON
break;
}
Section sectionCreated = _sectionService.Create(section);
@ -427,6 +514,7 @@ namespace ManagerService.Controllers
throw new KeyNotFoundException("Section does not exist");
// Todo add some verification ?
section.InstanceId = updatedSection.instanceId;
section.Label = updatedSection.label;
section.Title = updatedSection.title;
section.Description = updatedSection.description;
@ -437,6 +525,11 @@ namespace ManagerService.Controllers
section.IsSubSection = updatedSection.isSubSection;
section.ParentId = updatedSection.parentId;
section.Data = updatedSection.data;
section.IsBeacon = updatedSection.isBeacon;
section.BeaconId = updatedSection.beaconId;
section.Latitude = updatedSection.latitude;
section.Longitude = updatedSection.longitude;
section.MeterZoneGPS = updatedSection.meterZoneGPS;
Section sectionModified = _sectionService.Update(updatedSection.id, section);
@ -606,5 +699,55 @@ namespace ManagerService.Controllers
{
return new ObjectResult("PlayerMessageDTO") { StatusCode = 200 };
}
/// <summary>
/// Useless, just to generate dto code
/// </summary>
[ProducesResponseType(typeof(QuizzDTO), 200)]
[HttpGet("QuizzDTO")]
public ObjectResult GetQuizzDTO()
{
return new ObjectResult("QuizzDTO") { StatusCode = 200 };
}
/// <summary>
/// Useless, just to generate dto code
/// </summary>
[ProducesResponseType(typeof(ArticleDTO), 200)]
[HttpGet("ArticleDTO")]
public ObjectResult GetArticleDTO()
{
return new ObjectResult("ArticleDTO") { StatusCode = 200 };
}
/// <summary>
/// Useless, just to generate dto code
/// </summary>
[ProducesResponseType(typeof(PdfDTO), 200)]
[HttpGet("PdfDTO")]
public ObjectResult GetPdfDTO()
{
return new ObjectResult("PdfDTO") { StatusCode = 200 };
}
/// <summary>
/// Useless, just to generate dto code
/// </summary>
[ProducesResponseType(typeof(PuzzleDTO), 200)]
[HttpGet("PuzzleDTO")]
public ObjectResult GetPuzzleDTO()
{
return new ObjectResult("PuzzleDTO") { StatusCode = 200 };
}
/// <summary>
/// Useless, just to generate dto code
/// </summary>
[ProducesResponseType(typeof(AgendaDTO), 200)]
[HttpGet("AgendaDTO")]
public ObjectResult GetAgendaDTO()
{
return new ObjectResult("AgendaDTO") { StatusCode = 200 };
}
}
}

View File

@ -86,7 +86,7 @@ namespace ManagerService.Controllers
/// Create an user
/// </summary>
/// <param name="newUser">New user info</param>
[AllowAnonymous]
//[AllowAnonymous]
[ProducesResponseType(typeof(UserDetailDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 409)]
@ -99,6 +99,9 @@ namespace ManagerService.Controllers
if (newUser == null)
throw new ArgumentNullException("User param is null");
if (newUser.InstanceId == null)
throw new ArgumentNullException("InstanceId is null");
newUser.Token = _tokenService.GenerateToken(newUser.Email).ToString();
newUser.DateCreation = DateTime.Now;

25
ManagerService/Dockerfile Normal file
View File

@ -0,0 +1,25 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
RUN apt-get update && apt-get install -y apt-utils libgdiplus libc6-dev
WORKDIR /app
EXPOSE 80
VOLUME ["/etc/managerservice"]
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["ManagerService/ManagerService.csproj", "ManagerService/"]
COPY ["Manager.Interfaces/Manager.Interfaces.csproj", "Manager.Interfaces/"]
COPY ["Manager.Framework/Manager.Framework.csproj", "Manager.Framework/"]
RUN dotnet restore "ManagerService/ManagerService.csproj"
COPY . .
WORKDIR "/src/ManagerService"
RUN dotnet build "ManagerService.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ManagerService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ManagerService.dll"]

View File

@ -27,9 +27,9 @@ namespace Mqtt.Client.AspNetCore.Services
public MqttClientService(IMqttClientOptions options)
{
var server = "localhost";
var server = "mymuseum.be";
#if DEBUG
server = "localhost";//"192.168.31.96";
server = "mymuseum.be";//"192.168.31.96";
#endif
this.options = options;
this.options = new MqttClientOptionsBuilder()
@ -141,7 +141,7 @@ namespace Mqtt.Client.AspNetCore.Services
.WithRetainFlag(false)
.Build();
if (mqttClient.IsConnected)
if (mqttClient != null && mqttClient.IsConnected)
await mqttClient.PublishAsync(mqttMessage);
}

View File

@ -0,0 +1,125 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
namespace ManagerService.Helpers
{
public static class ImageHelper
{
public static Size ResizeKeepAspect(this Size src, int maxWidth, int maxHeight, bool enlarge = false)
{
maxWidth = enlarge ? maxWidth : Math.Min(maxWidth, src.Width);
maxHeight = enlarge ? maxHeight : Math.Min(maxHeight, src.Height);
decimal rnd = Math.Min(maxWidth / (decimal)src.Width, maxHeight / (decimal)src.Height);
return new Size((int)Math.Round(src.Width * rnd), (int)Math.Round(src.Height * rnd));
}
// TO Byte[] or Image type
public static dynamic ResizeImage(Image image,
/* note changed names */
int canvasWidth, int canvasHeight,
/* new */
int originalWidth, int originalHeight, bool isImage = false)
{
byte[] convertedToBytes;
System.Drawing.Image thumbnail =
new Bitmap(canvasWidth, canvasHeight); // changed parm names
System.Drawing.Graphics graphic =
System.Drawing.Graphics.FromImage(thumbnail);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
/* ------------------ new code --------------- */
// Figure out the ratio
double ratioX = (double)canvasWidth / (double)originalWidth;
double ratioY = (double)canvasHeight / (double)originalHeight;
// use whichever multiplier is smaller
double ratio = ratioX < ratioY ? ratioX : ratioY;
// now we can get the new height and width
int newHeight = Convert.ToInt32(originalHeight * ratio);
int newWidth = Convert.ToInt32(originalWidth * ratio);
// Now calculate the X,Y position of the upper-left corner
// (one of these will always be zero)
int posX = Convert.ToInt32((canvasWidth - (originalWidth * ratio)) / 2);
int posY = Convert.ToInt32((canvasHeight - (originalHeight * ratio)) / 2);
graphic.Clear(Color.White); // white padding
graphic.DrawImage(image, posX, posY, newWidth, newHeight);
/* ------------- end new code ---------------- */
System.Drawing.Imaging.ImageCodecInfo[] info =
ImageCodecInfo.GetImageEncoders();
EncoderParameters encoderParameters;
encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
100L);
if (isImage)
{
return thumbnail;
}
using (MemoryStream updatedImageMemorySteam = new MemoryStream())
{
thumbnail.Save(updatedImageMemorySteam, System.Drawing.Imaging.ImageFormat.Jpeg);
convertedToBytes = updatedImageMemorySteam.ToArray();
}
return convertedToBytes;
}
public static byte[] ResizeAndAddWatermark(Byte[] bytes, bool watermark, int maxWidth, int maxHeight)
{
byte[] convertedToBytes;
using (MemoryStream originalImageMemoryStream = new MemoryStream(bytes))
{
using (Image image = Image.FromStream(originalImageMemoryStream))
{
Image currentImage = image;
if (image.Width > maxWidth || image.Height > maxHeight)
{
Size newSize = ResizeKeepAspect(image.Size, maxWidth, maxHeight);
Image resizedImage = ImageHelper.ResizeImage(image, newSize.Width, newSize.Height, image.Width, image.Height, true);
currentImage = resizedImage;
}
if(watermark)
{
Font font = new Font("Arial", 25, FontStyle.Italic, GraphicsUnit.Pixel);
Color color = Color.DarkBlue;
Point point = new Point(currentImage.Width /2, (int)Math.Round(currentImage.Height - currentImage.Height * 0.1));
SolidBrush brush = new SolidBrush(color);
using (Graphics graphics = Graphics.FromImage(currentImage))
{
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
graphics.DrawString("fortsaintheribert.be", font, brush, point, stringFormat);
}
}
using (MemoryStream updatedImageMemorySteam = new MemoryStream())
{
currentImage.Save(updatedImageMemorySteam, System.Drawing.Imaging.ImageFormat.Jpeg);
convertedToBytes = updatedImageMemorySteam.ToArray();
}
}
}
return convertedToBytes;
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Manager.Interfaces.DTO;
using Manager.Interfaces.Models;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
namespace Manager.Helpers
{
public class LanguageInit
{
public static List<TranslationDTO> Init(string label, List<string> languages, bool toNull = false)
{
List<TranslationDTO> translations = new List<TranslationDTO>();
foreach (var language in languages)
{
var value = toNull ? null : $"{language} - {label}";
translations.Add(new TranslationDTO() { language = language.ToUpper(), value = value });
}
return translations;
}
}
}

View File

@ -1,12 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<UserSecretsId>d2e1a747-e204-4b43-bf93-abbd19c46417</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.2" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.10.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.14.0" />
<PackageReference Include="MongoDB.Driver" Version="2.12.1" />
<PackageReference Include="MQTTnet.AspNetCore" Version="3.0.13" />
<PackageReference Include="NSwag.AspNetCore" Version="13.10.8" />

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<WebPublishMethod>Custom</WebPublishMethod>
<DockerPublish>true</DockerPublish>
<RegistryUrl>https://registry.unov.be</RegistryUrl>
<UserName>admin</UserName>
<PublishImageTag>latest</PublishImageTag>
<PublishProvider>ContainerRegistry</PublishProvider>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<ProjectGuid>042e0bc4-8dcf-4eec-8420-c71aa85d4d99</ProjectGuid>
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<WebPublishMethod>Custom</WebPublishMethod>
<DockerPublish>true</DockerPublish>
<RegistryUrl>https://registry.unov.be</RegistryUrl>
<UserName />
<PublishImageTag>latest</PublishImageTag>
<PublishProvider>ContainerRegistry</PublishProvider>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<ProjectGuid>042e0bc4-8dcf-4eec-8420-c71aa85d4d99</ProjectGuid>
</PropertyGroup>
</Project>

View File

@ -1,4 +1,5 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
@ -7,15 +8,14 @@
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_URLS": "http://*:5000/",
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://*:5000/"
}
},
"ManagerService": {
@ -26,6 +26,22 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
},
"WSL": {
"commandName": "WSL2",
"launchBrowser": true,
"launchUrl": "https://localhost:5001/weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "https://localhost:5001;http://localhost:5000"
},
"distributionName": ""
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"publishAllPorts": true
}
}
}

View File

@ -18,9 +18,9 @@ namespace Manager.Services
var database = client.GetDatabase("TabletDb");
_Configurations = database.GetCollection<Configuration>("Configurations");
}
public List<Configuration> GetAll()
public List<Configuration> GetAll(string instanceId)
{
return _Configurations.Find(d => true).ToList();
return _Configurations.Find(d => d.InstanceId == instanceId).ToList();
}
public Configuration GetById(string id)

View File

@ -19,9 +19,9 @@ namespace Manager.Services
_Devices = database.GetCollection<Device>("Devices");
}
public List<Device> GetAll()
public List<Device> GetAll(string instanceId)
{
return _Devices.Find(d => true).ToList();
return _Devices.Find(d => d.InstanceId == instanceId).ToList();
}
public List<Device> GetAllConnected()

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Manager.Interfaces.Models;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
namespace Manager.Services
{
public class InstanceDatabaseService
{
private readonly IMongoCollection<Instance> _Instances;
public InstanceDatabaseService(IConfiguration config)
{
var client = new MongoClient(config.GetConnectionString("TabletDb"));
var database = client.GetDatabase("TabletDb");
_Instances = database.GetCollection<Instance>("Instances");
}
public List<Instance> GetAll()
{
return _Instances.Find(m => true).ToList();
}
public Instance GetByName(string name)
{
return _Instances.Find<Instance>(i => i.Name == name).FirstOrDefault();
}
public Instance GetById(string id)
{
return _Instances.Find<Instance>(i => i.Id == id).FirstOrDefault();
}
public Instance GetByPinCode(int pinCode)
{
return _Instances.Find<Instance>(c => c.PinCode == pinCode).FirstOrDefault();
}
public bool IsExist(string id)
{
return _Instances.Find<Instance>(i => i.Id == id).FirstOrDefault() != null ? true : false;
}
public Instance Create(Instance instance)
{
_Instances.InsertOne(instance);
return instance;
}
public Instance Update(string id, Instance instanceIn)
{
_Instances.ReplaceOne(instance => instance.Id == id, instanceIn);
return instanceIn;
}
public void Remove(string id)
{
_Instances.DeleteOne(instance => instance.Id == id);
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Manager.Interfaces.Models;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
namespace Manager.Services
{
public class ResourceDataDatabaseService
{
private readonly IMongoCollection<ResourceData> _ResourcesData;
public ResourceDataDatabaseService(IConfiguration config)
{
var client = new MongoClient(config.GetConnectionString("TabletDb"));
var database = client.GetDatabase("TabletDb");
_ResourcesData = database.GetCollection<ResourceData>("ResourcesData");
}
public List<ResourceData> GetAll(string instanceId)
{
return _ResourcesData.Find(r => r.InstanceId == instanceId).ToList();
}
public ResourceData GetById(string id)
{
return _ResourcesData.Find<ResourceData>(r => r.Id == id).FirstOrDefault();
}
public ResourceData GetByResourceId(string id)
{
return _ResourcesData.Find<ResourceData>(r => r.ResourceId == id).FirstOrDefault();
}
public bool IsExist(string id)
{
return _ResourcesData.Find<ResourceData>(r => r.Id == id).FirstOrDefault() != null ? true : false;
}
public bool IsExistResourceId(string id)
{
return _ResourcesData.Find<ResourceData>(r => r.ResourceId == id).FirstOrDefault() != null ? true : false;
}
public ResourceData Create(ResourceData resource)
{
_ResourcesData.InsertOne(resource);
return resource;
}
public ResourceData Update(string id, ResourceData resourceIn)
{
_ResourcesData.ReplaceOne(r => r.Id == id, resourceIn);
return resourceIn;
}
public void Remove(string id)
{
_ResourcesData.DeleteOne(r => r.Id == id);
}
}
}

View File

@ -18,14 +18,14 @@ namespace Manager.Services
var database = client.GetDatabase("TabletDb");
_Resources = database.GetCollection<Resource>("Resources");
}
public List<Resource> GetAll()
public List<Resource> GetAll(string instanceId)
{
return _Resources.Find(r => true).ToList();
return _Resources.Find(r => r.InstanceId == instanceId).ToList();
}
public Resource GetByType(ResourceType type)
public List<Resource> GetAllByType(string instanceId, List<ResourceType> types)
{
return _Resources.Find<Resource>(r => r.Type == type).FirstOrDefault();
return _Resources.Find<Resource>(r => r.InstanceId == instanceId && types.Contains(r.Type)).ToList();
}
public Resource GetById(string id)

View File

@ -19,9 +19,9 @@ namespace Manager.Services
_Sections = database.GetCollection<Section>("Sections");
}
public List<Section> GetAll()
public List<Section> GetAll(string instanceId)
{
return _Sections.Find(s => !s.IsSubSection).ToList();
return _Sections.Find(s => !s.IsSubSection && s.InstanceId == instanceId).ToList();
}
public List<Section> GetAllFromConfiguration(string configurationId)
@ -29,6 +29,11 @@ namespace Manager.Services
return _Sections.Find(s => !s.IsSubSection && s.ConfigurationId == configurationId).ToList();
}
public List<string> GetAllIdsFromConfiguration(string configurationId)
{
return _Sections.Find(s => !s.IsSubSection && s.ConfigurationId == configurationId).ToList().Select(s => s.Id).ToList();
}
public List<Section> GetAllSubSection(string parentId)
{
return _Sections.Find(s => s.IsSubSection && s.ParentId == parentId).ToList();

View File

@ -13,6 +13,7 @@ using Microsoft.IdentityModel.Tokens;
using Manager.Framework.Business;
using Manager.Interfaces.DTO;
using System.IdentityModel.Tokens.Jwt;
using Manager.Services;
namespace ManagerService.Service.Services
{
@ -24,6 +25,7 @@ namespace ManagerService.Service.Services
private readonly ILogger<TokensService> _logger;
private readonly TokensSettings _tokenSettings;
private readonly ProfileLogic _profileLogic;
private InstanceDatabaseService _instanceService;
private readonly SigningCredentials _signingCredentials;
@ -35,11 +37,12 @@ namespace ManagerService.Service.Services
/// <param name="context">Database context</param>
/// <param name="profileLogic">Profile logic</param>
/// <param name="emailClient">Email client</param>
public TokensService(ILogger<TokensService> logger, IOptions<TokensSettings> tokenSettings, ProfileLogic profileLogic)
public TokensService(ILogger<TokensService> logger, IOptions<TokensSettings> tokenSettings, ProfileLogic profileLogic, InstanceDatabaseService instanceService)
{
_logger = logger;
_tokenSettings = tokenSettings.Value;
_profileLogic = profileLogic;
_instanceService = instanceService;
var key = Encoding.UTF8.GetBytes(_tokenSettings.Secret);
_signingCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);
@ -51,17 +54,16 @@ namespace ManagerService.Service.Services
/// <param name="email">Email</param>
/// <param name="password">Password</param>
/// <returns>Token DTO in case of success</returns>
public TokenDTO Authenticate(string email, string password)
public TokenDTO Authenticate(User user, string password)
{
try
{
var claims = new List<System.Security.Claims.Claim>();
var expiration = DateTime.UtcNow.AddMinutes(_tokenSettings.AccessTokenExpiration);
// Todo nothing good here..
var profile = _profileLogic.Authenticate(email, password);
_profileLogic.TestPassword(user.Email, user.Password, password);
claims.Add(new Claim(ClaimTypes.Email, email));
claims.Add(new Claim(ClaimTypes.Email, user.Email));
// TODO: add refresh token support
@ -74,23 +76,27 @@ namespace ManagerService.Service.Services
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var instance = _instanceService.GetById(user.InstanceId);
return new TokenDTO()
{
access_token = tokenHandler.WriteToken(token),
expires_in = _tokenSettings.AccessTokenExpiration * 60,
expiration = new DateTimeOffset(token.ValidTo),
token_type = "Bearer",
scope = Security.Scope
scope = Security.Scope,
instanceId = user.InstanceId,
pinCode = instance.PinCode
};
}
catch (UnauthorizedAccessException ex)
{
_logger?.LogError(ex, $"Authenticate error for user '{email}': unauthorized access");
_logger?.LogError(ex, $"Authenticate error for user '{user.Email}': unauthorized access");
throw;
}
catch (Exception ex)
{
_logger?.LogError(ex, $"Authenticate error for user '{email}': {ex.Message}");
_logger?.LogError(ex, $"Authenticate error for user '{user.Email}': {ex.Message}");
throw;
}
}

View File

@ -20,22 +20,27 @@ namespace Manager.Services
}
public List<User> GetAll()
{
return _Users.Find(m => true).ToList();
return _Users.Find(u => true).ToList();
}
public User GetByEmail(string email)
{
return _Users.Find<User>(m => m.Email == email).FirstOrDefault();
return _Users.Find<User>(u => u.Email == email).FirstOrDefault();
}
public User GetById(string id)
{
return _Users.Find<User>(m => m.Id == id).FirstOrDefault();
return _Users.Find<User>(u => u.Id == id).FirstOrDefault();
}
public List<User> GetByInstanceId(string id)
{
return _Users.Find<User>(u => u.InstanceId == id).ToList();
}
public bool IsExist(string id)
{
return _Users.Find<User>(d => d.Id == id).FirstOrDefault() != null ? true : false;
return _Users.Find<User>(u => u.Id == id).FirstOrDefault() != null ? true : false;
}
public User Create(User user)

View File

@ -1,5 +1,6 @@
using Manager.Framework.Business;
using Manager.Framework.Models;
using Manager.Helpers;
using Manager.Interfaces.Models;
using Manager.Services;
using ManagerService.Extensions;
@ -132,14 +133,19 @@ namespace ManagerService
};
});
#if RELEASE
services.AddMqttClientHostedService();
#endif
services.AddScoped(typeof(ProfileLogic));
services.AddScoped<TokensService>();
services.AddScoped<UserDatabaseService>();
services.AddScoped<SectionDatabaseService>();
services.AddScoped<ConfigurationDatabaseService>();
services.AddScoped<ResourceDatabaseService>();
services.AddScoped<ResourceDataDatabaseService>();
services.AddScoped<LanguageInit>();
services.AddScoped<DeviceDatabaseService>();
services.AddScoped<InstanceDatabaseService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -151,11 +157,12 @@ namespace ManagerService
if (env.IsDevelopment())
{
//app.UseDeveloperExceptionPage();
app.UseExceptionHandler(HandleError);
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseExceptionHandler(HandleError);
//app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();

View File

@ -1,8 +1,10 @@
{
"ConnectionStrings": {
//"TabletDb": "mongodb://admin:MioTech4ever!@localhost:27017" //DEV
//"TabletDb": "mongodb://admin:MioTech4ever!@localhost:27017" //PROD - Thomas
"TabletDb": "mongodb://admin:mdlf2021!@localhost:27017" //PROD
//"TabletDb": "mongodb://admin:MioTech4ever!@localhost:27017", //PROD - Thomas
//"TabletDb": "mongodb://admin:MioTech4ever!@192.168.31.140:27017" //PROD - Thomas
//"TabletDb": "mongodb://admin:mdlf2021!@localhost:27017" //PROD MDLF
"TabletDb": "mongodb://admin:MyMuseum2022!@51.77.222.154:27017" //PROD MyMuseum
},
"Logging": {
"LogLevel": {
@ -30,8 +32,9 @@
},
"ClientSettings": {
"Id": "ManagerService",
"UserName": "admin",
"Password": "mdlf2021!"
"UserName": "user1", //admin
"Password": "MyMuseum2023!" //mdlf2021!
},
"Urls": "http://localhost:5002"
"SupportedLanguages": [ "FR", "NL", "EN", "DE", "IT", "ES", "PL", "CN", "AR", "UK" ]
//"Urls": "http://[::]:80"
}

View File

@ -1,4 +0,0 @@
# Publier sur docker
Publish via Visual studio, le docker file est à jour.
(registry.unov.be)

View File

@ -0,0 +1 @@
Ajout du quizz

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
{
"runtimeOptions": {
"additionalProbingPaths": [
"C:\\Users\\thoma\\.dotnet\\store\\|arch|\\|tfm|",
"C:\\Users\\thoma\\.nuget\\packages"
]
}
}

View File

@ -0,0 +1,14 @@
{
"runtimeOptions": {
"tfm": "netcoreapp3.1",
"framework": {
"name": "Microsoft.AspNetCore.App",
"version": "3.1.0"
},
"configProperties": {
"System.GC.Server": true,
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More