PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/services/Controllers/ActionController.cs

https://github.com/CTUIR/cdms-services
C# | 486 lines | 317 code | 125 blank | 44 comment | 44 complexity | 7c99e5917d8eda337ce91cd070af7658 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Threading.Tasks;
  8. using System.Web.Http;
  9. using Newtonsoft.Json;
  10. using Newtonsoft.Json.Linq;
  11. using NLog;
  12. using services.Models;
  13. using services.Models.Data;
  14. using services.Resources;
  15. namespace services.Controllers
  16. {
  17. /*
  18. * This controller provides a place for RPC-type calls.
  19. * Ken Burcham 8/9/2013
  20. */
  21. [Authorize]
  22. public class ActionController : ApiController
  23. {
  24. private static Logger logger = LogManager.GetCurrentClassLogger();
  25. [AllowAnonymous]
  26. [HttpPost]
  27. public string SystemLog(JObject jsonData)
  28. {
  29. dynamic json = jsonData;
  30. if(jsonData.GetValue("Type").ToString() == "AUDIT")
  31. {
  32. logger.Info(jsonData.GetValue("Message"));
  33. }
  34. else{
  35. logger.Error(jsonData.GetValue("Message"));
  36. }
  37. return "{Message: 'Success'}";
  38. }
  39. //returns empty list if none found...
  40. [AllowAnonymous]
  41. [HttpGet]
  42. public IEnumerable<Dataset> ProjectDatasets(int Id)
  43. {
  44. var result = new List<Dataset>();
  45. var ndb = ServicesContext.Current;
  46. var datasets = ndb.Datasets.Where(o => o.ProjectId == Id);
  47. return datasets;
  48. }
  49. [AllowAnonymous]
  50. [HttpGet]
  51. public IEnumerable<Activity> DatasetActivities(int Id)
  52. {
  53. var result = new List<Activity>();
  54. var ndb = ServicesContext.Current;
  55. var activities = ndb.Activities.Where(o => o.DatasetId == Id);
  56. return activities;
  57. }
  58. [AllowAnonymous]
  59. [HttpGet]
  60. public dynamic DatasetData(int Id)
  61. {
  62. var db = ServicesContext.Current;
  63. Activity activity = db.Activities.Find(Id);
  64. if (activity == null)
  65. throw new Exception("Configuration Error");
  66. System.Type type = db.GetTypeFor(activity.Dataset.Datastore.TablePrefix);
  67. //instantiate by name
  68. return Activator.CreateInstance(type, activity.Id);
  69. }
  70. //returns empty list if none found...
  71. [HttpGet]
  72. public List<File> ProjectFiles(int ProjectId)
  73. {
  74. var result = new List<File>();
  75. var ndb = ServicesContext.Current;
  76. Project project = ndb.Projects.Find(ProjectId);
  77. if (project == null)
  78. {
  79. throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
  80. }
  81. result = project.Files;
  82. return result;
  83. }
  84. //we will overwrite any of the keys that exist in the request
  85. [HttpPost]
  86. public HttpResponseMessage SaveUserPreference(JObject jsonData)
  87. {
  88. //string result = "{message: 'Success'}"; //TODO!
  89. //var resp = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK);
  90. //resp.Content = new System.Net.Http.StringContent(result, System.Text.Encoding.UTF8, "text/plain");
  91. var ndb = ServicesContext.Current;
  92. dynamic json = jsonData;
  93. JObject jpref = json.UserPreference;
  94. var pref = jpref.ToObject<UserPreference>();
  95. logger.Debug("Hey we have a user preference save!" + pref.Name + " = " + pref.Value);
  96. User me = AuthorizationManager.getCurrentUser();
  97. logger.Debug("Userid = " + me.Id);
  98. pref.UserId = me.Id; // you can only save preferences that are your own.
  99. //fetch user with preferences from the database -- really want a round-trip here.
  100. me = ndb.User.Find(me.Id);
  101. logger.Debug("Number of existing prefs for user = " + me.UserPreferences.Count());
  102. UserPreference match = me.UserPreferences.Where(x => x.Name == pref.Name).SingleOrDefault();
  103. if (match != null)
  104. {
  105. match.Value = pref.Value;
  106. ndb.Entry(match).State = EntityState.Modified;
  107. }
  108. else
  109. {
  110. me.UserPreferences.Add(pref);
  111. }
  112. try
  113. {
  114. ndb.SaveChanges();
  115. }
  116. catch (Exception e)
  117. {
  118. logger.Debug("Something went wrong saving the preference: " + e.Message);
  119. }
  120. return new HttpResponseMessage(HttpStatusCode.OK);
  121. }
  122. [HttpPost]
  123. public Project SaveProjectDetails(JObject jsonData)
  124. {
  125. Project project = null;
  126. var db = ServicesContext.Current;
  127. dynamic json = jsonData;
  128. JObject jproject = json.Project;
  129. JObject jlocation = json.Location;
  130. var in_project = jproject.ToObject<Project>();
  131. var in_location = jlocation.ToObject<Location>();
  132. if (in_project.Id == 0 || in_location.SdeFeatureClassId == 0 || in_location.SdeObjectId == 0)
  133. {
  134. throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
  135. }
  136. logger.Debug("incoming location objectid == " + in_location.SdeObjectId);
  137. project = db.Projects.Find(in_project.Id);
  138. if (project == null)
  139. {
  140. throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
  141. }
  142. var locations = from loc in db.Location
  143. where loc.SdeFeatureClassId == in_location.SdeFeatureClassId
  144. && loc.SdeObjectId == in_location.SdeObjectId
  145. select loc;
  146. Location location = locations.FirstOrDefault();
  147. if (location == null)
  148. {
  149. //then try to add it to the system so we can add it to our project
  150. logger.Debug("incoming Location doesn't exist, we will create it and link to it.");
  151. location = new Location();
  152. location.SdeFeatureClassId = in_location.SdeFeatureClassId;
  153. location.SdeObjectId = in_location.SdeObjectId;
  154. location.LocationTypeId = LocationType.PROJECT_TYPE;
  155. db.Location.Add(location);
  156. db.SaveChanges(); //we save the changes so that we have the id.
  157. logger.Debug("Saved a new location with id: " + location.Id);
  158. }
  159. logger.Debug(" and the locationid we are linking to will be " + location.Id);
  160. //link our project to that location if it isn't already
  161. if (project.Locations.Where(o => o.Id == location.Id).SingleOrDefault() == null)
  162. {
  163. logger.Debug("Project didn't have that location ... adding it.");
  164. project.Locations.Add(location);
  165. }
  166. else
  167. {
  168. logger.Debug("Project already has that location... why do we even bother?! (" + location.Id + ")");
  169. }
  170. User me = AuthorizationManager.getCurrentUser();
  171. //set project owner
  172. //project.OwnerId = me.Id; //this shouldn't be done here, but rather when we initially create the project.
  173. //db.Entry(project).State = EntityState.Modified; //shouldn't be necessary...
  174. //Now save metadata
  175. List<MetadataValue> metadata = new List<MetadataValue>();
  176. foreach (var jmv in json.Metadata)
  177. {
  178. var mv = jmv.ToObject<MetadataValue>();
  179. mv.UserId = me.Id;
  180. metadata.Add(mv);
  181. logger.Debug("Found new metadata: " + mv.MetadataPropertyId + " + + " + mv.Values);
  182. }
  183. //fire setMetdata which will handle persisting the metadata
  184. project.Metadata = metadata;
  185. db.SaveChanges();
  186. //need to refetch project -- otherwise it is old data
  187. //db.Entry(project).Reload();
  188. //logger.Debug("ok we saved now we are reloading...");
  189. db = ServicesContext.RestartCurrent;
  190. project = db.Projects.Where(o => o.Id == in_project.Id).SingleOrDefault();
  191. db = ServicesContext.RestartCurrent;
  192. project = db.Projects.Where(o => o.Id == in_project.Id).SingleOrDefault();
  193. db = ServicesContext.RestartCurrent;
  194. project = db.Projects.Where(o => o.Id == in_project.Id).SingleOrDefault();
  195. foreach (var mv in project.Metadata)
  196. {
  197. logger.Debug(" out --> " + mv.MetadataPropertyId + " === " + mv.Values);
  198. }
  199. //logger.Debug(JsonConvert.SerializeObject(project));
  200. return project; // JsonConvert.SerializeObject(project); //return our newly setup project.
  201. }
  202. /**
  203. * Handle uploaded files
  204. * IEnumerable<File>
  205. */
  206. public Task<HttpResponseMessage> PostFiles()
  207. {
  208. logger.Debug("starting to process incoming files.");
  209. if (!Request.Content.IsMimeMultipartContent())
  210. {
  211. throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
  212. }
  213. string root = System.Web.HttpContext.Current.Server.MapPath("~/uploads");
  214. string rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
  215. logger.Debug("saving files to location: " + root);
  216. logger.Debug(" and the root url = " + rootUrl);
  217. var provider = new MultipartFormDataStreamProvider(root);
  218. User me = AuthorizationManager.getCurrentUser();
  219. var db = ServicesContext.Current;
  220. var task = Request.Content.ReadAsMultipartAsync(provider).
  221. ContinueWith<HttpResponseMessage>(o =>
  222. {
  223. if (o.IsFaulted || o.IsCanceled)
  224. {
  225. logger.Debug("Error: " + o.Exception.Message);
  226. throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, o.Exception));
  227. }
  228. //Look up our project
  229. Int32 ProjectId = Convert.ToInt32(provider.FormData.Get("ProjectId"));
  230. logger.Debug("And we think the projectid === " + ProjectId);
  231. Project project = db.Projects.Find(ProjectId);
  232. if (project == null)
  233. throw new Exception("Project ID not found: " + ProjectId);
  234. //TODO: collaborators?
  235. //security check :: you can only edit your own projects
  236. if (project.Owner.Id != me.Id)
  237. {
  238. throw new Exception("NotAuthorized: You can only edit projects you own.");
  239. }
  240. //Now iterate through the files that just came in
  241. List<File> files = new List<File>();
  242. foreach (MultipartFileData file in provider.FileData)
  243. {
  244. logger.Debug("Filename = " + file.LocalFileName);
  245. logger.Debug("Orig = " + file.Headers.ContentDisposition.FileName);
  246. logger.Debug("Name? = " + file.Headers.ContentDisposition.Name);
  247. //var fileIndex = getFileIndex(file.Headers.ContentDisposition.Name); //"uploadedfile0" -> 0
  248. var fileIndex = "0";
  249. logger.Debug("Fileindex = " + fileIndex);
  250. var filename = file.Headers.ContentDisposition.FileName;
  251. filename = filename.Replace("\"", string.Empty);
  252. if (!String.IsNullOrEmpty(filename))
  253. {
  254. try
  255. {
  256. var newFileName = relocateProjectFile(
  257. file.LocalFileName,
  258. ProjectId,
  259. filename);
  260. var info = new System.IO.FileInfo(newFileName);
  261. File newFile = new File();
  262. newFile.Title = provider.FormData.Get("Title_" + fileIndex); //"Title_1, etc.
  263. logger.Debug("Title = " + newFile.Title);
  264. newFile.Description = provider.FormData.Get("Description_" + fileIndex); //"Description_1, etc.
  265. logger.Debug("Desc = " + newFile.Description);
  266. newFile.Name = info.Name;//.Headers.ContentDisposition.FileName;
  267. newFile.Link = rootUrl + "/services/uploads/" + ProjectId + "/" + info.Name; //file.LocalFileName;
  268. newFile.Size = (info.Length / 1024).ToString(); //file.Headers.ContentLength.ToString();
  269. newFile.FileTypeId = FileType.getFileTypeFromFilename(info);
  270. newFile.UserId = me.Id;
  271. logger.Debug(" Adding file " + newFile.Name + " at " + newFile.Link);
  272. files.Add(newFile);
  273. }
  274. catch (Exception e)
  275. {
  276. logger.Debug("Error: " + e.ToString());
  277. }
  278. }
  279. }
  280. //Add files to database for this project.
  281. if (files.Count() > 0)
  282. {
  283. logger.Debug("woot -- we have file objects to save");
  284. foreach (var file in files)
  285. {
  286. project.Files.Add(file);
  287. }
  288. db.Entry(project).State = EntityState.Modified;
  289. db.SaveChanges();
  290. }
  291. logger.Debug("Done saving files.");
  292. //TODO: actual error/success message handling
  293. string result = "{message: 'Success'}";
  294. HttpResponseMessage resp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
  295. resp.Content = new System.Net.Http.StringContent(result, System.Text.Encoding.UTF8, "text/plain");
  296. return resp;
  297. });
  298. return task;
  299. }
  300. //"uploadedfile0" -> 0
  301. public static object getFileIndex(string name)
  302. {
  303. var fileIndex = name.Replace("\"", string.Empty);
  304. fileIndex = fileIndex.Replace("uploadedfile", string.Empty);
  305. return fileIndex;
  306. }
  307. /**
  308. * takes current filename, project id and original filename and moves the file
  309. * from something like: D:\WebSites\GISInternet\services\uploads\BodyPart_c0a2f6f8-446b-42ee-88ab-2f2f3ace1e75
  310. * to D:\WebSites\GISInternet\services\uploads\3729\originalFilename.pdf
  311. * where 3729 is the projectid folder that will be created if it doesn't exist.
  312. */
  313. public static string relocateProjectFile(string current_fullfile, int ProjectId, string orig_fullfile, bool makeUnique = false)
  314. {
  315. string new_filename = current_fullfile;
  316. orig_fullfile = orig_fullfile.Replace("\"", string.Empty);
  317. if (String.IsNullOrEmpty(orig_fullfile))
  318. throw new Exception("Original filename path is not given.");
  319. logger.Debug("Incoming current: " + current_fullfile);
  320. logger.Debug("Original file: " + orig_fullfile);
  321. string directory = System.IO.Path.GetDirectoryName(current_fullfile);
  322. string orig_filename = System.IO.Path.GetFileName(orig_fullfile);
  323. //unless we want to make a UNIQUE filename (like for importing)
  324. if (makeUnique)
  325. {
  326. orig_filename = System.IO.Path.GetFileNameWithoutExtension(orig_fullfile) + "_" + System.IO.Path.GetFileNameWithoutExtension(System.IO.Path.GetRandomFileName()) + System.IO.Path.GetExtension(orig_fullfile);
  327. }
  328. string project_directory = directory + @"\" + ProjectId;
  329. logger.Debug("New target file: " + orig_filename);
  330. //first, ensure we have a projectid folder (will auto-create if necessary)
  331. logger.Debug("Creating (if necessary) project directory: " + project_directory);
  332. System.IO.Directory.CreateDirectory(project_directory);
  333. //now move the file from where it is to the project directory with the new name.
  334. new_filename = project_directory + @"\" + orig_filename;
  335. logger.Debug("Moving uploaded file to: " + new_filename);
  336. System.IO.File.Move(current_fullfile, new_filename);
  337. return new_filename;
  338. }
  339. [HttpGet]
  340. [AllowAnonymous]
  341. [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
  342. public User WhoAmI()
  343. {
  344. logger.Debug("whoami?");
  345. logger.Debug("might be --> " + System.Web.HttpContext.Current.Request.LogonUserIdentity.Name);
  346. if (User.Identity.IsAuthenticated)
  347. logger.Debug(" it says we are authenticated.");
  348. logger.Debug("Can we get our user?");
  349. User me = AuthorizationManager.getCurrentUser();
  350. if (me == null)
  351. {
  352. logger.Debug("nope");
  353. throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Forbidden));
  354. }
  355. logger.Debug("yep! you are "+me.Username);
  356. var ndb = ServicesContext.Current;
  357. me = ndb.User.Find(me.Id);
  358. return me;
  359. }
  360. }
  361. }