manager-service/ManagerService/Controllers/SectionMapController.cs
Thomas Fransolet b87e49d808 Cle d'API sur les routes visiteur, canal VR et contenu immersif
Securite
- RequireAppKey : filtre qui exige une cle d'API valide ou un utilisateur du
  manager. Pose sur les routes de contenu consommees par les apps visiteur
  (Configuration, Section, Resource, SectionMap, SectionEvent, SectionAgenda,
  SectionParcours, SectionQuiz, ApplicationInstance). Un [Authorize] d'action
  ne peut pas assouplir celui de la classe ; seul [AllowAnonymous] le
  court-circuite, et le filtre redevient le controle d'acces. Il ferme
  l'enumeration par identifiant, pas la confidentialite : la cle s'obtient
  par le slug ou le pincode.
- Instance/slug/{slug} rendait le pinCode, l'adresse de facturation, la TVA et
  les quotas a qui lit l'URL du site visiteur. StripCommercialFields est
  desormais applique sur slug et byPin ; isTrialActive reste expose pour le
  filigrane d'essai.
- Device.Create et Device/{id}/detail repondaient 403 a toute tablette depuis
  a452f4a (13/03) : la classe exige InstanceAdmin, une cle ne porte que
  AppRead. Ouverts a la cle, le cloisonnement par instance etait deja ecrit.

Canal VR
- Device.AppType (defaut Tablet, backfill a 1) ; Create resout
  l'ApplicationInstance sur ce type au lieu de Tablet en dur.
- Get filtre optionnellement par appType ; DeviceDetailDTO expose appVersion
  et lastSeen.
- PUT Device/{id}/heartbeat : batterie, version, connexion. Volontairement
  etroit, une app ne peut ni se renommer ni changer d'instance.
- ApiKeyAppType.VrApp en fin d'enum.

Contenu immersif
- ResourceType : Image360 (11), Video360 (12), Model3D (13), en fin d'enum.
- Section Scene3D : un modele GLB et ses points d'interet, en objet manipule
  ou en decor habite. Les points sont des GeoPoint, avec une LocalTransform
  en jsonb (convention glTF) ; CRUD dans SectionScene3DController.
- Instance.HasImmersiveContent : l'add-on ajoute 100 Go au quota de stockage,
  repose apres un changement de plan et retire a la desactivation.
- ImmersiveBackground (owned) sur Configuration et ApplicationInstance, avec
  une image de repli pour les canaux qui ne rendent pas l'immersif.

Export de configuration
- exportVersion (1) et generatedAt : le JSON devient un contrat, lu tel quel
  par l'app Unity.
- Section.ToDTO() n'etant pas virtuelle, l'export ne portait aucun champ
  specifique de sous-type. Passe par SectionFactory.ToDTO, et charge les
  points des Map et des Scene3D.
- Le fond immersif et son repli partent avec les ressources, URL resolues.

Migrations : AddAppTypeToDevice, AddScene3DSectionAndImmersiveAddon,
AddImmersiveBackground.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-13 16:54:10 +02:00

722 lines
29 KiB
C#
Raw Blame History

using Manager.DTOs;
using ManagerService.Data;
using ManagerService.Data.SubSection;
using ManagerService.DTOs;
using ManagerService.Helpers;
using ManagerService.Services;
using Microsoft.AspNetCore.Authorization;
using ManagerService.Security;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NSwag.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ManagerService.Controllers
{
[Authorize(Policy = ManagerService.Service.Security.Policies.ContentEditor)]
[ApiController, Route("api/[controller]")]
[OpenApiTag("Section map", Description = "Section map management")]
public class SectionMapController : ControllerBase
{
private readonly MyInfoMateDbContext _myInfoMateDbContext;
private readonly ILogger<SectionMapController> _logger;
private readonly IConfiguration _configuration;
IHexIdGeneratorService idService = new HexIdGeneratorService();
public SectionMapController(IConfiguration configuration, ILogger<SectionMapController> logger, MyInfoMateDbContext myInfoMateDbContext)
{
_logger = logger;
_configuration = configuration;
_myInfoMateDbContext = myInfoMateDbContext;
}
/// <summary>
/// Get all points from section
/// </summary>
/// <param name="sectionId">Section id</param>
[AllowAnonymous]
[RequireAppKey]
[ProducesResponseType(typeof(List<GeoPointDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{sectionId}/points")]
public ObjectResult GetAllGeoPointsFromSection(string sectionId)
{
try
{
SectionMap sectionMap = _myInfoMateDbContext.Sections.OfType<SectionMap>().Include(sm => sm.MapPoints).FirstOrDefault(sm => sm.Id == sectionId);
if (sectionMap == null)
throw new KeyNotFoundException("Section map does not exist");
List<GeoPointDTO> geoPointDTOs = new List<GeoPointDTO>();
foreach (var point in sectionMap.MapPoints)
{
foreach (var content in point.Contents) {
var resource = _myInfoMateDbContext.Resources.FirstOrDefault(r => r.Id == content.resourceId);
if (resource != null)
{
content.resource = resource.ToDTO();
}
}
geoPointDTOs.Add(new GeoPointDTO()
{
id = point.Id,
title = point.Title,
description = point.Description,
contents = point.Contents,
categorieId = point.CategorieId,
geometry = point.Geometry?.ToDto(),
polyColor = point.PolyColor,
imageResourceId = point.ImageResourceId,
imageUrl = point.ImageUrl,
schedules = point.Schedules,
prices = point.Prices,
phone = point.Phone,
email = point.Email,
site = point.Site
});
}
return new OkObjectResult(geoPointDTOs);
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create new point
/// </summary>
/// <param name="sectionId">Section Id</param>
/// <param name="geoPointDTO">geoPoint</param>
[ProducesResponseType(typeof(GeoPointDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 409)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("{sectionId}/points")]
public ObjectResult Create(string sectionId, [FromBody] GeoPointDTO geoPointDTO)
{
try
{
if (sectionId == null)
throw new ArgumentNullException("Section param is null");
if (geoPointDTO == null)
throw new ArgumentNullException("GeoPoint is null");
var existingSection = _myInfoMateDbContext.Sections.OfType<SectionMap>().Include(s => s.MapPoints).FirstOrDefault(s => s.Id == sectionId);
if (existingSection == null)
throw new KeyNotFoundException("Section map does not exist");
// TODO verification ?
GeoPoint geoPoint = new GeoPoint();
geoPoint.Title = geoPointDTO.title;
geoPoint.Description = geoPointDTO.description;
geoPoint.Contents = geoPointDTO.contents;
geoPoint.CategorieId = geoPointDTO.categorieId;
if (geoPointDTO.geometry != null)
{
geoPoint.Geometry = geoPointDTO.geometry.FromDto();
}
else
{
geoPoint.Geometry = null;
}
geoPoint.PolyColor = geoPointDTO.polyColor;
geoPoint.ImageResourceId = geoPointDTO.imageResourceId;
geoPoint.ImageUrl = geoPointDTO.imageUrl; // TO BE TESTED ? Depends on front
geoPoint.Schedules = geoPointDTO.schedules;
geoPoint.Prices = geoPointDTO.prices;
geoPoint.Phone = geoPointDTO.phone;
geoPoint.Email = geoPointDTO.email;
geoPoint.Site = geoPointDTO.site;
if (existingSection.MapPoints == null)
{
existingSection.MapPoints = [];
}
existingSection.MapPoints.Add(geoPoint);
_myInfoMateDbContext.SaveChanges();
var geoPointDto = new GeoPointDTO()
{
id = geoPoint.Id,
title = geoPoint.Title,
description = geoPoint.Description,
contents = geoPoint.Contents,
categorieId = geoPoint.CategorieId,
geometry = geoPoint.Geometry?.ToDto(),
polyColor = geoPointDTO.polyColor,
imageResourceId = geoPoint.ImageResourceId,
imageUrl = geoPoint.ImageUrl,
schedules = geoPoint.Schedules,
prices = geoPoint.Prices,
phone = geoPoint.Phone,
email = geoPoint.Email,
site = geoPoint.Site
};
return new OkObjectResult(geoPointDto);
}
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 a geo point
/// </summary>
/// <param name="updatedGeoPoint">GeoPoint to update</param>
[ProducesResponseType(typeof(GeoPointDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut]
public ObjectResult Update([FromBody] GeoPointDTO geoPointDTO)
{
try
{
if (geoPointDTO == null)
throw new ArgumentNullException("GeoPoint param is null");
var existingGeoPoint = _myInfoMateDbContext.GeoPoints.FirstOrDefault(gp => gp.Id == geoPointDTO.id);
if (existingGeoPoint == null)
throw new KeyNotFoundException("GeoPoint does not exist");
existingGeoPoint.Title = geoPointDTO.title;
existingGeoPoint.Description = geoPointDTO.description;
existingGeoPoint.Contents = geoPointDTO.contents;
existingGeoPoint.CategorieId = geoPointDTO.categorieId;
existingGeoPoint.Geometry = geoPointDTO.geometry.FromDto();
existingGeoPoint.PolyColor = geoPointDTO.polyColor;
existingGeoPoint.ImageResourceId = geoPointDTO.imageResourceId;
existingGeoPoint.ImageUrl = geoPointDTO.imageUrl;
existingGeoPoint.Schedules = geoPointDTO.schedules;
existingGeoPoint.Prices = geoPointDTO.prices;
existingGeoPoint.Phone = geoPointDTO.phone;
existingGeoPoint.Email = geoPointDTO.email;
existingGeoPoint.Site = geoPointDTO.site;
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(existingGeoPoint.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>
/// Update sections order
/// </summary>
/// <param name="updatedSectionsOrder">New sections order</param>
/*[ProducesResponseType(typeof(string), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut("order")]
public ObjectResult UpdateOrder([FromBody] List<SectionDTO> updatedSectionsOrder)
{
// TODO REWRITE LOGIC..
try
{
if (updatedSectionsOrder == null)
throw new ArgumentNullException("Sections param is null");
foreach (var section in updatedSectionsOrder)
{
var sectionDB = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == section.id);
if (sectionDB == null)
throw new KeyNotFoundException($"Section {section.label} with id {section.id} does not exist");
}
foreach (var updatedSection in updatedSectionsOrder)
{
var section = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == updatedSection.id);
//OldSection section = _sectionService.GetById(updatedSection.id);
section.Order = updatedSection.order.GetValueOrDefault();
_myInfoMateDbContext.SaveChanges();
//_sectionService.Update(section.Id, section);
}
if (updatedSectionsOrder.Count > 0) {
MqttClientService.PublishMessage($"config/{updatedSectionsOrder[0].configurationId}", JsonConvert.SerializeObject(new PlayerMessageDTO() { configChanged = true }));
}
return new ObjectResult("Sections order has been successfully modified") { StatusCode = 200 };
}
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>
/// Delete a geopoint
/// </summary>
/// <param name="geoPointId">Id of geopoint to delete</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("points/{geoPointId}")]
public ObjectResult Delete(int geoPointId)
{
try
{
var geoPoint = _myInfoMateDbContext.GeoPoints.FirstOrDefault(gp => gp.Id == geoPointId);
if (geoPoint == null)
throw new KeyNotFoundException("GeoPoint does not exist");
_myInfoMateDbContext.Remove(geoPoint);
_myInfoMateDbContext.SaveChanges();
return new ObjectResult("The geopoint 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 };
}
}
/// <summary>
/// Get all guided path from section
/// </summary>
/// <param name="sectionMapId">Section id</param>
[AllowAnonymous]
[RequireAppKey]
[ProducesResponseType(typeof(List<GuidedPathDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{sectionMapId}/guided-path")]
public ObjectResult GetAllGuidedPathFromSection(string sectionMapId)
{
try
{
List<GuidedPath> guidedPaths = _myInfoMateDbContext.GuidedPaths
.Include(gp => gp.Steps).ThenInclude(gp => gp.QuizQuestions).ThenInclude(q => q.PuzzleImage)
.Where(gp => gp.SectionEventId == sectionMapId).ToList();
/*List<ProgrammeBlock> programmeBlocks = new List<ProgrammeBlock>();
foreach (var program in sectionEvent.Programme)
{
foreach (var mapAnnotation in program.MapAnnotations) {
var resource = _myInfoMateDbContext.Resources.FirstOrDefault(r => r.Id == mapAnnotation.IconResourceId);
if (resource != null)
{
mapAnnotation.IconResource = resource; // TO check.. use DTO instead ?
}
}
}*/
return new OkObjectResult(guidedPaths.Select(gp => gp.ToDTO()));
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create new guided path
/// </summary>
/// <param name="sectionMapId">Section map Id</param>
/// <param name="guidedPath">guidedPath</param>
[ProducesResponseType(typeof(GuidedPathDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 409)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("{sectionMapId}/guided-path")]
public ObjectResult CreateGuidedPath(string sectionMapId, [FromBody] GuidedPathDTO guidedPathDTO)
{
try
{
if (sectionMapId == null)
throw new ArgumentNullException("Section param is null");
if (guidedPathDTO == null)
throw new ArgumentNullException("GuidedPath param is null");
var existingSectionEvent = _myInfoMateDbContext.Sections.OfType<SectionEvent>().FirstOrDefault(se => se.Id == sectionMapId);
if (existingSectionEvent == null)
throw new KeyNotFoundException("Section event does not exist");
GuidedPath guidedPath = new GuidedPath().FromDTO(guidedPathDTO);
guidedPath.Id = idService.GenerateHexId();
guidedPath.SectionEventId = existingSectionEvent?.Id;
guidedPath.Steps = new List<GuidedStep>();
foreach (var stepDTO in guidedPathDTO.steps ?? new List<GuidedStepDTO>())
{
GuidedStep step = new GuidedStep().FromDTO(stepDTO);
step.Id = idService.GenerateHexId();
step.GuidedPathId = guidedPath.Id;
guidedPath.Steps.Add(step);
}
_myInfoMateDbContext.GuidedPaths.Add(guidedPath);
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(guidedPath.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 a guided path
/// </summary>
/// <param name="guidedPath">GuidedPath to update</param>
[ProducesResponseType(typeof(GuidedPathDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut("guided-path")]
public ObjectResult UpdateGuidedPath([FromBody] GuidedPathDTO guidedPathDTO)
{
try
{
if (guidedPathDTO == null)
throw new ArgumentNullException("GuidedPath param is null");
var existingGuidedPath = _myInfoMateDbContext.GuidedPaths
.Include(gp => gp.Steps).ThenInclude(s => s.QuizQuestions)
.FirstOrDefault(gp => gp.Id == guidedPathDTO.id);
if (existingGuidedPath == null)
throw new KeyNotFoundException("GuidedPath does not exist");
existingGuidedPath.InstanceId = guidedPathDTO.instanceId;
existingGuidedPath.Title = guidedPathDTO.title ?? new List<TranslationDTO>();
existingGuidedPath.Description = guidedPathDTO.description ?? new List<TranslationDTO>();
existingGuidedPath.SectionEventId = guidedPathDTO.sectionEventId;
existingGuidedPath.IsLinear = guidedPathDTO.isLinear;
existingGuidedPath.RequireSuccessToAdvance = guidedPathDTO.requireSuccessToAdvance;
existingGuidedPath.HideNextStepsUntilComplete = guidedPathDTO.hideNextStepsUntilComplete;
existingGuidedPath.Order = guidedPathDTO.order.GetValueOrDefault();
// Sync steps
var dtoStepIds = (guidedPathDTO.steps ?? new List<GuidedStepDTO>())
.Where(s => s.id != null)
.Select(s => s.id)
.ToHashSet();
// Delete removed steps
var stepsToRemove = existingGuidedPath.Steps
.Where(s => !dtoStepIds.Contains(s.Id))
.ToList();
foreach (var s in stepsToRemove)
existingGuidedPath.Steps.Remove(s);
// Create or update steps
foreach (var stepDTO in guidedPathDTO.steps ?? new List<GuidedStepDTO>())
{
var existing = existingGuidedPath.Steps.FirstOrDefault(s => s.Id == stepDTO.id);
if (existing != null)
{
existing.FromDTO(stepDTO);
existing.GuidedPathId = existingGuidedPath.Id;
}
else
{
var newStep = new GuidedStep().FromDTO(stepDTO);
newStep.Id = idService.GenerateHexId();
newStep.GuidedPathId = existingGuidedPath.Id;
existingGuidedPath.Steps.Add(newStep);
}
}
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(existingGuidedPath.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>
/// Delete a guided path
/// </summary>
/// <param name="guidedPathId">Id of the guidedPath to delete</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("guided-path/{guidedPathId}")]
public ObjectResult DeleteGuidedPath(string guidedPathId)
{
try
{
var guidedPath = _myInfoMateDbContext.GuidedPaths.FirstOrDefault(gp => gp.Id == guidedPathId);
if (guidedPath == null)
throw new KeyNotFoundException("GuidedPath does not exist");
_myInfoMateDbContext.Remove(guidedPath);
_myInfoMateDbContext.SaveChanges();
return new ObjectResult("The guidedPath 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 };
}
}
/// <summary>
/// Get all guided step from guided path
/// </summary>
/// <param name="guidedPathId">Guided path id</param>
[AllowAnonymous]
[RequireAppKey]
[ProducesResponseType(typeof(List<GuidedStepDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("guided-path/{guidedPathId}/guided-step")]
public ObjectResult GetAllGuidedStepFromGuidedPath(string guidedPathId)
{
try
{
List<GuidedStep> guidedSteps = _myInfoMateDbContext.GuidedSteps
.Include(gs => gs.QuizQuestions)
.Where(gs => gs.GuidedPathId == guidedPathId).ToList();
/*List<ProgrammeBlock> programmeBlocks = new List<ProgrammeBlock>();
foreach (var program in sectionEvent.Programme)
{
foreach (var mapAnnotation in program.MapAnnotations) {
var resource = _myInfoMateDbContext.Resources.FirstOrDefault(r => r.Id == mapAnnotation.IconResourceId);
if (resource != null)
{
mapAnnotation.IconResource = resource; // TO check.. use DTO instead ?
}
}
}*/
return new OkObjectResult(guidedSteps.Select(gs => gs.ToDTO()));
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create new guided step
/// </summary>
/// <param name="guidedPathId">guidedPath Id</param>
/// <param name="guidedStep">guidedStep</param>
[ProducesResponseType(typeof(GuidedStepDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 409)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("guided-path/{guidedPathId}/guided-step")]
public ObjectResult CreateGuidedStep(string guidedPathId, [FromBody] GuidedStepDTO guidedStepDTO)
{
try
{
if (guidedPathId == null)
throw new ArgumentNullException("GuidedPathId param is null");
if (guidedStepDTO == null)
throw new ArgumentNullException("GuidedStep param is null");
GuidedStep guidedStep = new GuidedStep().FromDTO(guidedStepDTO);
guidedStep.Id = idService.GenerateHexId();
guidedStep.GuidedPathId = guidedPathId;
_myInfoMateDbContext.GuidedSteps.Add(guidedStep);
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(guidedStep.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 a guided step
/// </summary>
/// <param name="guidedStep">GuidedStep to update</param>
[ProducesResponseType(typeof(GuidedStepDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut("guided-step")]
public ObjectResult UpdateGuidedStep([FromBody] GuidedStepDTO guidedStepDTO)
{
try
{
if (guidedStepDTO == null)
throw new ArgumentNullException("GuidedStep param is null");
var existingGuidedStep = _myInfoMateDbContext.GuidedSteps.FirstOrDefault(gs => gs.Id == guidedStepDTO.id);
if (existingGuidedStep == null)
throw new KeyNotFoundException("GuidedStep does not exist");
existingGuidedStep.GuidedPathId = guidedStepDTO.guidedPathId;
existingGuidedStep.Order = guidedStepDTO.order.GetValueOrDefault();
existingGuidedStep.Title = guidedStepDTO.title;
existingGuidedStep.Description = guidedStepDTO.description;
if (guidedStepDTO.geometry != null)
{
existingGuidedStep.Geometry = guidedStepDTO.geometry.FromDto();
}
else
{
existingGuidedStep.Geometry = null;
}
existingGuidedStep.ZoneRadiusMeters = guidedStepDTO.zoneRadiusMeters;
existingGuidedStep.ImageUrl = guidedStepDTO.imageUrl;
existingGuidedStep.QuizQuestions = guidedStepDTO.quizQuestions; // <20> convertir si besoin ?
existingGuidedStep.IsStepTimer = guidedStepDTO.isStepTimer;
existingGuidedStep.TimerSeconds = guidedStepDTO.timerSeconds;
existingGuidedStep.TimerExpiredMessage = guidedStepDTO.timerExpiredMessage;
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(existingGuidedStep.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>
/// Delete a guided step
/// </summary>
/// <param name="guidedStepId">Id of the guidedStep to delete</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("guided-step/{guidedStepId}")]
public ObjectResult DeleteGuidedStep(string guidedStepId)
{
try
{
var guidedStep = _myInfoMateDbContext.GuidedSteps.Include(gs => gs.QuizQuestions).FirstOrDefault(gs => gs.Id == guidedStepId);
if (guidedStep == null)
throw new KeyNotFoundException("GuidedStep does not exist");
guidedStep.QuizQuestions.Clear();
_myInfoMateDbContext.Remove(guidedStep);
_myInfoMateDbContext.SaveChanges();
return new ObjectResult("The guidedStep 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 };
}
}
}
}