PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Server/DeviceHive.API/Controllers/DeviceController.cs

https://github.com/oryol/devicehive-.net
C# | 220 lines | 146 code | 20 blank | 54 comment | 60 complexity | 726879453e13364a0317c8fa9853aa2c MD5 | raw file
Possible License(s): MIT
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Http;
  6. using System.Web.Http;
  7. using DeviceHive.API.Filters;
  8. using DeviceHive.API.Mapping;
  9. using DeviceHive.Data.Model;
  10. using Newtonsoft.Json.Linq;
  11. namespace DeviceHive.API.Controllers
  12. {
  13. /// <resource cref="Device" />
  14. public class DeviceController : BaseController
  15. {
  16. /// <name>list</name>
  17. /// <summary>
  18. /// Gets list of devices.
  19. /// </summary>
  20. /// <returns cref="Device">If successful, this method returns array of <see cref="Device"/> resources in the response body.</returns>
  21. [AuthorizeUser(Roles = "Administrator")]
  22. public JArray Get()
  23. {
  24. return new JArray(DataContext.Device.GetAll().Select(n => Mapper.Map(n)));
  25. }
  26. /// <name>get</name>
  27. /// <summary>
  28. /// Gets information about device.
  29. /// </summary>
  30. /// <param name="id">Device unique identifier.</param>
  31. /// <returns cref="Device">If successful, this method returns a <see cref="Device"/> resource in the response body.</returns>
  32. [AuthorizeUser]
  33. public JObject Get(Guid id)
  34. {
  35. var device = DataContext.Device.Get(id);
  36. if (device == null || !IsNetworkAccessible(device.NetworkID))
  37. ThrowHttpResponse(HttpStatusCode.NotFound, "Device not found!");
  38. return Mapper.Map(device);
  39. }
  40. public HttpResponseMessage Post(JObject json)
  41. {
  42. return HttpResponse(HttpStatusCode.MethodNotAllowed, "The method is not allowed, please use POST /device/{id} to register a device");
  43. }
  44. /// <name>register</name>
  45. /// <summary>
  46. /// <para>Registers a device.</para>
  47. /// <para>If device with specified identifier has already been registered, it gets updated in case when valid key is provided in the authorization header.</para>
  48. /// </summary>
  49. /// <param name="id">Device unique identifier.</param>
  50. /// <param name="json" cref="Device">In the request body, supply a <see cref="Device"/> resource.</param>
  51. /// <returns cref="Device">If successful, this method returns a <see cref="Device"/> resource in the response body.</returns>
  52. /// <request>
  53. /// <parameter name="network" mode="remove" />
  54. /// <parameter name="deviceClass" mode="remove" />
  55. /// <parameter name="network" type="integer, string, or object" required="true">
  56. /// <para>Network identifier, network key or <see cref="Network"/> object.</para>
  57. /// <para>If object is passed, the target network will be searched by name and automatically created if not found.</para>
  58. /// <para>In case when existing network is protected with the key, the key value must be included.</para>
  59. /// </parameter>
  60. /// <parameter name="deviceClass" type="integer or object" required="true">
  61. /// <para>Device class identifier or <see cref="DeviceClass"/> object.</para>
  62. /// <para>If object is passed, the target device class will be searched by name and version, and automatically created if not found.</para>
  63. /// </parameter>
  64. /// <parameter name="equipment" type="array" required="false" cref="Equipment">
  65. /// <para>Array of <see cref="Equipment"/> objects to be associated with the device class. If specified, all existing values will be replaced.</para>
  66. /// <para>In case when device class is permanent, this value is ignored.</para>
  67. /// </parameter>
  68. /// </request>
  69. public JObject Put(Guid id, JObject json)
  70. {
  71. // load device from repository
  72. var device = DataContext.Device.Get(id);
  73. if (device != null)
  74. {
  75. // if device exists, administrator or device authorization is required
  76. if ((RequestContext.CurrentUser == null || RequestContext.CurrentUser.Role != (int)UserRole.Administrator) &&
  77. (RequestContext.CurrentDevice == null || RequestContext.CurrentDevice.GUID != id))
  78. {
  79. ThrowHttpResponse(HttpStatusCode.Unauthorized, "Not authorized");
  80. }
  81. }
  82. else
  83. {
  84. // otherwise, create new device
  85. device = new Device(id);
  86. }
  87. // map and save the device object
  88. ResolveNetwork(json, device.ID == 0);
  89. ResolveDeviceClass(json, device.ID == 0);
  90. Mapper.Apply(device, json);
  91. Validate(device);
  92. DataContext.Device.Save(device);
  93. // replace equipments for the corresponding device class
  94. if (!device.DeviceClass.IsPermanent && json["equipment"] is JArray)
  95. {
  96. foreach (var equipment in DataContext.Equipment.GetByDeviceClass(device.DeviceClass.ID))
  97. {
  98. DataContext.Equipment.Delete(equipment.ID);
  99. }
  100. foreach (JObject jEquipment in (JArray)json["equipment"])
  101. {
  102. var equipment = GetMapper<Equipment>().Map(jEquipment);
  103. equipment.DeviceClass = device.DeviceClass;
  104. Validate(equipment);
  105. DataContext.Equipment.Save(equipment);
  106. }
  107. }
  108. return Mapper.Map(device);
  109. }
  110. /// <name>delete</name>
  111. /// <summary>
  112. /// Deletes an existing device.
  113. /// </summary>
  114. /// <param name="id">Device unique identifier.</param>
  115. [HttpNoContentResponse]
  116. [AuthorizeUser(Roles = "Administrator")]
  117. public void Delete(Guid id)
  118. {
  119. var device = DataContext.Device.Get(id);
  120. if (device != null)
  121. {
  122. DataContext.Device.Delete(device.ID);
  123. }
  124. }
  125. private IJsonMapper<Device> Mapper
  126. {
  127. get { return GetMapper<Device>(); }
  128. }
  129. private void ResolveNetwork(JObject json, bool isRequired)
  130. {
  131. var jNetwork = json.Property("network");
  132. if (isRequired && jNetwork == null)
  133. ThrowHttpResponse(HttpStatusCode.BadRequest, "Required 'network' property was not specified!");
  134. Network network = null;
  135. var verifyNetworkKey = RequestContext.CurrentUser == null;
  136. if (jNetwork != null && jNetwork.Value is JValue)
  137. {
  138. var jNetworkValue = (JValue)jNetwork.Value;
  139. if (jNetworkValue.Value is long)
  140. {
  141. // search network by ID
  142. network = DataContext.Network.Get((int)jNetworkValue);
  143. if (verifyNetworkKey && network != null && network.Key != null)
  144. ThrowHttpResponse(HttpStatusCode.Forbidden, "Could not register a device because target network is protected with a key!");
  145. }
  146. else if (jNetworkValue.Value is string)
  147. {
  148. // search network by key
  149. network = DataContext.Network.GetByKey((string)jNetworkValue);
  150. if (network == null)
  151. ThrowHttpResponse(HttpStatusCode.BadRequest, "Network with specified key was not found!");
  152. jNetwork.Value = (long)network.ID;
  153. }
  154. }
  155. else if (jNetwork != null && jNetwork.Value is JObject)
  156. {
  157. // search network by name or auto-create
  158. var jNetworkObj = (JObject)jNetwork.Value;
  159. if (jNetworkObj["name"] == null)
  160. ThrowHttpResponse(HttpStatusCode.BadRequest, "Specified 'network' object must include 'name' property!");
  161. network = DataContext.Network.Get((string)jNetworkObj["name"]);
  162. if (network == null)
  163. {
  164. // auto-create network if it does not exist
  165. network = new Network();
  166. GetMapper<Network>().Apply(network, jNetworkObj);
  167. DataContext.Network.Save(network);
  168. }
  169. // check passed network key
  170. if (verifyNetworkKey && network.Key != null && (string)jNetworkObj["key"] != network.Key)
  171. ThrowHttpResponse(HttpStatusCode.Forbidden, "Could not register a device because target network is protected with a key!");
  172. jNetwork.Value = (long)network.ID;
  173. }
  174. }
  175. private void ResolveDeviceClass(JObject json, bool isRequired)
  176. {
  177. var jDeviceClass = json.Property("deviceClass");
  178. if (isRequired && jDeviceClass == null)
  179. ThrowHttpResponse(HttpStatusCode.BadRequest, "Required 'deviceClass' property was not specified!");
  180. if (jDeviceClass != null && jDeviceClass.Value is JObject)
  181. {
  182. // search device class by name/version or auto-create
  183. var jDeviceClassObj = (JObject)jDeviceClass.Value;
  184. if (jDeviceClassObj["name"] == null)
  185. ThrowHttpResponse(HttpStatusCode.BadRequest, "Specified 'deviceClass' object must include 'name' property!");
  186. if (jDeviceClassObj["version"] == null)
  187. ThrowHttpResponse(HttpStatusCode.BadRequest, "Specified 'deviceClass' object must include 'version' property!");
  188. var deviceClass = DataContext.DeviceClass.Get((string)jDeviceClassObj["name"], (string)jDeviceClassObj["version"]);
  189. if (deviceClass == null)
  190. {
  191. // auto-create device class if it does not exist
  192. deviceClass = new DeviceClass();
  193. GetMapper<DeviceClass>().Apply(deviceClass, jDeviceClassObj);
  194. DataContext.DeviceClass.Save(deviceClass);
  195. }
  196. jDeviceClass.Value = (long)deviceClass.ID;
  197. }
  198. }
  199. }
  200. }