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>
135 lines
4.3 KiB
C#
135 lines
4.3 KiB
C#
using ManagerService.DTOs;
|
|
using System;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace ManagerService.Data
|
|
{
|
|
/// <summary>
|
|
/// Resource Information
|
|
/// </summary>
|
|
[Index(nameof(InstanceId))]
|
|
public class Resource : IAuditableEntity
|
|
{
|
|
[Key]
|
|
[Required]
|
|
/*[BsonId]
|
|
[BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]*/
|
|
public string Id { get; set; }
|
|
|
|
/*[BsonElement("Type")]
|
|
[BsonRequired]*/
|
|
[Required]
|
|
public ResourceType Type { get; set; }
|
|
|
|
/*[BsonElement("Label")]
|
|
[BsonRequired]*/
|
|
[Required]
|
|
public string Label { get; set; }
|
|
|
|
/*[BsonElement("DateCreation")]*/
|
|
public DateTime DateCreation { get; set; }
|
|
|
|
public DateTime DateUpdate { get; set; }
|
|
|
|
/*[BsonElement("InstanceId")]
|
|
[BsonRequired]*/
|
|
[Required]
|
|
public string InstanceId { get; set; }
|
|
|
|
/*[BsonElement("URL")]*/
|
|
public string Url { get; set; } // Firebase url
|
|
|
|
public long SizeBytes { get; set; } = 0;
|
|
|
|
/// <summary>
|
|
/// Clé relative dans le stockage (`pictures/{instanceId}/{resourceId}`), source de vérité.
|
|
/// L'URL absolue à jeton reste dans Url, mais elle n'est plus ce dont on part.
|
|
/// </summary>
|
|
public string StoragePath { get; set; }
|
|
|
|
/// <summary>
|
|
/// Vrai nom de fichier ("brochure-2026.pdf"). Ni Label (libellé libre) ni Url (jeton)
|
|
/// ne le donnent — nécessaire pour choisir l'extracteur et citer la source.
|
|
/// </summary>
|
|
public string FileName { get; set; }
|
|
|
|
/// <summary>Largeur en pixels, connue de manager-app au moment de l'upload. Nulle sur les ressources anciennes.</summary>
|
|
public int? Width { get; set; }
|
|
|
|
/// <summary>Hauteur en pixels, connue de manager-app au moment de l'upload. Nulle sur les ressources anciennes.</summary>
|
|
public int? Height { get; set; }
|
|
|
|
/// <summary>Inclure ce document dans les connaissances du guide IA. Exposé dans l'UI en V2 seulement.</summary>
|
|
public bool IncludeInAiKnowledge { get; set; } = false;
|
|
|
|
public AiIndexStatus AiIndexStatus { get; set; } = AiIndexStatus.NotIndexed;
|
|
|
|
/// <summary>Raison de l'échec d'indexation, affichée telle quelle au client.</summary>
|
|
public string AiIndexMessage { get; set; }
|
|
|
|
public DateTime? AiIndexedAt { get; set; }
|
|
|
|
public int AiChunkCount { get; set; } = 0;
|
|
|
|
public ResourceDTO ToDTO()
|
|
{
|
|
return new ResourceDTO()
|
|
{
|
|
id = Id,
|
|
label = Label,
|
|
type = Type,
|
|
url = Url,
|
|
dateCreation = DateCreation,
|
|
dateUpdate = DateUpdate,
|
|
instanceId = InstanceId,
|
|
sizeBytes = SizeBytes,
|
|
fileName = FileName,
|
|
width = Width,
|
|
height = Height
|
|
};
|
|
}
|
|
}
|
|
|
|
public enum ResourceType
|
|
{
|
|
// ⚠️ Persisté en int. Ne JAMAIS réordonner ni insérer au milieu : les valeurs
|
|
// existantes en base se décaleraient (les PDF deviendraient des JSON).
|
|
// Toute nouvelle valeur s'ajoute à la fin.
|
|
Image, // 0
|
|
Video, // 1
|
|
ImageUrl, // 2
|
|
VideoUrl, // 3
|
|
Audio, // 4
|
|
PDF, // 5
|
|
JSON, // 6
|
|
JSONUrl, // 7
|
|
Word, // 8
|
|
PowerPoint, // 9
|
|
Text, // 10
|
|
|
|
/// <summary>Photo équirectangulaire, affichée en skybox dans un casque.</summary>
|
|
Image360, // 11
|
|
|
|
/// <summary>Vidéo équirectangulaire, même usage.</summary>
|
|
Video360, // 12
|
|
|
|
/// <summary>
|
|
/// Modèle 3D glTF binaire. Posé ici en même temps que les deux précédents parce
|
|
/// qu'une valeur d'enum ne coûte rien à ajouter et que la suivante devra encore
|
|
/// aller en fin — mais son exploitation demande bien plus : un type de section
|
|
/// dédié, une position 3D sur les points d'intérêt et un éditeur de placement
|
|
/// (voir le §9 de DOCS/v2/vr-quest-unity-plan.md).
|
|
/// </summary>
|
|
Model3D // 13
|
|
}
|
|
|
|
public enum AiIndexStatus
|
|
{
|
|
NotIndexed = 0,
|
|
Pending = 1,
|
|
Indexed = 2,
|
|
Failed = 3
|
|
}
|
|
}
|