-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1935 as a developper i want to use amazon s3 to store and expose devi…
…ces images (#2032) * AWS S3 store & expose device images * s3 storage image + some unit testing * #1935 code + tests * #1935 code + tests * AWS image cache control * removing usersecret
- Loading branch information
1 parent
94350a6
commit 508d916
Showing
13 changed files
with
659 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
195 changes: 195 additions & 0 deletions
195
src/AzureIoTHub.Portal.Infrastructure/Managers/AwsDeviceModelImageManager.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
// Copyright (c) CGI France. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace AzureIoTHub.Portal.Infrastructure.Managers | ||
{ | ||
using System; | ||
using System.Threading.Tasks; | ||
using Amazon; | ||
using Amazon.S3; | ||
using Amazon.S3.Model; | ||
using Azure; | ||
using AzureIoTHub.Portal.Application.Managers; | ||
using AzureIoTHub.Portal.Domain; | ||
using AzureIoTHub.Portal.Domain.Exceptions; | ||
using AzureIoTHub.Portal.Domain.Options; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
public class AwsDeviceModelImageManager : IDeviceModelImageManager | ||
{ | ||
private readonly ILogger<AwsDeviceModelImageManager> logger; | ||
private readonly ConfigHandler configHandler; | ||
private readonly IOptions<DeviceModelImageOptions> imageOptions; | ||
private readonly IAmazonS3 s3Client; | ||
|
||
public AwsDeviceModelImageManager( | ||
ILogger<AwsDeviceModelImageManager> logger, | ||
ConfigHandler configHandler, | ||
IOptions<DeviceModelImageOptions> options, | ||
IAmazonS3 s3Client) | ||
{ | ||
this.logger = logger; | ||
this.configHandler = configHandler; | ||
this.imageOptions = options; | ||
this.s3Client = s3Client; | ||
} | ||
|
||
|
||
public async Task<string> ChangeDeviceModelImageAsync(string deviceModelId, Stream stream) | ||
{ | ||
this.logger.LogInformation($"Uploading Image to AWS S3 storage"); | ||
|
||
//Portal must be able to upload images to Amazon S3 | ||
var putObjectRequest = new PutObjectRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = deviceModelId, | ||
InputStream = stream, | ||
ContentType = "image/*", | ||
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" } | ||
}; | ||
|
||
var putObjectResponse = await this.s3Client.PutObjectAsync(putObjectRequest); | ||
|
||
if (putObjectResponse.HttpStatusCode == System.Net.HttpStatusCode.OK) | ||
{ | ||
//Images on S3 are publicly accessible and read-only | ||
var putAclRequest = new PutACLRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = deviceModelId, | ||
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read | ||
}; | ||
var putACLResponse = await this.s3Client.PutACLAsync(putAclRequest); | ||
|
||
return putACLResponse.HttpStatusCode == System.Net.HttpStatusCode.OK | ||
? ComputeImageUrl(deviceModelId) | ||
: throw new InternalServerErrorException("Error by setting the image access to public and read-only"); | ||
} | ||
else | ||
{ | ||
throw new InternalServerErrorException("Error by uploading the image in S3 Storage"); | ||
} | ||
|
||
} | ||
|
||
public Uri ComputeImageUri(string deviceModelId) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
private string ComputeImageUrl(string deviceModelId) | ||
{ | ||
return $"https://{this.configHandler.AWSBucketName}.s3.{RegionEndpoint.GetBySystemName(this.configHandler.AWSRegion)}.amazonaws.com/{deviceModelId}"; | ||
} | ||
public async Task DeleteDeviceModelImageAsync(string deviceModelId) | ||
{ | ||
|
||
this.logger.LogInformation($"Deleting image from AWS S3 storage"); | ||
|
||
var deleteImageObject = new DeleteObjectRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = deviceModelId | ||
}; | ||
try | ||
{ | ||
_ = await this.s3Client.DeleteObjectAsync(deleteImageObject); | ||
|
||
} | ||
catch (RequestFailedException e) | ||
{ | ||
throw new InternalServerErrorException("Unable to delete the image from S3 storage.", e); | ||
} | ||
} | ||
|
||
public async Task<string> SetDefaultImageToModel(string deviceModelId) | ||
{ | ||
this.logger.LogInformation($"Uploading Default Image to AWS S3 storage"); | ||
|
||
//Portal must be able to upload images to Amazon S3 | ||
var putObjectRequest = new PutObjectRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = deviceModelId, | ||
FilePath = $"../Resources/{this.imageOptions.Value.DefaultImageName}", | ||
ContentType = "image/*", // image content type | ||
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" } | ||
|
||
}; | ||
|
||
var putObjectResponse = await this.s3Client.PutObjectAsync(putObjectRequest); | ||
|
||
if (putObjectResponse.HttpStatusCode == System.Net.HttpStatusCode.OK) | ||
{ | ||
//Images on S3 are publicly accessible and read-only | ||
var putAclRequest = new PutACLRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = deviceModelId, | ||
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read | ||
}; | ||
var putACLResponse = await this.s3Client.PutACLAsync(putAclRequest); | ||
|
||
return putACLResponse.HttpStatusCode == System.Net.HttpStatusCode.OK | ||
? ComputeImageUrl(deviceModelId) | ||
: throw new InternalServerErrorException("Error by setting the image access to public and read-only"); | ||
} | ||
else | ||
{ | ||
throw new InternalServerErrorException("Error by uploading the image in S3 Storage"); | ||
} | ||
|
||
} | ||
|
||
public async Task InitializeDefaultImageBlob() | ||
{ | ||
|
||
this.logger.LogInformation($"Initializing default Image to AWS S3 storage"); | ||
|
||
var putObjectRequest = new PutObjectRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = this.imageOptions.Value.DefaultImageName, | ||
FilePath = $"../Resources/{this.imageOptions.Value.DefaultImageName}", | ||
ContentType = "image/*", // image content type | ||
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" } | ||
|
||
}; | ||
|
||
var putObjectResponse = await this.s3Client.PutObjectAsync(putObjectRequest); | ||
|
||
if (putObjectResponse.HttpStatusCode == System.Net.HttpStatusCode.OK) | ||
{ | ||
//Images on S3 are publicly accessible and read-only | ||
var putAclRequest = new PutACLRequest | ||
{ | ||
BucketName = this.configHandler.AWSBucketName, | ||
Key = this.imageOptions.Value.DefaultImageName, | ||
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read | ||
}; | ||
var putACLResponse = await this.s3Client.PutACLAsync(putAclRequest); | ||
|
||
if (putACLResponse.HttpStatusCode != System.Net.HttpStatusCode.OK) | ||
{ | ||
throw new InternalServerErrorException("Error by setting the image access to public and read-only"); | ||
} | ||
} | ||
else | ||
{ | ||
throw new InternalServerErrorException("Error by uploading the image in S3 Storage"); | ||
} | ||
|
||
} | ||
|
||
public Task SyncImagesCacheControl() | ||
{ | ||
/* We don't need an implementation of | ||
this mehod for AWS because new images will processed by the method SetDefaultImageToModel | ||
*/ | ||
throw new NotImplementedException(); | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.