(feat): mongo grid fs
This commit is contained in:
parent
9c97e50c53
commit
6e37619ac0
@ -1183,6 +1183,138 @@
|
|||||||
"response": []
|
"response": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "File",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "01-Get",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json",
|
||||||
|
"type": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json",
|
||||||
|
"type": "default"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "https://localhost:7151/api/File/404c8232-9048-4519-bfba-6e78dc7005ca/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60/3930ff55-67e1-4763-be59-37407f91e0a9",
|
||||||
|
"protocol": "https",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "7151",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"File",
|
||||||
|
"404c8232-9048-4519-bfba-6e78dc7005ca",
|
||||||
|
"fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
|
||||||
|
"3930ff55-67e1-4763-be59-37407f91e0a9"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Files",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "01-Post",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"warning": "This is a duplicate header and will be overridden by the Content-Type header generated by Postman.",
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json",
|
||||||
|
"type": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json",
|
||||||
|
"type": "default"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "formdata",
|
||||||
|
"formdata": [
|
||||||
|
{
|
||||||
|
"key": "file",
|
||||||
|
"type": "file",
|
||||||
|
"src": "/C:/Users/maksym/Pictures/IMG_0146.JPG"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "https://localhost:7151/api/Files/404c8232-9048-4519-bfba-6e78dc7005ca/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
|
||||||
|
"protocol": "https",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "7151",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"Files",
|
||||||
|
"404c8232-9048-4519-bfba-6e78dc7005ca",
|
||||||
|
"fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "02-Delete",
|
||||||
|
"request": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"warning": "This is a duplicate header and will be overridden by the Content-Type header generated by Postman.",
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json",
|
||||||
|
"type": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json",
|
||||||
|
"type": "default"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "formdata",
|
||||||
|
"formdata": [
|
||||||
|
{
|
||||||
|
"key": "file",
|
||||||
|
"type": "file",
|
||||||
|
"src": "/C:/Users/maksym/Pictures/IMG_0146.JPG"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "https://localhost:7151/api/Files/404c8232-9048-4519-bfba-6e78dc7005ca/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
|
||||||
|
"protocol": "https",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "7151",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"Files",
|
||||||
|
"404c8232-9048-4519-bfba-6e78dc7005ca",
|
||||||
|
"fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using Core.Abstractions.DomainObjects;
|
using Core.Abstractions.DomainObjects;
|
||||||
using Core.DomainObjects.L10n;
|
using Core.DomainObjects.L10n;
|
||||||
|
|
||||||
namespace Core.DomainObjects {
|
namespace Core.DomainObjects.Documents {
|
||||||
public class Category : DomainObjectDocumentBase<Category> {
|
public class Category : DomainObjectDocumentBase<Category> {
|
||||||
public Guid SiteId { get; set; }
|
public Guid SiteId { get; set; }
|
||||||
public List<CategoryL10n> L10n { get; set; }
|
public List<CategoryL10n> L10n { get; set; }
|
||||||
|
|||||||
199
webapi/DataProviders/Abstractions/BucketDataProviderBase.cs
Normal file
199
webapi/DataProviders/Abstractions/BucketDataProviderBase.cs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MongoDB.Driver.GridFS;
|
||||||
|
|
||||||
|
using DomainResults.Common;
|
||||||
|
|
||||||
|
namespace DataProviders.Abstractions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public abstract class BucketDataProviderBase : DataProviderBase<BucketDataProviderBase> {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
public BucketDataProviderBase(
|
||||||
|
ILogger<BucketDataProviderBase> logger,
|
||||||
|
IMongoClient client
|
||||||
|
) : base (logger, client){ }
|
||||||
|
|
||||||
|
#region Upload
|
||||||
|
private protected (Guid?, IDomainResult) Upload(Guid siteId, Guid userId, BucketFile file, string bucketName) =>
|
||||||
|
UploadAsync(siteId, userId, file, bucketName).Result;
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> UploadAsync(Guid siteId, Guid userId, BucketFile file, string bucketName) =>
|
||||||
|
UploadAsyncCore(siteId, userId, file, bucketName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Upload many
|
||||||
|
private protected (List<Guid>?, IDomainResult) UploadMany(Guid siteId, Guid userId, List<BucketFile> files, string bucketName) =>
|
||||||
|
UploadAsync(siteId, userId, files, bucketName).Result;
|
||||||
|
|
||||||
|
private protected Task<(List<Guid>?, IDomainResult)> UploadAsync(Guid siteId, Guid userId, List<BucketFile> files, string bucketName) =>
|
||||||
|
UploadManyAsyncCore(siteId, userId, files, bucketName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Download
|
||||||
|
private protected (BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId, string bucketName) =>
|
||||||
|
DownloadAsync(siteId, userId, fileId, bucketName).Result;
|
||||||
|
|
||||||
|
private protected Task<(BucketFile?, IDomainResult)> DownloadAsync(Guid siteId, Guid userId, Guid fileId, string bucketName) =>
|
||||||
|
DownloadAsyncCore(siteId, userId, fileId, bucketName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Delete
|
||||||
|
private protected IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId, string bucketName) =>
|
||||||
|
DeleteOneAsync(siteId, userId, fileId, bucketName).Result;
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteOneAsync(Guid siteId, Guid userId, Guid fileId, string bucketName) =>
|
||||||
|
DeleteOneAsyncCore(siteId, userId, fileId, bucketName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Delete many
|
||||||
|
private protected IDomainResult DeleteMany(Guid siteId, Guid userId, string bucketName) =>
|
||||||
|
DeleteManyAsync(siteId, userId, bucketName).Result;
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteManyAsync(Guid siteId, Guid userId, string bucketName) =>
|
||||||
|
DeleteManyAsyncCore(siteId, userId, bucketName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Core methods
|
||||||
|
private GridFSBucket CreateBucket(string bucketName) => new GridFSBucket(_client.GetDatabase(_databaseName), new GridFSBucketOptions {
|
||||||
|
BucketName = bucketName,
|
||||||
|
ChunkSizeBytes = 1048576, // 1MB
|
||||||
|
WriteConcern = WriteConcern.WMajority,
|
||||||
|
ReadPreference = ReadPreference.Secondary
|
||||||
|
});
|
||||||
|
|
||||||
|
private async Task<(Guid?, IDomainResult)> UploadAsyncCore(Guid siteId, Guid userId, BucketFile file, string bucketName) {
|
||||||
|
var (list, result) = await UploadManyAsyncCore(siteId, userId, new List<BucketFile> { file }, bucketName);
|
||||||
|
|
||||||
|
if (!result.IsSuccess || list == null)
|
||||||
|
return (null, result);
|
||||||
|
|
||||||
|
return (list.First(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(List<Guid>?, IDomainResult)> UploadManyAsyncCore(Guid siteId, Guid userId, List<BucketFile> files, string bucketName) {
|
||||||
|
var options = new GridFSUploadOptions {
|
||||||
|
ChunkSizeBytes = 64512, // 63KB
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
var bucket = CreateBucket(bucketName);
|
||||||
|
|
||||||
|
var result = new List<Guid>();
|
||||||
|
foreach (var file in files) {
|
||||||
|
|
||||||
|
options.Metadata = new BsonDocument {
|
||||||
|
{ "siteId", $"{siteId}"},
|
||||||
|
{ "userId", $"{userId}"},
|
||||||
|
{ "fileName", file.Name },
|
||||||
|
{ "contentType", file.ContentType }
|
||||||
|
};
|
||||||
|
|
||||||
|
var fileId = Guid.NewGuid();
|
||||||
|
await bucket.UploadFromBytesAsync($"{fileId}", file.Bytes, options);
|
||||||
|
result.Add(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Count > 0
|
||||||
|
? IDomainResult.Success(result)
|
||||||
|
: IDomainResult.Failed<List<Guid>?>();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Bucket data provider error");
|
||||||
|
return IDomainResult.Failed<List<Guid>?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(BucketFile?, IDomainResult)> DownloadAsyncCore(Guid siteId, Guid userId, Guid fileId, string bucketName) {
|
||||||
|
try {
|
||||||
|
var filter = Builders<GridFSFileInfo>.Filter.And(
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
|
||||||
|
);
|
||||||
|
|
||||||
|
var sort = Builders<GridFSFileInfo>.Sort.Descending(x => x.UploadDateTime);
|
||||||
|
|
||||||
|
var bucket = CreateBucket(bucketName);
|
||||||
|
|
||||||
|
using var cursor = await bucket.FindAsync(filter, new GridFSFindOptions {
|
||||||
|
Limit = 1,
|
||||||
|
Sort = sort,
|
||||||
|
});
|
||||||
|
|
||||||
|
// fileInfo either has the matching file information or is null
|
||||||
|
var fileInfo = (await cursor.ToListAsync()).FirstOrDefault();
|
||||||
|
if (fileInfo == null)
|
||||||
|
return IDomainResult.NotFound<BucketFile?>();
|
||||||
|
|
||||||
|
var fileName = fileInfo.Metadata["fileName"].ToString() ?? "";
|
||||||
|
if (fileName == null)
|
||||||
|
return IDomainResult.Failed<BucketFile?>();
|
||||||
|
|
||||||
|
var contentType = fileInfo.Metadata["contentType"].ToString() ?? "";
|
||||||
|
if (contentType == null)
|
||||||
|
return IDomainResult.Failed<BucketFile?>();
|
||||||
|
|
||||||
|
var bytes = await bucket.DownloadAsBytesByNameAsync($"{fileId}", new GridFSDownloadByNameOptions {
|
||||||
|
Revision = -1
|
||||||
|
});
|
||||||
|
|
||||||
|
if(bytes == null)
|
||||||
|
return IDomainResult.Failed<BucketFile?>();
|
||||||
|
|
||||||
|
return IDomainResult.Success(new BucketFile(fileName, bytes, contentType));
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Bucket data provider error");
|
||||||
|
return IDomainResult.Failed<BucketFile?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IDomainResult> DeleteOneAsyncCore(Guid siteId, Guid userId, Guid fileId, string bucketName) =>
|
||||||
|
DeleteAsyncCore(siteId, userId, Builders<GridFSFileInfo>.Filter.And(
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
|
||||||
|
), bucketName);
|
||||||
|
|
||||||
|
private Task<IDomainResult> DeleteManyAsyncCore(Guid siteId, Guid userId, string bucketName) =>
|
||||||
|
DeleteAsyncCore(siteId, userId, Builders<GridFSFileInfo>.Filter.And(
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
||||||
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}")
|
||||||
|
), bucketName);
|
||||||
|
|
||||||
|
private async Task<IDomainResult> DeleteAsyncCore(Guid siteId, Guid userId, FilterDefinition<GridFSFileInfo> filter, string bucketName) {
|
||||||
|
try {
|
||||||
|
var bucket = CreateBucket(bucketName);
|
||||||
|
|
||||||
|
using var cursor = await bucket.FindAsync(filter);
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
foreach (var fileInfo in await cursor.ToListAsync()) {
|
||||||
|
await bucket.DeleteAsync(fileInfo.Id);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count > 0
|
||||||
|
? IDomainResult.Success()
|
||||||
|
: IDomainResult.NotFound();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Bucket data provider error");
|
||||||
|
return IDomainResult.Failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
220
webapi/DataProviders/Abstractions/CollectionDataProviderBase.cs
Normal file
220
webapi/DataProviders/Abstractions/CollectionDataProviderBase.cs
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
using DomainResults.Common;
|
||||||
|
|
||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace DataProviders.Abstractions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public abstract class CollectionDataProviderBase<T> : DataProviderBase<CollectionDataProviderBase<T>> where T : DomainObjectDocumentBase<T> {
|
||||||
|
|
||||||
|
private protected readonly IIdGenerator _idGenerator;
|
||||||
|
private protected readonly ISessionService _sessionService;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Main constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="idGenerator"></param>
|
||||||
|
/// <param name="dataProviderUtils"></param>
|
||||||
|
public CollectionDataProviderBase(
|
||||||
|
ILogger<CollectionDataProviderBase<T>> logger,
|
||||||
|
IMongoClient client,
|
||||||
|
IIdGenerator idGenerator,
|
||||||
|
ISessionService sessionService
|
||||||
|
) : base (logger, client){
|
||||||
|
_idGenerator = idGenerator;
|
||||||
|
_sessionService = sessionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Insert
|
||||||
|
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName) =>
|
||||||
|
InsertAsync(obj, collectionName).Result;
|
||||||
|
|
||||||
|
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName, Guid sessionId) =>
|
||||||
|
InsertAsync(obj, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName) =>
|
||||||
|
InsertAsyncCore(obj, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName, Guid sessionId) =>
|
||||||
|
InsertAsyncCore(obj, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region InsertMany
|
||||||
|
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName) =>
|
||||||
|
InsertManyAsync(objList, collectionName).Result;
|
||||||
|
|
||||||
|
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName, Guid sessionId) =>
|
||||||
|
InsertManyAsync(objList, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName) =>
|
||||||
|
InsertManyAsyncCore(objList, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName, Guid sessionId) =>
|
||||||
|
InsertManyAsyncCore(objList, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Get
|
||||||
|
private protected (List<T>?, IDomainResult) GetWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
GetWithPredicateCore(predicate, 0, 0, collectionName);
|
||||||
|
private protected (List<T>?, IDomainResult) GetWithPredicate(Expression<Func<T, bool>> predicate, int skip, int limit, string collectionName) =>
|
||||||
|
GetWithPredicateCore(predicate, skip, limit, collectionName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Update
|
||||||
|
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
UpdateWithPredicateAsync(obj, predicate, collectionName).Result;
|
||||||
|
|
||||||
|
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
UpdateWithPredicateAsync(obj, predicate, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Delete
|
||||||
|
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteWithPredicateAsync(predicate, collectionName).Result;
|
||||||
|
|
||||||
|
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteWithPredicateAsyncCore(predicate, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region DeleteMany
|
||||||
|
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteManyWithPredicateAsync(predicate, collectionName).Result;
|
||||||
|
|
||||||
|
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteManyWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteManyWithPredicateAsyncCore(predicate, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteManyWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Core methods
|
||||||
|
private async protected Task<(Guid?, IDomainResult)> InsertAsyncCore(T obj, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.InsertOneAsync(_sessionService.GetSession(sessionId.Value), obj);
|
||||||
|
else
|
||||||
|
collection.InsertOne(obj);
|
||||||
|
|
||||||
|
return IDomainResult.Success(obj.Id);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<Guid?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(List<Guid>?, IDomainResult)> InsertManyAsyncCore(List<T> objList, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.InsertManyAsync(_sessionService.GetSession(sessionId.Value), objList);
|
||||||
|
else
|
||||||
|
collection.InsertMany(objList);
|
||||||
|
|
||||||
|
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<List<Guid>?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (List<T>?, IDomainResult) GetWithPredicateCore(Expression<Func<T, bool>> predicate, int skip, int limit, string collectionName) {
|
||||||
|
try {
|
||||||
|
var result = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName)
|
||||||
|
.Find(predicate).Skip(skip).Limit(limit).ToList();
|
||||||
|
|
||||||
|
return result != null && result.Count > 0
|
||||||
|
? IDomainResult.Success(result)
|
||||||
|
: IDomainResult.NotFound<List<T>?>();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<List<T>?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Guid?, IDomainResult)> UpdateWithPredicateAsyncCore(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.ReplaceOneAsync(_sessionService.GetSession(sessionId.Value), predicate, obj);
|
||||||
|
else
|
||||||
|
await collection.ReplaceOneAsync(predicate, obj);
|
||||||
|
|
||||||
|
return IDomainResult.Success(obj.Id);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<Guid?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDomainResult> DeleteWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.DeleteOneAsync<T>(_sessionService.GetSession(sessionId.Value), predicate);
|
||||||
|
else
|
||||||
|
await collection.DeleteOneAsync<T>(predicate);
|
||||||
|
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDomainResult> DeleteManyWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.DeleteManyAsync(_sessionService.GetSession(sessionId.Value), predicate);
|
||||||
|
else
|
||||||
|
await collection.DeleteManyAsync(predicate);
|
||||||
|
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,264 +1,34 @@
|
|||||||
using System.Linq.Expressions;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
using MongoDB.Bson.Serialization;
|
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
using DomainResults.Common;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Core.Abstractions.DomainObjects;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace DataProviders.Abstractions {
|
namespace DataProviders.Abstractions {
|
||||||
public abstract class DataProviderBase<T> where T : DomainObjectDocumentBase<T> {
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public abstract class DataProviderBase<T> {
|
||||||
private protected const string _databaseName = "reactredux";
|
private protected const string _databaseName = "reactredux";
|
||||||
|
|
||||||
private protected readonly ILogger<DataProviderBase<T>> _logger;
|
private protected readonly ILogger<T> _logger;
|
||||||
private protected readonly IMongoClient _client;
|
private protected readonly IMongoClient _client;
|
||||||
private protected readonly IIdGenerator _idGenerator;
|
|
||||||
private protected readonly ISessionService _sessionService;
|
|
||||||
|
|
||||||
private protected List<T>? _collection;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main constructor
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger"></param>
|
/// <param name="logger"></param>
|
||||||
/// <param name="client"></param>
|
/// <param name="client"></param>
|
||||||
/// <param name="idGenerator"></param>
|
|
||||||
/// <param name="dataProviderUtils"></param>
|
|
||||||
public DataProviderBase(
|
public DataProviderBase(
|
||||||
ILogger<DataProviderBase<T>> logger,
|
ILogger<T> logger,
|
||||||
IMongoClient client,
|
IMongoClient client
|
||||||
IIdGenerator idGenerator,
|
|
||||||
ISessionService sessionService
|
|
||||||
) {
|
) {
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_client = client;
|
_client = client;
|
||||||
_idGenerator = idGenerator;
|
|
||||||
_sessionService = sessionService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Insert
|
|
||||||
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName) =>
|
|
||||||
InsertAsync(obj, collectionName).Result;
|
|
||||||
|
|
||||||
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName, Guid sessionId) =>
|
|
||||||
InsertAsync(obj, collectionName, sessionId).Result;
|
|
||||||
|
|
||||||
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName) =>
|
|
||||||
InsertAsyncCore(obj, collectionName, null);
|
|
||||||
|
|
||||||
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName, Guid sessionId) =>
|
|
||||||
InsertAsyncCore(obj, collectionName, sessionId);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region InsertMany
|
|
||||||
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName) =>
|
|
||||||
InsertManyAsync(objList, collectionName).Result;
|
|
||||||
|
|
||||||
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName, Guid sessionId) =>
|
|
||||||
InsertManyAsync(objList, collectionName, sessionId).Result;
|
|
||||||
|
|
||||||
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName) =>
|
|
||||||
InsertManyAsyncCore(objList, collectionName, null);
|
|
||||||
|
|
||||||
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName, Guid sessionId) =>
|
|
||||||
InsertManyAsyncCore(objList, collectionName, sessionId);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Get
|
|
||||||
private protected (List<T>?, IDomainResult) GetWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
GetWithPredicateCore(predicate, 0, 0, collectionName);
|
|
||||||
private protected (List<T>?, IDomainResult) GetWithPredicate(Expression<Func<T, bool>> predicate, int skip, int limit, string collectionName) =>
|
|
||||||
GetWithPredicateCore(predicate, skip, limit, collectionName);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Update
|
|
||||||
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
UpdateWithPredicateAsync(obj, predicate, collectionName).Result;
|
|
||||||
|
|
||||||
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
||||||
UpdateWithPredicateAsync(obj, predicate, collectionName, sessionId).Result;
|
|
||||||
|
|
||||||
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, null);
|
|
||||||
|
|
||||||
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
||||||
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, sessionId);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Exists
|
|
||||||
private protected (Guid?, IDomainResult) Exists(Guid id, string collectionName) {
|
|
||||||
var (_resultList, result) = GetWithPredicate(x => x.Id == id, 0, 0, collectionName);
|
|
||||||
|
|
||||||
return (result.Status != DomainOperationStatus.Failed && _resultList != null && _resultList.Count > 0
|
|
||||||
? id
|
|
||||||
:null,
|
|
||||||
result);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Delete
|
|
||||||
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
DeleteWithPredicateAsync(predicate, collectionName).Result;
|
|
||||||
|
|
||||||
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
||||||
DeleteWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
|
||||||
|
|
||||||
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
DeleteWithPredicateAsyncCore(predicate, collectionName, null);
|
|
||||||
|
|
||||||
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
||||||
DeleteWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region DeleteMany
|
|
||||||
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
DeleteManyWithPredicateAsync(predicate, collectionName).Result;
|
|
||||||
|
|
||||||
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
||||||
DeleteManyWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
|
||||||
|
|
||||||
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
||||||
DeleteManyWithPredicateAsyncCore(predicate, collectionName, null);
|
|
||||||
|
|
||||||
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
||||||
DeleteManyWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Core methods
|
|
||||||
private async protected Task<(Guid?, IDomainResult)> InsertAsyncCore(T obj, string collectionName, Guid? sessionId) {
|
|
||||||
try {
|
|
||||||
if (_collection != null) {
|
|
||||||
obj.Id = Guid.NewGuid();
|
|
||||||
_collection.Add(obj);
|
|
||||||
return IDomainResult.Success(obj.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
||||||
|
|
||||||
if (sessionId != null)
|
|
||||||
await collection.InsertOneAsync(_sessionService.GetSession(sessionId.Value), obj);
|
|
||||||
else
|
|
||||||
collection.InsertOne(obj);
|
|
||||||
|
|
||||||
return IDomainResult.Success(obj.Id);
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
_logger.LogError(ex, "Data provider error");
|
|
||||||
return IDomainResult.Failed<Guid?>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<(List<Guid>?, IDomainResult)> InsertManyAsyncCore(List<T> objList, string collectionName, Guid? sessionId) {
|
|
||||||
try {
|
|
||||||
if (_collection != null) {
|
|
||||||
_collection = _collection.Concat(objList).ToList();
|
|
||||||
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
||||||
|
|
||||||
if (sessionId != null)
|
|
||||||
await collection.InsertManyAsync(_sessionService.GetSession(sessionId.Value), objList);
|
|
||||||
else
|
|
||||||
collection.InsertMany(objList);
|
|
||||||
|
|
||||||
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
_logger.LogError(ex, "Data provider error");
|
|
||||||
return IDomainResult.Failed<List<Guid>?>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private (List<T>?, IDomainResult) GetWithPredicateCore(Expression<Func<T, bool>> predicate, int skip, int limit, string collectionName) {
|
|
||||||
try {
|
|
||||||
List<T>? result;
|
|
||||||
|
|
||||||
if (_collection != null) {
|
|
||||||
result = _collection?.AsQueryable()
|
|
||||||
.Where(predicate).ToList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName)
|
|
||||||
.Find(predicate).Skip(skip).Limit(limit).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result != null && result.Count > 0
|
|
||||||
? IDomainResult.Success(result)
|
|
||||||
: IDomainResult.NotFound<List<T>?>();
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
_logger.LogError(ex, "Data provider error");
|
|
||||||
return IDomainResult.Failed<List<T>?>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<(Guid?, IDomainResult)> UpdateWithPredicateAsyncCore(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
|
||||||
try {
|
|
||||||
if (_collection != null) {
|
|
||||||
// remove element(s) from list
|
|
||||||
foreach (var element in _collection.AsQueryable().Where(predicate))
|
|
||||||
_collection = _collection.Where(x => x.Id != element.Id).ToList();
|
|
||||||
|
|
||||||
// add updated element
|
|
||||||
_collection.Add(obj);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
||||||
|
|
||||||
if (sessionId != null)
|
|
||||||
await collection.ReplaceOneAsync(_sessionService.GetSession(sessionId.Value), predicate, obj);
|
|
||||||
else
|
|
||||||
await collection.ReplaceOneAsync(predicate, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return IDomainResult.Success(obj.Id);
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
_logger.LogError(ex, "Data provider error");
|
|
||||||
return IDomainResult.Failed<Guid?>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IDomainResult> DeleteWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
|
||||||
try {
|
|
||||||
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
||||||
|
|
||||||
if (sessionId != null)
|
|
||||||
await collection.DeleteOneAsync<T>(_sessionService.GetSession(sessionId.Value), predicate);
|
|
||||||
else
|
|
||||||
await collection.DeleteOneAsync<T>(predicate);
|
|
||||||
|
|
||||||
return IDomainResult.Success();
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
_logger.LogError(ex, "Data provider error");
|
|
||||||
return IDomainResult.Failed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IDomainResult> DeleteManyWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
|
||||||
try {
|
|
||||||
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
||||||
|
|
||||||
if (sessionId != null)
|
|
||||||
await collection.DeleteManyAsync(_sessionService.GetSession(sessionId.Value), predicate);
|
|
||||||
else
|
|
||||||
await collection.DeleteManyAsync(predicate);
|
|
||||||
|
|
||||||
return IDomainResult.Success();
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
_logger.LogError(ex, "Data provider error");
|
|
||||||
return IDomainResult.Failed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
webapi/DataProviders/BucketFile.cs
Normal file
19
webapi/DataProviders/BucketFile.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DataProviders {
|
||||||
|
public class BucketFile {
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public byte[] Bytes { get; private set; }
|
||||||
|
public string ContentType { get; private set; }
|
||||||
|
|
||||||
|
public BucketFile(string name, byte[] bytes, string contentType) {
|
||||||
|
Name = name;
|
||||||
|
Bytes = bytes;
|
||||||
|
ContentType = contentType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
122
webapi/DataProviders/Buckets/ImagesBucketDataProvider.cs
Normal file
122
webapi/DataProviders/Buckets/ImagesBucketDataProvider.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using DomainResults.Common;
|
||||||
|
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
using DataProviders.Abstractions;
|
||||||
|
|
||||||
|
namespace DataProviders.Buckets {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public interface IImagesBucketDataProvider {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(Guid?, IDomainResult) Upload(Guid siteId, Guid userId, BucketFile file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="files"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(List<Guid>?, IDomainResult) UploadMany(Guid siteId, Guid userId, List<BucketFile> files);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IDomainResult DeletMany(Guid siteId, Guid userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class ImagesBucketDataProvider : BucketDataProviderBase, IImagesBucketDataProvider {
|
||||||
|
|
||||||
|
private const string _bucketName = "images";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
public ImagesBucketDataProvider(
|
||||||
|
ILogger<BucketDataProviderBase> logger,
|
||||||
|
IMongoClient client
|
||||||
|
) : base(logger, client) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public (Guid?, IDomainResult) Upload(Guid siteId, Guid userId, BucketFile file) => Upload(siteId, userId, file, _bucketName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="files"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public (List<Guid>?, IDomainResult) UploadMany(Guid siteId, Guid userId, List<BucketFile> files) => UploadMany(siteId, userId, files, _bucketName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId) => Download(siteId, userId, fileId, _bucketName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId) => DeleteOne(siteId, userId, fileId, _bucketName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IDomainResult DeletMany(Guid siteId, Guid userId) => DeleteMany(siteId, userId, _bucketName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@ using MongoDB.Driver;
|
|||||||
using DataProviders.Abstractions;
|
using DataProviders.Abstractions;
|
||||||
using Core.DomainObjects.Documents;
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
namespace DataProviders {
|
namespace DataProviders.Collections {
|
||||||
public interface IBlogCatalogDataProvider {
|
public interface IBlogCatalogDataProvider {
|
||||||
(Guid?, IDomainResult) Insert(BlogItem blogItem);
|
(Guid?, IDomainResult) Insert(BlogItem blogItem);
|
||||||
(BlogItem?, IDomainResult) Get(Guid siteId, Guid blogId);
|
(BlogItem?, IDomainResult) Get(Guid siteId, Guid blogId);
|
||||||
@ -20,12 +20,12 @@ namespace DataProviders {
|
|||||||
IDomainResult DeleteAll(Guid siteId);
|
IDomainResult DeleteAll(Guid siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlogCatalogDataProvider : DataProviderBase<BlogItem>, IBlogCatalogDataProvider {
|
public class BlogCatalogDataProvider : CollectionDataProviderBase<BlogItem>, IBlogCatalogDataProvider {
|
||||||
|
|
||||||
private const string _collectionName = "blogcatalog";
|
private const string _collectionName = "blogcatalog";
|
||||||
|
|
||||||
public BlogCatalogDataProvider(
|
public BlogCatalogDataProvider(
|
||||||
ILogger<DataProviderBase<BlogItem>> logger,
|
ILogger<CollectionDataProviderBase<BlogItem>> logger,
|
||||||
IMongoClient client,
|
IMongoClient client,
|
||||||
IIdGenerator idGenerator,
|
IIdGenerator idGenerator,
|
||||||
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
||||||
@ -6,9 +6,9 @@ using MongoDB.Bson.Serialization;
|
|||||||
using DomainResults.Common;
|
using DomainResults.Common;
|
||||||
|
|
||||||
using DataProviders.Abstractions;
|
using DataProviders.Abstractions;
|
||||||
using Core.DomainObjects;
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
namespace DataProviders {
|
namespace DataProviders.Collections {
|
||||||
|
|
||||||
public interface ICategoryDataProvider {
|
public interface ICategoryDataProvider {
|
||||||
(Guid?, IDomainResult) Insert(Category obj);
|
(Guid?, IDomainResult) Insert(Category obj);
|
||||||
@ -21,11 +21,11 @@ namespace DataProviders {
|
|||||||
IDomainResult DeleteAll(Guid siteId);
|
IDomainResult DeleteAll(Guid siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CategoryDataProvider : DataProviderBase<Category>, ICategoryDataProvider {
|
public class CategoryDataProvider : CollectionDataProviderBase<Category>, ICategoryDataProvider {
|
||||||
|
|
||||||
private const string _collectionName = "categories";
|
private const string _collectionName = "categories";
|
||||||
public CategoryDataProvider(
|
public CategoryDataProvider(
|
||||||
ILogger<DataProviderBase<Category>> logger,
|
ILogger<CollectionDataProviderBase<Category>> logger,
|
||||||
IMongoClient client,
|
IMongoClient client,
|
||||||
IIdGenerator idGenerator,
|
IIdGenerator idGenerator,
|
||||||
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
||||||
@ -1,21 +1,24 @@
|
|||||||
using Core.DomainObjects.Documents;
|
using Microsoft.Extensions.Logging;
|
||||||
using DataProviders.Abstractions;
|
|
||||||
using DomainResults.Common;
|
using DomainResults.Common;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MongoDB.Bson.Serialization;
|
using MongoDB.Bson.Serialization;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace DataProviders {
|
using DataProviders.Abstractions;
|
||||||
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
|
namespace DataProviders.Collections {
|
||||||
|
|
||||||
public interface IContentDataProvider {
|
public interface IContentDataProvider {
|
||||||
(Content?, IDomainResult) Get(Guid siteId, string locale);
|
(Content?, IDomainResult) Get(Guid siteId, string locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ContentDataProvider : DataProviderBase<Content>, IContentDataProvider {
|
public class ContentDataProvider : CollectionDataProviderBase<Content>, IContentDataProvider {
|
||||||
|
|
||||||
private const string _collectionName = "content";
|
private const string _collectionName = "content";
|
||||||
public ContentDataProvider(
|
public ContentDataProvider(
|
||||||
ILogger<DataProviderBase<Content>> logger,
|
ILogger<CollectionDataProviderBase<Content>> logger,
|
||||||
IMongoClient client,
|
IMongoClient client,
|
||||||
IIdGenerator idGenerator,
|
IIdGenerator idGenerator,
|
||||||
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
||||||
@ -8,7 +8,7 @@ using MongoDB.Driver;
|
|||||||
using DataProviders.Abstractions;
|
using DataProviders.Abstractions;
|
||||||
using Core.DomainObjects.Documents;
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
namespace DataProviders {
|
namespace DataProviders.Collections {
|
||||||
|
|
||||||
public interface IShopCartDataProvider {
|
public interface IShopCartDataProvider {
|
||||||
(Guid?, IDomainResult) Insert(ShopCartItem obj);
|
(Guid?, IDomainResult) Insert(ShopCartItem obj);
|
||||||
@ -19,10 +19,10 @@ namespace DataProviders {
|
|||||||
IDomainResult DeleteAll(Guid siteId, Guid userId);
|
IDomainResult DeleteAll(Guid siteId, Guid userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShopCartDataProvider : DataProviderBase<ShopCartItem>, IShopCartDataProvider {
|
public class ShopCartDataProvider : CollectionDataProviderBase<ShopCartItem>, IShopCartDataProvider {
|
||||||
private const string _collectionName = "shopcart";
|
private const string _collectionName = "shopcart";
|
||||||
public ShopCartDataProvider(
|
public ShopCartDataProvider(
|
||||||
ILogger<DataProviderBase<ShopCartItem>> logger,
|
ILogger<CollectionDataProviderBase<ShopCartItem>> logger,
|
||||||
IMongoClient client,
|
IMongoClient client,
|
||||||
IIdGenerator idGenerator,
|
IIdGenerator idGenerator,
|
||||||
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
||||||
@ -8,7 +8,7 @@ using MongoDB.Driver;
|
|||||||
using Core.DomainObjects.Documents;
|
using Core.DomainObjects.Documents;
|
||||||
using DataProviders.Abstractions;
|
using DataProviders.Abstractions;
|
||||||
|
|
||||||
namespace DataProviders {
|
namespace DataProviders.Collections {
|
||||||
public interface IShopCatalogDataProvider {
|
public interface IShopCatalogDataProvider {
|
||||||
(Guid?, IDomainResult) Insert(ShopItem obj);
|
(Guid?, IDomainResult) Insert(ShopItem obj);
|
||||||
(ShopItem?, IDomainResult) Get(Guid siteId, string sku);
|
(ShopItem?, IDomainResult) Get(Guid siteId, string sku);
|
||||||
@ -20,12 +20,12 @@ namespace DataProviders {
|
|||||||
IDomainResult DeleteAll(Guid siteId);
|
IDomainResult DeleteAll(Guid siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShopCatalogDataProvider : DataProviderBase<ShopItem>, IShopCatalogDataProvider {
|
public class ShopCatalogDataProvider : CollectionDataProviderBase<ShopItem>, IShopCatalogDataProvider {
|
||||||
|
|
||||||
private const string _collectionName = "shopcatalog";
|
private const string _collectionName = "shopcatalog";
|
||||||
|
|
||||||
public ShopCatalogDataProvider(
|
public ShopCatalogDataProvider(
|
||||||
ILogger<DataProviderBase<ShopItem>> logger,
|
ILogger<CollectionDataProviderBase<ShopItem>> logger,
|
||||||
IMongoClient client,
|
IMongoClient client,
|
||||||
IIdGenerator idGenerator,
|
IIdGenerator idGenerator,
|
||||||
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
||||||
@ -37,8 +37,6 @@ namespace DataProviders.Converters {
|
|||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"No implementation to deserialize {type}");
|
throw new NotImplementedException($"No implementation to deserialize {type}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
private void Serialize(IBsonWriter writer, List<T> values) {
|
private void Serialize(IBsonWriter writer, List<T> values) {
|
||||||
if (values != null) {
|
if (values != null) {
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.17.1" />
|
<PackageReference Include="MongoDB.Driver" Version="2.17.1" />
|
||||||
|
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.17.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -4,6 +4,9 @@ using MongoDB.Driver;
|
|||||||
using MongoDB.Bson.Serialization;
|
using MongoDB.Bson.Serialization;
|
||||||
using MongoDB.Bson.Serialization.IdGenerators;
|
using MongoDB.Bson.Serialization.IdGenerators;
|
||||||
|
|
||||||
|
using DataProviders.Collections;
|
||||||
|
using DataProviders.Buckets;
|
||||||
|
|
||||||
namespace DataProviders.Extensions
|
namespace DataProviders.Extensions
|
||||||
{
|
{
|
||||||
public static class ServiceCollectionExtensions {
|
public static class ServiceCollectionExtensions {
|
||||||
@ -13,14 +16,21 @@ namespace DataProviders.Extensions
|
|||||||
services.AddSingleton<IMongoClient>(x => new MongoClient(config.ConnectionString));
|
services.AddSingleton<IMongoClient>(x => new MongoClient(config.ConnectionString));
|
||||||
services.AddSingleton<IIdGenerator, GuidGenerator>();
|
services.AddSingleton<IIdGenerator, GuidGenerator>();
|
||||||
|
|
||||||
|
Mappings.RegisterClassMap();
|
||||||
|
|
||||||
services.AddSingleton<ISessionService, SessionService>();
|
services.AddSingleton<ISessionService, SessionService>();
|
||||||
|
|
||||||
|
#region Collections
|
||||||
services.AddSingleton<IContentDataProvider, ContentDataProvider>();
|
services.AddSingleton<IContentDataProvider, ContentDataProvider>();
|
||||||
services.AddSingleton<IShopCatalogDataProvider, ShopCatalogDataProvider>();
|
services.AddSingleton<IShopCatalogDataProvider, ShopCatalogDataProvider>();
|
||||||
services.AddSingleton<IShopCartDataProvider, ShopCartDataProvider>();
|
services.AddSingleton<IShopCartDataProvider, ShopCartDataProvider>();
|
||||||
services.AddSingleton<ICategoryDataProvider, CategoryDataProvider>();
|
services.AddSingleton<ICategoryDataProvider, CategoryDataProvider>();
|
||||||
services.AddSingleton<IBlogCatalogDataProvider, BlogCatalogDataProvider>();
|
services.AddSingleton<IBlogCatalogDataProvider, BlogCatalogDataProvider>();
|
||||||
Mappings.RegisterClassMap();
|
#endregion
|
||||||
|
|
||||||
|
#region Buckets
|
||||||
|
services.AddSingleton<IImagesBucketDataProvider, ImagesBucketDataProvider>();
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
62
webapi/WeatherForecast/Controllers/FileController.cs
Normal file
62
webapi/WeatherForecast/Controllers/FileController.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using DomainResults.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using WeatherForecast.Services;
|
||||||
|
|
||||||
|
namespace WeatherForecast.Controllers {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[AllowAnonymous]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class FileController : Controller {
|
||||||
|
|
||||||
|
private readonly IFileService _fileService;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileService"></param>
|
||||||
|
public FileController(
|
||||||
|
IFileService fileService
|
||||||
|
) {
|
||||||
|
_fileService = fileService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userid"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("{siteId}/{userId}/{fileId}")]
|
||||||
|
public IActionResult Get([FromRoute] Guid siteId, [FromRoute] Guid userid, [FromRoute] Guid fileId) {
|
||||||
|
var (file, result) = _fileService.Get(siteId, userid, fileId);
|
||||||
|
|
||||||
|
if (!result.IsSuccess || file == null)
|
||||||
|
return result.ToActionResult();
|
||||||
|
|
||||||
|
var stream = new MemoryStream(file.Bytes);
|
||||||
|
return new FileStreamResult(stream, file.ContentType) {
|
||||||
|
FileDownloadName = file.Name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpDelete("{siteId}/{userId}/{fileId}")]
|
||||||
|
public IActionResult Delete([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid fileId) {
|
||||||
|
var result = _fileService.Delete(siteId, userId, fileId);
|
||||||
|
return result.ToActionResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
webapi/WeatherForecast/Controllers/FilesController.cs
Normal file
54
webapi/WeatherForecast/Controllers/FilesController.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using DomainResults.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using WeatherForecast.Services;
|
||||||
|
|
||||||
|
namespace WeatherForecast.Controllers {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[AllowAnonymous]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class FilesController : Controller {
|
||||||
|
|
||||||
|
private readonly IFilesService _filesService;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filesService"></param>
|
||||||
|
public FilesController(
|
||||||
|
IFilesService filesService
|
||||||
|
) {
|
||||||
|
_filesService = filesService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("{siteId}/{userId}")]
|
||||||
|
public IActionResult Post([FromRoute] Guid siteId, [FromRoute] Guid userId, List<IFormFile> file) {
|
||||||
|
var result = _filesService.Post(siteId, userId, file);
|
||||||
|
return result.ToActionResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
|
||||||
|
[HttpDelete("{siteId}/{userId}")]
|
||||||
|
public IActionResult Delete([FromRoute] Guid siteId, [FromRoute] Guid userId) {
|
||||||
|
var result = _filesService.Delete(siteId, userId);
|
||||||
|
return result.ToActionResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using Core.Abstractions.DomainObjects;
|
using Core.Abstractions.DomainObjects;
|
||||||
using Core.Abstractions.Models;
|
using Core.Abstractions.Models;
|
||||||
using Core.DomainObjects;
|
using Core.DomainObjects.Documents;
|
||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
using WeatherForecast.Models.Responses.L10n;
|
using WeatherForecast.Models.Responses.L10n;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core.Abstractions.Models;
|
using Core.Abstractions.Models;
|
||||||
using Core.DomainObjects;
|
using Core.DomainObjects.Documents;
|
||||||
using Core.DomainObjects.L10n;
|
using Core.DomainObjects.L10n;
|
||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
using Extensions;
|
using Extensions;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core.Abstractions.Models;
|
using Core.Abstractions.Models;
|
||||||
using Core.DomainObjects;
|
using Core.DomainObjects.Documents;
|
||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
using WeatherForecast.Models.Responses.L10n;
|
using WeatherForecast.Models.Responses.L10n;
|
||||||
|
|
||||||
|
|||||||
@ -4,11 +4,13 @@ using ExtensionMethods;
|
|||||||
using DataProviders;
|
using DataProviders;
|
||||||
|
|
||||||
using Core.DomainObjects;
|
using Core.DomainObjects;
|
||||||
|
using Core.DomainObjects.Documents;
|
||||||
using Core.DomainObjects.L10n;
|
using Core.DomainObjects.L10n;
|
||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
|
|
||||||
using WeatherForecast.Models.Requests;
|
using WeatherForecast.Models.Requests;
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ using Core.DomainObjects;
|
|||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
|
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using Core.Enumerations;
|
|||||||
|
|
||||||
using WeatherForecast.Models.Requests;
|
using WeatherForecast.Models.Requests;
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using Core.Abstractions;
|
|||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
|
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using DomainResults.Common;
|
using DomainResults.Common;
|
||||||
|
|
||||||
using DataProviders;
|
using DataProviders.Collections;
|
||||||
|
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
|
||||||
|
|||||||
87
webapi/WeatherForecast/Services/FileService.cs
Normal file
87
webapi/WeatherForecast/Services/FileService.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using DataProviders;
|
||||||
|
using DataProviders.Buckets;
|
||||||
|
using DomainResults.Common;
|
||||||
|
|
||||||
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public interface IFileService {
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(BucketFile?, IDomainResult) Get(Guid siteId, Guid userId, Guid fileId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IDomainResult Delete(Guid siteId, Guid userId, Guid fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class FileService : IFileService {
|
||||||
|
|
||||||
|
private readonly ILogger<FilesService> _logger;
|
||||||
|
private readonly IImagesBucketDataProvider _imageBucketDataProvider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="imageBucketDataProvider"></param>
|
||||||
|
public FileService(
|
||||||
|
ILogger<FilesService> logger,
|
||||||
|
IImagesBucketDataProvider imageBucketDataProvider
|
||||||
|
) {
|
||||||
|
_logger = logger;
|
||||||
|
_imageBucketDataProvider = imageBucketDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public (BucketFile?, IDomainResult) Get(Guid siteId, Guid userId, Guid fileId) {
|
||||||
|
try {
|
||||||
|
var (file, result) = _imageBucketDataProvider.Download(siteId, userId, fileId);
|
||||||
|
if (!result.IsSuccess || file == null)
|
||||||
|
return (null, result);
|
||||||
|
|
||||||
|
return IDomainResult.Success(file);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
return IDomainResult.Failed<BucketFile?>(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IDomainResult Delete(Guid siteId, Guid userId, Guid fileId) {
|
||||||
|
try {
|
||||||
|
return _imageBucketDataProvider.DeleteOne(siteId, userId, fileId);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
return IDomainResult.Failed(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
webapi/WeatherForecast/Services/FilesService.cs
Normal file
100
webapi/WeatherForecast/Services/FilesService.cs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
using DataProviders;
|
||||||
|
using DataProviders.Buckets;
|
||||||
|
using DomainResults.Common;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public interface IFilesService {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="files"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(List<Guid>?, IDomainResult) Post(Guid siteId, Guid userId, List<IFormFile> files);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IDomainResult Delete(Guid siteId, Guid userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class FilesService : IFilesService {
|
||||||
|
|
||||||
|
private readonly ILogger<FilesService> _logger;
|
||||||
|
private readonly IImagesBucketDataProvider _imageBucketDataProvider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="imageBucketDataProvider"></param>
|
||||||
|
public FilesService(
|
||||||
|
ILogger<FilesService> logger,
|
||||||
|
IImagesBucketDataProvider imageBucketDataProvider
|
||||||
|
) {
|
||||||
|
_logger = logger;
|
||||||
|
_imageBucketDataProvider = imageBucketDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process uploaded files
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="files"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public (List<Guid>?, IDomainResult) Post(Guid siteId, Guid userId, List<IFormFile> files) {
|
||||||
|
try {
|
||||||
|
// Don't rely on or trust the FileName property without validation.
|
||||||
|
|
||||||
|
var newFiles = new List<BucketFile>();
|
||||||
|
foreach (var formFile in files) {
|
||||||
|
if (formFile.Length > 0) {
|
||||||
|
using var ms = new MemoryStream();
|
||||||
|
formFile.CopyTo(ms);
|
||||||
|
|
||||||
|
newFiles.Add(new BucketFile(formFile.FileName, ms.ToArray(), formFile.ContentType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (list, result) = _imageBucketDataProvider.UploadMany(siteId, userId, newFiles);
|
||||||
|
|
||||||
|
if (!result.IsSuccess || list == null)
|
||||||
|
return IDomainResult.Failed<List<Guid>?>();
|
||||||
|
|
||||||
|
return IDomainResult.Success(list);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
return IDomainResult.Failed<List<Guid>?> (ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IDomainResult Delete(Guid siteId, Guid userId) {
|
||||||
|
try {
|
||||||
|
return _imageBucketDataProvider.DeletMany(siteId, userId);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
return IDomainResult.Failed(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using DomainResults.Common;
|
using DomainResults.Common;
|
||||||
|
|
||||||
using DataProviders;
|
using DataProviders.Collections;
|
||||||
|
|
||||||
using Core.Abstractions;
|
using Core.Abstractions;
|
||||||
using Core.Enumerations;
|
using Core.Enumerations;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using Core.Enumerations;
|
|||||||
using Core.Abstractions;
|
using Core.Abstractions;
|
||||||
|
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,8 @@ using Core.Enumerations;
|
|||||||
|
|
||||||
using WeatherForecast.Models;
|
using WeatherForecast.Models;
|
||||||
using WeatherForecast.Models.Requests;
|
using WeatherForecast.Models.Requests;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,8 @@ using Core.Enumerations;
|
|||||||
|
|
||||||
using WeatherForecast.Models;
|
using WeatherForecast.Models;
|
||||||
using WeatherForecast.Models.Responses;
|
using WeatherForecast.Models.Responses;
|
||||||
|
using DataProviders.Collections;
|
||||||
|
using Core.DomainObjects.Documents;
|
||||||
|
|
||||||
namespace WeatherForecast.Services {
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
|||||||
@ -80,6 +80,9 @@ namespace WeatherForecast {
|
|||||||
services.AddScoped<ICategoryItemService, CategoryItemService>();
|
services.AddScoped<ICategoryItemService, CategoryItemService>();
|
||||||
services.AddScoped<ICategoryItemsService, CategoryItemsService>();
|
services.AddScoped<ICategoryItemsService, CategoryItemsService>();
|
||||||
|
|
||||||
|
services.AddScoped<IFileService, FileService>();
|
||||||
|
services.AddScoped<IFilesService, FilesService>();
|
||||||
|
|
||||||
services.RegisterDataproviders(appSettings);
|
services.RegisterDataproviders(appSettings);
|
||||||
|
|
||||||
#region Swagger
|
#region Swagger
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user