PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/WP7.1/BabelCam/C#/BabelCam.Web/Services/SharedAccessSignatureService.cs

#
C# | 181 lines | 136 code | 25 blank | 20 comment | 10 complexity | 0a11773867fa074d32634960ed64d6ee MD5 | raw file
  1. // ----------------------------------------------------------------------------------
  2. // Microsoft Developer & Platform Evangelism
  3. //
  4. // Copyright (c) Microsoft Corporation. All rights reserved.
  5. //
  6. // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  7. // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
  8. // OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  9. // ----------------------------------------------------------------------------------
  10. // The example companies, organizations, products, domain names,
  11. // e-mail addresses, logos, people, places, and events depicted
  12. // herein are fictitious. No association with any real company,
  13. // organization, product, domain name, email address, logo, person,
  14. // places, or events is intended or should be inferred.
  15. // ----------------------------------------------------------------------------------
  16. namespace Microsoft.Samples.BabelCam.Web.Services
  17. {
  18. using System;
  19. using System.Globalization;
  20. using System.Linq;
  21. using System.Net;
  22. using System.ServiceModel;
  23. using System.ServiceModel.Activation;
  24. using System.ServiceModel.Web;
  25. using System.Web;
  26. using System.Web.Security;
  27. using Microsoft.Samples.BabelCam.Infrastructure.Helpers;
  28. using Microsoft.Samples.BabelCam.Web.Helpers;
  29. using Microsoft.Samples.BabelCam.Web.UserAccountWrappers;
  30. using Microsoft.WindowsAzure;
  31. using Microsoft.WindowsAzure.StorageClient;
  32. [ServiceBehavior(IncludeExceptionDetailInFaults = false)]
  33. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
  34. public class SharedAccessSignatureService : ISharedAccessSignatureService
  35. {
  36. private const SharedAccessPermissions ContainerSharedAccessPermissions = SharedAccessPermissions.Write | SharedAccessPermissions.Delete | SharedAccessPermissions.List;
  37. private readonly CloudBlobClient cloudBlobClient;
  38. private readonly WebOperationContext webOperationContext;
  39. public SharedAccessSignatureService()
  40. : this(null, WebOperationContext.Current)
  41. {
  42. }
  43. [CLSCompliant(false)]
  44. public SharedAccessSignatureService(CloudBlobClient cloudBlobClient, WebOperationContext webOperationContext)
  45. {
  46. if ((cloudBlobClient == null) && (GetStorageAccountFromConfigurationSetting() == null))
  47. {
  48. throw new ArgumentNullException("cloudBlobClient", "The Cloud Blob Client cannot be null if no configuration is loaded.");
  49. }
  50. this.cloudBlobClient = cloudBlobClient ?? GetStorageAccountFromConfigurationSetting().CreateCloudBlobClient();
  51. this.webOperationContext = webOperationContext;
  52. }
  53. private string UserId
  54. {
  55. get
  56. {
  57. var identity = HttpContext.Current.User.Identity as Microsoft.IdentityModel.Claims.IClaimsIdentity;
  58. return identity.Claims.Single(c => c.ClaimType == Microsoft.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
  59. }
  60. }
  61. public Uri GetContainerSharedAccessSignature(string containerName)
  62. {
  63. // Authenticate.
  64. // TODO: Authorize (user and container access).
  65. var userId = this.UserId;
  66. try
  67. {
  68. var container = this.GetCloudBlobContainer(containerName);
  69. var containerSASExperiationTime = int.Parse(ConfigReader.GetConfigValue("ContainerSASExperiationTime"), NumberStyles.Integer, CultureInfo.InvariantCulture);
  70. var sas = container.GetSharedAccessSignature(new SharedAccessPolicy()
  71. {
  72. Permissions = ContainerSharedAccessPermissions,
  73. SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromMinutes(containerSASExperiationTime)
  74. });
  75. if (this.webOperationContext != null)
  76. {
  77. this.webOperationContext.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
  78. }
  79. var uriBuilder = new UriBuilder(container.Uri) { Query = sas.TrimStart('?') };
  80. return uriBuilder.Uri;
  81. }
  82. catch (Exception exception)
  83. {
  84. throw new WebFaultException<string>(exception.Message, HttpStatusCode.InternalServerError);
  85. }
  86. }
  87. public Models.CloudBlobCollection GetBlobsSharedAccessSignatures(string containerName, string blobPrefix, bool useFlatBlobListing)
  88. {
  89. // Authenticate.
  90. // TODO: Authorize (user and container access).
  91. var userId = this.UserId;
  92. if (!string.IsNullOrEmpty(blobPrefix))
  93. {
  94. blobPrefix = blobPrefix.TrimStart('/', '\\').Replace('\\', '/');
  95. }
  96. try
  97. {
  98. SetReadOnlySharedAccessPolicy(this.GetCloudBlobContainer(containerName));
  99. var prefix = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", containerName, blobPrefix);
  100. var blobs = this.cloudBlobClient.ListBlobsWithPrefix(prefix, new BlobRequestOptions { UseFlatBlobListing = useFlatBlobListing });
  101. var result = new Models.CloudBlobCollection
  102. {
  103. Blobs = blobs.Where(b => b is CloudBlob)
  104. .Select(b => b.ToModel(containerName, this.cloudBlobClient.Credentials.AccountName))
  105. .ToArray()
  106. };
  107. if (this.webOperationContext != null)
  108. {
  109. this.webOperationContext.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
  110. }
  111. return result;
  112. }
  113. catch (Exception exception)
  114. {
  115. throw new WebFaultException<string>(exception.Message, HttpStatusCode.InternalServerError);
  116. }
  117. }
  118. private static void SetReadOnlySharedAccessPolicy(CloudBlobContainer container)
  119. {
  120. var blobSASExperiationTime = int.Parse(ConfigReader.GetConfigValue("BlobSASExperiationTime"), NumberStyles.Integer, CultureInfo.InvariantCulture);
  121. var permissions = container.GetPermissions();
  122. var options = new BlobRequestOptions
  123. {
  124. // Fail if someone else has already changed the container before we do.
  125. AccessCondition = AccessCondition.IfMatch(container.Properties.ETag)
  126. };
  127. var sharedAccessPolicy = new SharedAccessPolicy
  128. {
  129. Permissions = SharedAccessPermissions.Read,
  130. SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromDays(blobSASExperiationTime)
  131. };
  132. permissions.SharedAccessPolicies.Remove("readonly");
  133. permissions.SharedAccessPolicies.Add("readonly", sharedAccessPolicy);
  134. container.SetPermissions(permissions, options);
  135. }
  136. private static CloudStorageAccount GetStorageAccountFromConfigurationSetting()
  137. {
  138. CloudStorageAccount account = null;
  139. try
  140. {
  141. account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
  142. }
  143. catch (InvalidOperationException)
  144. {
  145. account = null;
  146. }
  147. return account;
  148. }
  149. private CloudBlobContainer GetCloudBlobContainer(string containerName)
  150. {
  151. var container = this.cloudBlobClient.GetContainerReference(containerName);
  152. container.CreateIfNotExist();
  153. return container;
  154. }
  155. }
  156. }