Merge branch 'feature/Attachments' into develop

# Conflicts:
#	Step/Controllers/WebApi/MaintenanceController.cs
This commit is contained in:
Lucio Maranta
2018-06-19 17:12:44 +02:00
13 changed files with 256 additions and 22 deletions
@@ -285,6 +285,55 @@ namespace Step.Database.Controllers
dbCtx.SaveChanges();
}
public List<MaintenanceFileModel> 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, string localFileName ,int maintenanceId)
{
MaintenanceFileModel file = new MaintenanceFileModel()
{
FileName = fileName,
LocalFileName = localFileName,
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
}
}
+1
View File
@@ -27,6 +27,7 @@ namespace Step.Database
public DbSet<MaintenanceModel> Maintenances { get; set; }
public DbSet<PerformedMaintenanceModel> PerformedMaintenances { get; set; }
public DbSet<MaintenanceNoteModel> MaintenancesNotes { get; set; }
public DbSet<MaintenanceFileModel> MaintenanceFiles { get; set; }
// Create migration string
public static string CONNECTION_STRING = "Server = " + "localhost" + "; Database=" + DATABASE_NAME +";Uid="+ DATABASE_USER +";Pwd="+ DATABASE_PWD +";";
@@ -13,7 +13,7 @@ namespace Step.Database.Migrations
string IMigrationMetadata.Id
{
get { return "201806141227365_InitMigration"; }
get { return "201806191402402_InitMigration"; }
}
string IMigrationMetadata.Source
@@ -71,6 +71,19 @@ 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),
local_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 +111,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 +153,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 +163,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");
+5 -5
View File
@@ -77,9 +77,9 @@
<Compile Include="Controllers\UsersController.cs" />
<Compile Include="Controllers\MachinesUsersController.cs" />
<Compile Include="DatabaseContext.cs" />
<Compile Include="Migrations\201806141227365_InitMigration.cs" />
<Compile Include="Migrations\201806141227365_InitMigration.Designer.cs">
<DependentUpon>201806141227365_InitMigration.cs</DependentUpon>
<Compile Include="Migrations\201806191402402_InitMigration.cs" />
<Compile Include="Migrations\201806191402402_InitMigration.Designer.cs">
<DependentUpon>201806191402402_InitMigration.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\Configuration.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -115,8 +115,8 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Migrations\201806141227365_InitMigration.resx">
<DependentUpon>201806141227365_InitMigration.cs</DependentUpon>
<EmbeddedResource Include="Migrations\201806191402402_InitMigration.resx">
<DependentUpon>201806191402402_InitMigration.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+3 -1
View File
@@ -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";
@@ -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
};
}
}
}
}
@@ -0,0 +1,30 @@
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("local_file_name")]
public string LocalFileName { get; set; }
[Column("maintenance_id")]
public int MaintenanceId { get; set; }
[ForeignKey("MaintenanceId")]
public MaintenanceModel Maintenance { get; set; }
}
}
@@ -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; }
+1
View File
@@ -72,6 +72,7 @@
<Compile Include="DatabaseModels\FunctionAccessModel.cs" />
<Compile Include="ConfigModels\MessageModel.cs" />
<Compile Include="DatabaseModels\MachineModel.cs" />
<Compile Include="DatabaseModels\MaintenanceFileModel.cs" />
<Compile Include="DatabaseModels\MaintenanceModel.cs" />
<Compile Include="DatabaseModels\PerformedMaintenanceModel.cs" />
<Compile Include="DatabaseModels\RoleModel.cs">
+3 -3
View File
@@ -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)]
@@ -1,16 +1,24 @@
using Step.Database.Controllers;
using Newtonsoft.Json;
using Step.Database.Controllers;
using Step.Model.DatabaseModels;
using Step.Model.DTOModels.MaintenanceModels;
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
{
@@ -51,7 +59,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));
@@ -62,7 +70,7 @@ namespace Step.Controllers.WebApi
CmsError cmsError = ncHandler.GetMaintenanceData(out DTOMaintenanceModel maintenance, dbMaint.MaintenanceId, Convert.ToInt32(userId.Value));
if (cmsError.IsError())
return BadRequest(cmsError.localizationKey);
return Ok(maintenance);
}
}
@@ -179,7 +187,6 @@ namespace Step.Controllers.WebApi
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,7 +213,7 @@ namespace Step.Controllers.WebApi
{
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();
@@ -261,6 +268,7 @@ namespace Step.Controllers.WebApi
return Ok();
}
}
[Route("maintenance/{maintenanceId:int}/performe"), HttpPost]
@@ -298,5 +306,133 @@ namespace Step.Controllers.WebApi
}
}
}
[Route("maintenance/{maintenanceId:int}/attachment"), HttpPost]
public async Task<IHttpActionResult> 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);
// MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(MAINTENANCE_ATTACHMENT_PATH);
List<string> files = new List<string>();
// Read all contents of multipart message into CustomMultipartFormDataStreamProvider.
var result = await Request.Content.ReadAsMultipartAsync(provider);
MaintenanceFileModel attachment = null;
using (MaintenancesController maintenancesController = new MaintenancesController())
{
// Remove foreach
foreach (MultipartFileData file in provider.FileData)
{
var fileName = Path.GetFileName(file.LocalFileName);
files.Add(fileName);
attachment = maintenancesController.AddAttachment(file.Headers.ContentDisposition.FileName.Replace("\"", string.Empty), fileName, maintenanceId);
}
}
// Send OK Response along with saved file names to the client.
return Ok(attachment);
}
[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.LocalFileName))
return NotFound();
return new FileResult(MAINTENANCE_ATTACHMENT_PATH + attachment.LocalFileName);
}
}
[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.LocalFileName))
File.Delete(MAINTENANCE_ATTACHMENT_PATH + attachment.LocalFileName);
return Ok();
}
}
}
public class FileResult : IHttpActionResult
{
private readonly string FilePath;
private readonly string ContentType;
private readonly string FileName;
public FileResult(string filePath, string contentType = null, string fileName = null)
{
FilePath = filePath;
ContentType = contentType;
FileName = fileName;
}
public Task<HttpResponseMessage> 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 = ContentType ?? MimeMapping.GetMimeMapping(Path.GetExtension(FilePath));
response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = FileName
};
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)
{
var fileName = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
return Path.GetFileNameWithoutExtension(fileName) + Guid.NewGuid() + Path.GetExtension(fileName);
}
}
}