From 4802ff09c98c6c2d22000ce3b5a9a4ab71c3ac94 Mon Sep 17 00:00:00 2001 From: Lucio Maranta Date: Mon, 18 Jun 2018 17:17:14 +0200 Subject: [PATCH] Added maintenance attachments API --- .../Controllers/MaintenancesController.cs | 48 ++++++ Step.Database/DatabaseContext.cs | 1 + ...201806180938301_InitMigration.Designer.cs} | 2 +- ...on.cs => 201806180938301_InitMigration.cs} | 19 ++- ...esx => 201806180938301_InitMigration.resx} | 2 +- Step.Database/Step.Database.csproj | 10 +- Step.Model/Constants.cs | 4 +- .../DTOMaintenanceNoteModel.cs | 3 +- .../DatabaseModels/MaintenanceFileModel.cs | 27 ++++ .../DatabaseModels/MaintenanceNoteModel.cs | 2 +- Step.Model/Step.Model.csproj | 1 + Step/Controllers/SignalR/NcHub.cs | 6 +- .../WebApi/MaintenanceController.cs | 145 ++++++++++++++++-- 13 files changed, 240 insertions(+), 30 deletions(-) rename Step.Database/Migrations/{201806141227365_InitMigration.Designer.cs => 201806180938301_InitMigration.Designer.cs} (92%) rename Step.Database/Migrations/{201806141227365_InitMigration.cs => 201806180938301_InitMigration.cs} (89%) rename Step.Database/Migrations/{201806141227365_InitMigration.resx => 201806180938301_InitMigration.resx} (52%) create mode 100644 Step.Model/DatabaseModels/MaintenanceFileModel.cs diff --git a/Step.Database/Controllers/MaintenancesController.cs b/Step.Database/Controllers/MaintenancesController.cs index ac6a7fb3..1b0751ef 100644 --- a/Step.Database/Controllers/MaintenancesController.cs +++ b/Step.Database/Controllers/MaintenancesController.cs @@ -267,6 +267,54 @@ namespace Step.Database.Controllers dbCtx.SaveChanges(); } + public List FindAttachmentByMaintenance(int maintenanceId) + { + return dbCtx + .MaintenanceFiles + .Where(x => x.MaintenanceId == maintenanceId) + .ToList(); + } + + public MaintenanceFileModel FindAttachmentById(int attachmentId) + { + return dbCtx + .MaintenanceFiles + .Where(x => x.AttachmentId == attachmentId) + .FirstOrDefault(); + } + + public MaintenanceFileModel AddAttachment(string fileName, int maintenanceId) + { + MaintenanceFileModel file = new MaintenanceFileModel() + { + FileName = fileName, + MaintenanceId = maintenanceId + }; + + dbCtx.MaintenanceFiles.Add(file); + + dbCtx.SaveChanges(); + + return file; + } + + public void DeleteAttachment(int attachmentId) + { + MaintenanceFileModel file = dbCtx.MaintenanceFiles.Where(x => x.AttachmentId == attachmentId).FirstOrDefault(); + if (file != null) + { + dbCtx.MaintenanceFiles.Remove(file); + + dbCtx.SaveChanges(); + } + } + + public void DeleteAttachment(MaintenanceFileModel attachment) + { + dbCtx.MaintenanceFiles.Remove(attachment); + + dbCtx.SaveChanges(); + } #endregion } } \ No newline at end of file diff --git a/Step.Database/DatabaseContext.cs b/Step.Database/DatabaseContext.cs index 52129988..dffdb045 100644 --- a/Step.Database/DatabaseContext.cs +++ b/Step.Database/DatabaseContext.cs @@ -26,6 +26,7 @@ namespace Step.Database public DbSet Maintenances { get; set; } public DbSet PerformedMaintenances { get; set; } public DbSet MaintenancesNotes { get; set; } + public DbSet MaintenanceFiles { get; set; } // Create migration string public static string CONNECTION_STRING = "Server = " + "localhost" + "; Database=" + DATABASE_NAME +";Uid="+ DATABASE_USER +";Pwd="+ DATABASE_PWD +";"; diff --git a/Step.Database/Migrations/201806141227365_InitMigration.Designer.cs b/Step.Database/Migrations/201806180938301_InitMigration.Designer.cs similarity index 92% rename from Step.Database/Migrations/201806141227365_InitMigration.Designer.cs rename to Step.Database/Migrations/201806180938301_InitMigration.Designer.cs index 093e50f1..0561631c 100644 --- a/Step.Database/Migrations/201806141227365_InitMigration.Designer.cs +++ b/Step.Database/Migrations/201806180938301_InitMigration.Designer.cs @@ -13,7 +13,7 @@ namespace Step.Database.Migrations string IMigrationMetadata.Id { - get { return "201806141227365_InitMigration"; } + get { return "201806180938301_InitMigration"; } } string IMigrationMetadata.Source diff --git a/Step.Database/Migrations/201806141227365_InitMigration.cs b/Step.Database/Migrations/201806180938301_InitMigration.cs similarity index 89% rename from Step.Database/Migrations/201806141227365_InitMigration.cs rename to Step.Database/Migrations/201806180938301_InitMigration.cs index d6954295..329ce3cc 100644 --- a/Step.Database/Migrations/201806141227365_InitMigration.cs +++ b/Step.Database/Migrations/201806180938301_InitMigration.cs @@ -71,6 +71,18 @@ namespace Step.Database.Migrations }) .PrimaryKey(t => t.id); + CreateTable( + "dbo.maintenance_file", + c => new + { + id = c.Int(nullable: false, identity: true), + file_name = c.String(unicode: false), + maintenance_id = c.Int(nullable: false), + }) + .PrimaryKey(t => t.id) + .ForeignKey("dbo.maintenance", t => t.maintenance_id, cascadeDelete: true) + .Index(t => t.maintenance_id); + CreateTable( "dbo.maintenance", c => new @@ -98,11 +110,11 @@ namespace Step.Database.Migrations id = c.Int(nullable: false, identity: true), message = c.String(unicode: false), user_id = c.Int(nullable: false), - maintenance_id = c.Int(), + maintenance_id = c.Int(nullable: false), timestamp = c.DateTime(nullable: false, precision: 0), }) .PrimaryKey(t => t.id) - .ForeignKey("dbo.maintenance", t => t.maintenance_id) + .ForeignKey("dbo.maintenance", t => t.maintenance_id, cascadeDelete: true) .ForeignKey("dbo.user", t => t.user_id, cascadeDelete: true) .Index(t => t.user_id) .Index(t => t.maintenance_id); @@ -140,6 +152,7 @@ namespace Step.Database.Migrations DropForeignKey("dbo.performed_maintenance", "maintenance", "dbo.maintenance"); DropForeignKey("dbo.maintenance_note", "user_id", "dbo.user"); DropForeignKey("dbo.maintenance_note", "maintenance_id", "dbo.maintenance"); + DropForeignKey("dbo.maintenance_file", "maintenance_id", "dbo.maintenance"); DropForeignKey("dbo.maintenance", "user_id", "dbo.user"); DropForeignKey("dbo.machine_user", "user_id", "dbo.user"); DropForeignKey("dbo.machine_user", "role_id", "dbo.role"); @@ -149,12 +162,14 @@ namespace Step.Database.Migrations DropIndex("dbo.maintenance_note", new[] { "maintenance_id" }); DropIndex("dbo.maintenance_note", new[] { "user_id" }); DropIndex("dbo.maintenance", new[] { "user_id" }); + DropIndex("dbo.maintenance_file", new[] { "maintenance_id" }); DropIndex("dbo.machine_user", new[] { "role_id" }); DropIndex("dbo.machine_user", "unique_machine_user"); DropTable("dbo.session"); DropTable("dbo.performed_maintenance"); DropTable("dbo.maintenance_note"); DropTable("dbo.maintenance"); + DropTable("dbo.maintenance_file"); DropTable("dbo.user"); DropTable("dbo.role"); DropTable("dbo.machine_user"); diff --git a/Step.Database/Migrations/201806141227365_InitMigration.resx b/Step.Database/Migrations/201806180938301_InitMigration.resx similarity index 52% rename from Step.Database/Migrations/201806141227365_InitMigration.resx rename to Step.Database/Migrations/201806180938301_InitMigration.resx index 6e0f7d04..0d26c46d 100644 --- a/Step.Database/Migrations/201806141227365_InitMigration.resx +++ b/Step.Database/Migrations/201806180938301_InitMigration.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 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 dbo diff --git a/Step.Database/Step.Database.csproj b/Step.Database/Step.Database.csproj index 72bcd6fd..c8f69adb 100644 --- a/Step.Database/Step.Database.csproj +++ b/Step.Database/Step.Database.csproj @@ -77,9 +77,9 @@ - - - 201806141227365_InitMigration.cs + + + 201806180938301_InitMigration.cs @@ -115,8 +115,8 @@ - - 201806141227365_InitMigration.cs + + 201806180938301_InitMigration.cs diff --git a/Step.Model/Constants.cs b/Step.Model/Constants.cs index 5de97765..59ba192d 100644 --- a/Step.Model/Constants.cs +++ b/Step.Model/Constants.cs @@ -100,7 +100,9 @@ namespace Step.Model // Filenames - // Config File Names + public const string MAINTENANCE_ATTACHMENT_PATH = "C:\\CMS\\STEP\\attachment\\"; + + // Config File Names public static readonly string BASE_PATH = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public const string CONFIG_DIRECTORY = "Config\\"; public const string SERVER_CONFIG_SCHEMA_PATH = CONFIG_DIRECTORY + "serverConfigValidator.xsd"; diff --git a/Step.Model/DTOModels/MaintenanceModels/DTOMaintenanceNoteModel.cs b/Step.Model/DTOModels/MaintenanceModels/DTOMaintenanceNoteModel.cs index 48d81172..4573a74e 100644 --- a/Step.Model/DTOModels/MaintenanceModels/DTOMaintenanceNoteModel.cs +++ b/Step.Model/DTOModels/MaintenanceModels/DTOMaintenanceNoteModel.cs @@ -21,7 +21,6 @@ namespace Step.Model.DTOModels.MaintenanceModels public DateTime DateTime { get; set; } public DTOMessageUserModel User { get; set; } - public static explicit operator DTOMaintenanceNoteModel(MaintenanceNoteModel note) { @@ -35,4 +34,4 @@ namespace Step.Model.DTOModels.MaintenanceModels }; } } -} +} \ No newline at end of file diff --git a/Step.Model/DatabaseModels/MaintenanceFileModel.cs b/Step.Model/DatabaseModels/MaintenanceFileModel.cs new file mode 100644 index 00000000..cdefa067 --- /dev/null +++ b/Step.Model/DatabaseModels/MaintenanceFileModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Step.Model.DatabaseModels +{ + [Table("maintenance_file")] + public class MaintenanceFileModel + { + [Key] + [Column("id")] + public int AttachmentId { get; set; } + + [Column("file_name")] + public string FileName { get; set; } + + [Column("maintenance_id")] + public int MaintenanceId { get; set; } + + [ForeignKey("MaintenanceId")] + public MaintenanceModel Maintenance { get; set; } + } +} diff --git a/Step.Model/DatabaseModels/MaintenanceNoteModel.cs b/Step.Model/DatabaseModels/MaintenanceNoteModel.cs index 55c035bf..969c4b47 100644 --- a/Step.Model/DatabaseModels/MaintenanceNoteModel.cs +++ b/Step.Model/DatabaseModels/MaintenanceNoteModel.cs @@ -26,7 +26,7 @@ namespace Step.Model.DatabaseModels public UserModel User { get; set; } [Column("maintenance_id")] - public int? MaintenanceId { get; set; } + public int MaintenanceId { get; set; } [ForeignKey("MaintenanceId")] public MaintenanceModel Maintenance { get; set; } diff --git a/Step.Model/Step.Model.csproj b/Step.Model/Step.Model.csproj index acd0db73..456e8864 100644 --- a/Step.Model/Step.Model.csproj +++ b/Step.Model/Step.Model.csproj @@ -72,6 +72,7 @@ + diff --git a/Step/Controllers/SignalR/NcHub.cs b/Step/Controllers/SignalR/NcHub.cs index da07c31f..6f8d3cd4 100644 --- a/Step/Controllers/SignalR/NcHub.cs +++ b/Step/Controllers/SignalR/NcHub.cs @@ -72,7 +72,7 @@ namespace Step.Controllers.SignalR // Call the library functions libraryError = ncHandler.RefreshAllAlarms(); } - MessageServices.Current.Publish(SHOW_MSG_UI, null, "Refresh All Alarms."); + // MessageServices.Current.Publish(SHOW_MSG_UI, null, "Refresh All Alarms."); } [SignalRAuthorize(FunctionAccess = ALARM_CMD, Action = ACTIONS.WRITE)] @@ -87,7 +87,7 @@ namespace Step.Controllers.SignalR throw new HubException(libraryError.localizationKey); } - MessageServices.Current.Publish(SHOW_MSG_UI, null, "Refresh Single Alarm. ID: " + id); + // MessageServices.Current.Publish(SHOW_MSG_UI, null, "Refresh Single Alarm. ID: " + id); } [SignalRAuthorize(FunctionAccess = ALARM_CMD, Action = ACTIONS.WRITE)] @@ -102,7 +102,7 @@ namespace Step.Controllers.SignalR throw new HubException(libraryError.localizationKey); } - MessageServices.Current.Publish(SHOW_MSG_UI, null, "Recovery Alarm. ID: " + id); + // MessageServices.Current.Publish(SHOW_MSG_UI, null, "Recovery Alarm. ID: " + id); } [SignalRAuthorize(FunctionAccess = NC_SOFTKEY, Action = ACTIONS.WRITE)] diff --git a/Step/Controllers/WebApi/MaintenanceController.cs b/Step/Controllers/WebApi/MaintenanceController.cs index dc76f940..c81a6117 100644 --- a/Step/Controllers/WebApi/MaintenanceController.cs +++ b/Step/Controllers/WebApi/MaintenanceController.cs @@ -5,12 +5,19 @@ using Step.NC; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.IO; using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using System.Web; using System.Web.Http; using static CMS_CORE_Library.DataStructures; -using static Step.Model.Constants; using static Step.Config.ServerConfig; +using static Step.Model.Constants; namespace Step.Controllers.WebApi { @@ -18,7 +25,6 @@ namespace Step.Controllers.WebApi public class MaintenanceController : ApiController { [Route("maintenances"), HttpGet] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult GetMaintenances() { @@ -40,7 +46,6 @@ namespace Step.Controllers.WebApi } [Route("maintenance"), HttpPost] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult AddMaintenance([Required]DTONewMaintenanceModel newMaint) { @@ -52,7 +57,7 @@ namespace Step.Controllers.WebApi var userId = identity.Claims.Where(c => c.Type == USER_ID_KEY).FirstOrDefault(); if (userId == null) return Unauthorized(); - + using (MaintenancesController maintenancesController = new MaintenancesController()) { MaintenanceModel dbMaint = maintenancesController.Create(newMaint, Convert.ToInt32(userId.Value)); @@ -63,14 +68,13 @@ namespace Step.Controllers.WebApi CmsError cmsError = ncHandler.GetMaintenances(out List maintenances, Convert.ToInt32(userId.Value)); if (cmsError.IsError()) return BadRequest(cmsError.localizationKey); - + return Ok(maintenances.Where(x => x.Id == dbMaint.MaintenanceId).FirstOrDefault()); } } } [Route("maintenance/{maintenanceId:int}"), HttpPut] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult AddMaintenance(int maintenanceId, [Required]DTOUpdateMaintenanceModel newMaint) { @@ -115,9 +119,7 @@ namespace Step.Controllers.WebApi } } - [Route("maintenance/{maintenanceId:int}"), HttpDelete] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult DeleteMaintenance(int maintenanceId) { @@ -155,7 +157,6 @@ namespace Step.Controllers.WebApi } [Route("maintenance/{maintenanceId:int}/note"), HttpGet] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult GetMaintenanceNotes(int maintenanceId) { @@ -177,14 +178,12 @@ namespace Step.Controllers.WebApi } [Route("maintenance/{maintenanceId:int}/note"), HttpPost] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult AddMaintenanceNote(int maintenanceId, DTONewMaintenanceNoteModel note) { if (!ModelState.IsValid) return BadRequest(ModelState); - var identity = User.Identity as ClaimsIdentity; // Find user id from the bearer token var userId = identity.Claims.Where(c => c.Type == USER_ID_KEY).FirstOrDefault(); @@ -206,13 +205,12 @@ namespace Step.Controllers.WebApi } [Route("maintenance/{maintenanceId:int}/note/{noteId:int}"), HttpPut] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult EditMaintenanceNote(int noteId, DTONewMaintenanceNoteModel newNote) { if (!ModelState.IsValid) return BadRequest(ModelState); - + var identity = User.Identity as ClaimsIdentity; // Find user id from the bearer token var userId = identity.Claims.Where(c => c.Type == USER_ID_KEY).FirstOrDefault(); @@ -238,7 +236,6 @@ namespace Step.Controllers.WebApi } [Route("maintenance/{maintenanceId:int}/note/{noteId:int}"), HttpDelete] - [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.USER_FUNCTIONS, Action = ACTIONS.WRITE)] public IHttpActionResult DeleteMaintenanceNote(int noteId) { @@ -268,5 +265,125 @@ namespace Step.Controllers.WebApi return Ok(); } } + + [Route("maintenance/{maintenanceId:int}/attachment"), HttpPost] + public async Task AddAttachment(int maintenanceId) + { + // Check whether the POST operation is MultiPart? + if (!Request.Content.IsMimeMultipartContent()) + throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); + + // Create CustomMultipartFormDataStreamProvider + CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(MAINTENANCE_ATTACHMENT_PATH); + List files = new List(); + + // Read all contents of multipart message into CustomMultipartFormDataStreamProvider. + await Request.Content.ReadAsMultipartAsync(provider); + + using (MaintenancesController maintenancesController = new MaintenancesController()) + { + foreach (MultipartFileData file in provider.FileData) + { + var fileName = Path.GetFileName(file.LocalFileName); + if (File.Exists(MAINTENANCE_ATTACHMENT_PATH + fileName)) + return BadRequest("file_already_exists"); + + files.Add(fileName); + maintenancesController.AddAttachment(fileName, maintenanceId); + } + } + + // Send OK Response along with saved file names to the client. + return Ok(); + } + + [Route("maintenance/{maintenanceId:int}/attachments"), HttpGet] + public IHttpActionResult GetAttachments(int maintenanceId) + { + using (MaintenancesController maintenancesController = new MaintenancesController()) + { + return Ok(maintenancesController.FindAttachmentByMaintenance(maintenanceId)); + } + } + + [Route("attachment/{attachmentId:int}"), HttpGet] + public IHttpActionResult GetAttachment(int attachmentId) + { + using (MaintenancesController maintenancesController = new MaintenancesController()) + { + // Get single file + MaintenanceFileModel attachment = maintenancesController.FindAttachmentById(attachmentId); + // Check if exist in db or physically + if (attachment == null) + return NotFound(); + if(!File.Exists(MAINTENANCE_ATTACHMENT_PATH + attachment.FileName)) + return NotFound(); + + return new FileResult(MAINTENANCE_ATTACHMENT_PATH + attachment.FileName); + } + } + + [Route("attachment/{attachmentId:int}"), HttpDelete] + public IHttpActionResult DeleteAttachment(int attachmentId) + { + using (MaintenancesController maintenancesController = new MaintenancesController()) + { + // Get single file + MaintenanceFileModel attachment = maintenancesController.FindAttachmentById(attachmentId); + // Check if exist in db or physically + if (attachment == null) + return NotFound(); + + maintenancesController.DeleteAttachment(attachment); + + if (File.Exists(MAINTENANCE_ATTACHMENT_PATH + attachment.FileName)) + File.Delete(MAINTENANCE_ATTACHMENT_PATH + attachment.FileName); + + return Ok(); + } + } + } + + + public class FileResult : IHttpActionResult + { + private readonly string filePath; + private readonly string contentType; + + public FileResult(string filePath, string contentType = null) + { + this.filePath = filePath; + this.contentType = contentType; + } + + public Task ExecuteAsync(CancellationToken cancellationToken) + { + return Task.Run(() => + { + // Create response + var response = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StreamContent(File.OpenRead(filePath)) // Set file + }; + // Set header content type + var contentType = this.contentType ?? MimeMapping.GetMimeMapping(Path.GetExtension(filePath)); + response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType); + + return response; + }, cancellationToken); + } + } + + // Override MultipartFormDataStreamProvider to override the GetLocalFileName + public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider + { + public CustomMultipartFormDataStreamProvider(string path) : base(path) + { + } + + public override string GetLocalFileName(HttpContentHeaders headers) + { + return headers.ContentDisposition.FileName.Replace("\"", string.Empty); + } } } \ No newline at end of file