remove other stuff

This commit is contained in:
2022-12-05 11:26:58 +01:00
parent 6f9d6ecf53
commit adc749efac
226 changed files with 2 additions and 11000 deletions
@@ -1,24 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Abstractions;
[ApiController]
[ZeroAuthorize]
[ApiMetadataFilter]
[ApiResponseFilter]
[TypeFilter(typeof(ApiExceptionFilter))]
//[MiddlewareFilter(typeof(ApiUnhandledExceptionMiddlewareFilter))]
//[ServiceFilter(typeof(ModelStateValidationFilterAttribute))]
//[ServiceFilter(typeof(BackofficeFilterAttribute))]
public abstract class ZeroApiController : ControllerBase
{
IZeroMapper _mapper;
protected IZeroMapper Mapper => _mapper ?? (_mapper = HttpContext?.RequestServices?.GetService<IZeroMapper>());
IZeroContext _context;
protected IZeroContext ZeroContext => _context ?? (_context = HttpContext?.RequestServices?.GetService<IZeroContext>());
public ApiRequestHints Hints { get; protected set; } = new();
}
@@ -1,35 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Raven.Client.Documents.Indexes;
namespace zero.Api.Abstractions;
public abstract class ZeroApiEntityStoreController<TModel, TStore> : ZeroApiController
where TModel : ZeroEntity, new()
where TStore : IEntityStore<TModel>
{
protected TStore Store { get; set; }
protected ZeroApiEntityStoreOperations<TModel, TStore> Ops { get; set; }
public ZeroApiEntityStoreController(TStore store)
{
Store = store;
Ops = new ZeroApiEntityStoreOperations<TModel, TStore>(this, store);
}
protected Task<ActionResult<T>> EmptyModel<T>(string flavorAlias = null, Action<T> modify = null) => Ops.EmptyModel<T>(flavorAlias, modify);
protected Task<ActionResult<TModel>> EmptyModel(string flavorAlias = null, Action<TModel> modify = null) => Ops.EmptyModel(flavorAlias, modify);
protected Task<ActionResult<T>> GetModel<T>(string id, string changeVector = null) => Ops.GetModel<T>(id, changeVector);
protected Task<ActionResult<TModel>> GetModel(string id, string changeVector = null) => Ops.GetModel(id, changeVector);
protected Task<ActionResult<Paged>> GetModels<T>(ListQuery<TModel> query) => Ops.GetModels<T>(query);
protected Task<ActionResult<Paged>> GetModels(ListQuery<TModel> query) => Ops.GetModels(query);
protected Task<ActionResult<Paged>> GetModelsByIndex<T, TIndex>(ListQuery<TModel> query) where TIndex : AbstractCommonApiForIndexes, new() => Ops.GetModelsByIndex<T, TIndex>(query);
protected Task<ActionResult<Paged>> GetModelsByIndex<TIndex>(ListQuery<TModel> query) where TIndex : AbstractCommonApiForIndexes, new() => Ops.GetModelsByIndex<TIndex>(query);
protected Task<ActionResult<Result>> CreateModel<T, TEdit>(T saveModel) where T : ISupportsFlavors => Ops.CreateModel<T, TEdit>(saveModel);
protected Task<ActionResult<Result>> CreateModel(TModel saveModel) => Ops.CreateModel(saveModel);
protected Task<ActionResult<Result>> UpdateModel<T, TEdit>(string id, T updateModel, string changeToken = null) where T : ZeroIdEntity => Ops.UpdateModel<T, TEdit>(id, updateModel, changeToken);
protected Task<ActionResult<Result>> UpdateModel(string id, TModel updateModel, string changeToken = null) => Ops.UpdateModel(id, updateModel, changeToken);
protected Task<ActionResult<Result>> SortModels(string[] ids) => Ops.SortModels(ids);
protected Task<ActionResult<Result>> DeleteModel(string id) => Ops.DeleteModel(id);
}
@@ -1,255 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Raven.Client.Documents.Indexes;
namespace zero.Api.Abstractions;
public class ZeroApiEntityStoreOperations<TModel, TStore>
where TModel : ZeroEntity, new()
where TStore : IEntityStore<TModel>
{
public TStore Store { get; set; }
IZeroMapper _mapper;
protected IZeroMapper Mapper => _mapper ?? (_mapper = Controller.HttpContext?.RequestServices?.GetService<IZeroMapper>());
protected ZeroApiController Controller { get; private set; }
public ZeroApiEntityStoreOperations(ZeroApiController controller, TStore store)
{
Controller = controller;
Store = store;
Store.Config.IncludeInactive = true;
}
protected string GetActionMethod { get; set; } = "Get";
protected virtual string GetAction(TModel model)
{
return "/"; // TODO Url.Action does not work anymore,
// probably due to ZeroApiControllerModelConvention, which rewrites AttributeRouteModel
//return Url.Action(GetActionMethod, ControllerContext.ActionDescriptor.ControllerName, new { id = model.Id, changeVector = default(string) });
}
public async Task<ActionResult<T>> EmptyModel<T>(string flavorAlias = null, Action<T> modify = null)
{
TModel model = await Store.Empty(flavorAlias);
if (model == null)
{
return Controller.NotFound();
}
T result = Mapper.Map<TModel, T>(model);
modify?.Invoke(result);
return result;
}
public async Task<ActionResult<TModel>> EmptyModel(string flavorAlias = null, Action<TModel> modify = null)
{
TModel model = await Store.Empty(flavorAlias);
if (model == null)
{
return Controller.NotFound();
}
modify?.Invoke(model);
return model;
}
public async Task<ActionResult<T>> GetModel<T>(string id, string changeVector = null)
{
TModel model = await Store.Load(id, changeVector);
if (model == null)
{
return Controller.NotFound();
}
Controller.HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model);
return Mapper.Map<TModel, T>(model);
}
public async Task<ActionResult<TModel>> GetModel(string id, string changeVector = null)
{
TModel model = await Store.Load(id, changeVector);
if (model == null)
{
return Controller.NotFound();
}
Controller.HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model);
return model;
}
public async Task<ActionResult<Paged>> GetModels<T>(ListQuery<TModel> query)
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
query.SearchSelector ??= x => x.Name;
Paged<TModel> result = await Store.Load(query.Page, query.PageSize, q => q.Filter(query));
return Mapper.Map<TModel, T>(result);
}
public async Task<ActionResult<Paged>> GetModels(ListQuery<TModel> query)
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
query.SearchSelector ??= x => x.Name;
Paged<TModel> result = await Store.Load(query.Page, query.PageSize, q => q.Filter(query));
return result;
}
public async Task<ActionResult<Paged>> GetModelsByIndex<T, TIndex>(ListQuery<TModel> query) where TIndex : AbstractCommonApiForIndexes, new()
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
query.SearchSelector ??= x => x.Name;
Paged<TModel> result = await Store.Load<TIndex>(query.Page, query.PageSize, q => q.Filter(query));
return Mapper.Map<TModel, T>(result);
}
public async Task<ActionResult<Paged>> GetModelsByIndex<TIndex>(ListQuery<TModel> query) where TIndex : AbstractCommonApiForIndexes, new()
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
query.SearchSelector ??= x => x.Name;
Paged<TModel> result = await Store.Load<TIndex>(query.Page, query.PageSize, q => q.Filter(query));
return result;
}
public async Task<ActionResult<Result>> CreateModel<T, TEdit>(T saveModel) where T : ISupportsFlavors
{
TModel emptyModel = saveModel.Flavor.IsNullOrEmpty() ? await Store.Empty() : await Store.Empty(saveModel.Flavor);
TModel model = Mapper.Map(saveModel, emptyModel);
Result<TModel> result = await Store.Create(model);
bool minimalResponse = false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal;
if (result.IsSuccess)
{
Result<TEdit> mappedResult = Mapper.Map<TModel, TEdit>(result);
return Controller.Created(GetAction(model), minimalResponse ? null : mappedResult);
}
return result.WithoutModel();
}
public async Task<ActionResult<Result>> CreateModel(TModel saveModel)
{
Result<TModel> result = await Store.Create(saveModel);
bool minimalResponse = false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal;
if (result.IsSuccess)
{
return Controller.Created(GetAction(saveModel), minimalResponse ? null : saveModel);
}
return result.WithoutModel();
}
public async Task<ActionResult<Result>> UpdateModel<T, TEdit>(string id, T updateModel, string changeToken = null) where T : ZeroIdEntity
{
if (id != updateModel.Id)
{
return Controller.BadRequest(Result.Fail(nameof(id), "@errors.onupdate.noidmatch"));
}
TModel model = await Store.Load(id);
if (model == null)
{
return Controller.BadRequest(Result.Fail(nameof(id), "@errors.idnotfound"));
}
string storedChangeToken = Store.GetChangeToken(model);
if (!changeToken.IsNullOrEmpty() && storedChangeToken != changeToken)
{
return Controller.BadRequest(Result.Fail("@errors.onupdate.changetokenmismatch"));
}
Mapper.Map(updateModel, model);
Result<TModel> result = await Store.Update(model);
if (false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
// TODO add Preference-Applied header, see https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#76-standard-response-headers
return Mapper.Map<TModel, TEdit>(result);
}
public async Task<ActionResult<Result>> UpdateModel(string id, TModel updateModel, string changeToken = null)
{
if (id != updateModel.Id)
{
return Controller.BadRequest(Result.Fail(nameof(id), "@errors.onupdate.noidmatch"));
}
// TODO throws error on save: Attempted to associate a different object with id ...
// we need to map props to new object
//TModel model = await Store.Load(id);
//if (model == null)
//{
// return BadRequest(Result.Fail(nameof(id), "@errors.idnotfound"));
//}
//string storedChangeToken = Store.GetChangeToken(model);
//if (!changeToken.IsNullOrEmpty() && storedChangeToken != changeToken)
//{
// return BadRequest(Result.Fail("@errors.onupdate.changetokenmismatch"));
//}
Result<TModel> result = await Store.Update(updateModel);
if (false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
return result;
}
public async Task<ActionResult<Result>> SortModels(string[] ids)
{
return await Store.Sort(ids);
}
public async Task<ActionResult<Result>> DeleteModel(string id)
{
TModel model = await Store.Load(id);
if (model == null)
{
return Controller.NotFound();
}
Result<TModel> result = await Store.Delete(model);
return result.WithoutModel();
}
}
@@ -1,130 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Raven.Client.Documents.Indexes;
namespace zero.Api.Abstractions;
public abstract class ZeroApiTreeEntityStoreController<TModel, TStore> : ZeroApiEntityStoreController<TModel, TStore>
where TModel : ZeroEntity, ISupportsTrees, new()
where TStore : ITreeEntityStore<TModel>
{
public ZeroApiTreeEntityStoreController(TStore store) : base(store) { }
protected async Task<ActionResult<Paged>> GetChildModels<T>(string parentId, ListQuery<TModel> query)
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
Paged<TModel> result = await Store.LoadChildren(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query));
return Mapper.Map<TModel, T>(result);
}
protected async Task<ActionResult<Paged>> GetChildModels(string parentId, ListQuery<TModel> query)
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
Paged<TModel> result = await Store.LoadChildren(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query));
return result;
}
protected async Task<ActionResult<Paged>> GetChildModelsByIndex<T, TIndex>(string parentId, ListQuery<TModel> query) where TIndex : AbstractCommonApiForIndexes, new()
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
Paged<TModel> result = await Store.LoadChildren<TIndex>(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query));
return Mapper.Map<TModel, T>(result);
}
protected async Task<ActionResult<Paged>> GetChildModelsByIndex<TIndex>(string parentId, ListQuery<TModel> query) where TIndex : AbstractCommonApiForIndexes, new()
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
Paged<TModel> result = await Store.LoadChildren<TIndex>(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query));
return result;
}
protected async Task<ActionResult<Result>> MoveModel<TEdit>(string id, string newParentId)
{
return await PutOperation<TEdit>(async () => await Store.Move(id, NormalizeParentId(newParentId)));
}
protected async Task<ActionResult<Result>> MoveModel(string id, string newParentId)
{
return await PutOperation(async () => await Store.Move(id, NormalizeParentId(newParentId)));
}
protected async Task<ActionResult<Result>> CopyModel<TEdit>(string id, string newParentId)
{
return await PutOperation<TEdit>(async () => await Store.Copy(id, NormalizeParentId(newParentId)));
}
protected async Task<ActionResult<Result>> CopyModel(string id, string newParentId)
{
return await PutOperation(async () => await Store.Copy(id, NormalizeParentId(newParentId)));
}
protected async Task<ActionResult<Result>> CopyModelWithDescendants<TEdit>(string id, string newParentId)
{
return await PutOperation<TEdit>(async () => await Store.CopyWithDescendants(id, NormalizeParentId(newParentId)));
}
protected async Task<ActionResult<Result>> CopyModelWithDescendants(string id, string newParentId)
{
return await PutOperation(async () => await Store.CopyWithDescendants(id, NormalizeParentId(newParentId)));
}
protected async Task<ActionResult<Result<string[]>>> DeleteModelWithDescendants(string id)
{
TModel model = await Store.Load(id);
if (model == null)
{
return NotFound();
}
Result<string[]> result = await Store.DeleteWithDescendants(model);
return result;
}
async Task<ActionResult<Result>> PutOperation<TEdit>(Func<Task<Result<TModel>>> action)
{
Result<TModel> result = await action();
if (false && Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
return Mapper.Map<TModel, TEdit>(result);
}
async Task<ActionResult<Result>> PutOperation(Func<Task<Result<TModel>>> action)
{
Result<TModel> result = await action();
if (false && Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
return result;
}
protected string NormalizeParentId(string id)
{
return id == "root" ? null : id;
}
}
-39
View File
@@ -1,39 +0,0 @@
using Microsoft.AspNetCore.Http;
namespace zero.Api;
public class ApiApplicationResolverHandler : IBackofficeApplicationResolverHandler
{
readonly IZeroOptions options;
public ApiApplicationResolverHandler(IZeroOptions options)
{
this.options = options;
}
public bool TryResolve(HttpContext context, IEnumerable<Application> applications, ZeroUser user, out Application resolved)
{
string path = options.ZeroPath.EnsureStartsWith('/').TrimEnd('/');
if (!context.Request.Path.ToString().StartsWith(path))
{
resolved = null;
return false;
}
resolved = applications.FirstOrDefault();
return resolved != null;
//string appKey = context.Request.Path.Value.Substring(path.Length).TrimStart('/').Split('/').ElementAtOrDefault(1);
//if (appKey.HasValue())
//{
// resolved = applications.FirstOrDefault(x => x.Alias == appKey);
// return resolved != null;
//}
//resolved = null;
//return false;
}
}
-15
View File
@@ -1,15 +0,0 @@
namespace zero.Api;
public static class ApiErrorCodes
{
public static class Categories
{
public const string Server = "server";
public const string Validation = "validation";
}
public static class Server
{
public const string Exception = "server.error";
}
}
-11
View File
@@ -1,11 +0,0 @@
using Microsoft.AspNetCore.Routing;
namespace zero.Api;
public class ApiParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
return value == null ? null : Safenames.Alias(value);
}
}
-28
View File
@@ -1,28 +0,0 @@
namespace zero.Api;
public struct ApiRequestHints
{
public ApiRequestHints(ApiResponsePreference responsePreference)
{
ResponsePreference = responsePreference;
}
public ApiResponsePreference ResponsePreference { get; set; } = ApiResponsePreference.Representation;
}
/// <summary>
/// Preference for POST + PUT requests
/// see https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#75-standard-request-headers
/// </summary>
public enum ApiResponsePreference
{
/// <summary>
/// Returns a minimal repsonse for inserts and updates
/// </summary>
Minimal = 0,
/// <summary>
/// Returns status as well as model for inserts and updates
/// </summary>
Representation = 1
}
-12
View File
@@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api;
public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder UseZeroApi(this IApplicationBuilder builder)
{
return builder;
}
}
@@ -1,4 +0,0 @@
namespace zero.Api.Attributes;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ZeroSystemApiAttribute : Attribute { }
-6
View File
@@ -1,6 +0,0 @@
namespace zero.Api.Configuration;
public static class ApiConstants
{
public const string ChangeToken = "zero.api.change_vector";
}
-15
View File
@@ -1,15 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Text.Json;
namespace zero.Api;
public class ConfigureApiJsonOptions : IConfigureOptions<JsonOptions>
{
public void Configure(JsonOptions options)
{
// TODO this matches all serialization, not limited to API
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
}
}
@@ -1,13 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Applications;
public class ApplicationModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, ApplicationPermissions>();
services.AddSingleton<IMapperProfile, ApplicationMapperProfile>();
}
}
@@ -1,30 +0,0 @@
namespace zero.Api.Endpoints.Applications;
public class ApplicationPermissions : PermissionProvider
{
// TODO wrong
public const string Create = "zero.settings.country.create";
public const string Read = "zero.settings.country.read";
public const string Update = "zero.settings.country.update";
public const string Delete = "zero.settings.country.delete";
public override Task Configure(IPermissionContext context)
{
if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group))
{
group.Permissions.Add(new Permission("zero.settings.country", "@settings.application.countries.name")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
}
return Task.CompletedTask;
}
}
@@ -1,39 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Applications;
[ZeroSystemApi]
public class ApplicationsController : ZeroApiEntityStoreController<Application, IApplicationStore>
{
public ApplicationsController(IApplicationStore store) : base(store) { }
[HttpGet("empty")]
[ZeroAuthorize(ApplicationPermissions.Create)]
public virtual Task<ActionResult<Application>> Empty(string flavor = null) => EmptyModel(flavor);
[HttpGet("{id}")]
[ZeroAuthorize(ApplicationPermissions.Read)]
public virtual Task<ActionResult<Application>> Get(string id, string changeVector = null) => GetModel(id, changeVector);
[HttpGet("")]
[ZeroAuthorize(ApplicationPermissions.Read)]
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<Application> query) => GetModels<ApplicationBasic>(query);
[HttpPost("")]
[ZeroAuthorize(ApplicationPermissions.Create)]
public virtual Task<ActionResult<Result>> Create(Application saveModel) => CreateModel(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(ApplicationPermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, Application updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(ApplicationPermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
}
@@ -1,10 +0,0 @@
namespace zero.Api.Endpoints.Applications;
public class ApplicationBasic : BasicModel<Application>
{
public string FullName { get; set; }
public string ImageId { get; set; }
public Uri[] Domains { get; set; }
}
@@ -1,16 +0,0 @@
namespace zero.Api.Endpoints.Applications;
public class ApplicationEdit : DisplayModel<Application>
{
public string ImageId { get; set; }
public string IconId { get; set; }
public Uri[] Domains { get; set; } = Array.Empty<Uri>();
public string FullName { get; set; }
public string Email { get; set; }
public List<string> Features { get; set; } = new();
}
@@ -1,42 +0,0 @@
namespace zero.Api.Endpoints.Applications;
public class ApplicationMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<Application, ApplicationBasic>((source, ctx) => new(), Map);
mapper.Define<Application, ApplicationEdit>((source, ctx) => new(), Map);
mapper.Define<ApplicationSave, Application>((source, ctx) => new(), Map);
}
protected virtual void Map(Application source, ApplicationBasic target, IZeroMapperContext ctx)
{
this.MapBasicData(source, target);
target.ImageId = source.ImageId;
target.Domains = source.Domains;
target.FullName = source.FullName;
}
protected virtual void Map(Application source, ApplicationEdit target, IZeroMapperContext ctx)
{
this.MapDisplayData(source, target);
target.ImageId = source.ImageId;
target.IconId = source.IconId;
target.Domains = source.Domains;
target.FullName = source.FullName;
target.Email = source.Email;
target.Features = source.Features;
}
protected virtual void Map(ApplicationSave source, Application target, IZeroMapperContext ctx)
{
this.MapSaveData(source, target);
target.ImageId = source.ImageId;
target.IconId = source.IconId;
target.Domains = source.Domains;
target.FullName = source.FullName;
target.Email = source.Email;
target.Features = source.Features;
}
}
@@ -1,16 +0,0 @@
namespace zero.Api.Endpoints.Applications;
public class ApplicationSave : SaveModel<Application>
{
public string ImageId { get; set; }
public string IconId { get; set; }
public Uri[] Domains { get; set; } = Array.Empty<Uri>();
public string FullName { get; set; }
public string Email { get; set; }
public List<string> Features { get; set; } = new();
}
@@ -1,42 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Countries;
public class CountriesController : ZeroApiEntityStoreController<Country, ICountryStore>
{
public CountriesController(ICountryStore store) : base(store) { }
[HttpGet("empty")]
[ZeroAuthorize(CountryPermissions.Create)]
public virtual Task<ActionResult<Country>> Empty(string flavor = null) => EmptyModel(flavor);
[HttpGet("{id}")]
[ZeroAuthorize(CountryPermissions.Read)]
public virtual Task<ActionResult<Country>> Get(string id, string changeVector = null) => GetModel(id, changeVector);
[HttpGet("")]
[ZeroAuthorize(CountryPermissions.Read)]
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<Country> query)
{
query.OrderQuery = q => q.OrderByDescending(x => x.IsPreferred).ThenBy(x => x.Name);
return GetModelsByIndex<CountryBasic, zero_Api_Countries_Listing>(query);
}
[HttpPost("")]
[ZeroAuthorize(CountryPermissions.Create)]
public virtual Task<ActionResult<Result>> Create(Country saveModel) => CreateModel(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(CountryPermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, Country updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(CountryPermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
}
@@ -1,18 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Countries;
public class CountryModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, CountryPermissions>();
services.AddSingleton<IMapperProfile, CountryMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_Countries_Listing>();
});
}
}
@@ -1,29 +0,0 @@
namespace zero.Api.Endpoints.Countries;
public class CountryPermissions : PermissionProvider
{
public const string Create = "zero.settings.country.create";
public const string Read = "zero.settings.country.read";
public const string Update = "zero.settings.country.update";
public const string Delete = "zero.settings.country.delete";
public override Task Configure(IPermissionContext context)
{
if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group))
{
group.Permissions.Add(new Permission("zero.settings.country", "@settings.application.countries.name")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
}
return Task.CompletedTask;
}
}
@@ -1,17 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Countries;
public class zero_Api_Countries_Listing : ZeroIndex<Country>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
IsPreferred = item.IsPreferred
});
Index(x => x.Name, FieldIndexing.Search);
}
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Countries;
public class CountryBasic : BasicModel<Country>
{
public bool IsPreferred { get; set; }
public string Code { get; set; }
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Countries;
public class CountryEdit : DisplayModel<Country>
{
public bool IsPreferred { get; set; }
public string Code { get; set; }
}
@@ -1,33 +0,0 @@
namespace zero.Api.Endpoints.Countries;
public class CountryMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<Country, CountryBasic>((source, ctx) => new(), Map);
mapper.Define<Country, CountryEdit>((source, ctx) => new(), Map);
mapper.Define<CountrySave, Country>((source, ctx) => new(), Map);
}
protected virtual void Map(Country source, CountryBasic target, IZeroMapperContext ctx)
{
this.MapBasicData(source, target);
target.Code = source.Code;
target.IsPreferred = source.IsPreferred;
}
protected virtual void Map(Country source, CountryEdit target, IZeroMapperContext ctx)
{
this.MapDisplayData(source, target);
target.Code = source.Code;
target.IsPreferred = source.IsPreferred;
}
protected virtual void Map(CountrySave source, Country target, IZeroMapperContext ctx)
{
this.MapSaveData(source, target);
target.Code = source.Code;
target.IsPreferred = source.IsPreferred;
}
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Countries;
public class CountrySave : SaveModel<Country>
{
public bool IsPreferred { get; set; }
public string Code { get; set; }
}
@@ -1,30 +0,0 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Error;
public class ErrorController : ZeroApiController
{
[HttpGet("")]
public virtual ActionResult<ApiResponse> Index()
{
return new ErrorApiResponse()
{
Success = false,
Status = HttpContext.Response.StatusCode
};
//IExceptionHandlerFeature exception = HttpContext.Features.Get<IExceptionHandlerFeature>();
//return new ErrorApiResponse()
//{
// Success = false,
// Status = HttpContext.Response.StatusCode,
// Error = new()
// {
// ApiPath = exception.Path,
// Message = exception.Error.Message
// }
//};
}
}
@@ -1,11 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Error;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddZeroBackofficeErrorHandler(this IServiceCollection services)
{
return services;
}
}
@@ -1,17 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Integrations;
public class IntegrationModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IMapperProfile, IntegrationMapperProfile>();
//services.Configure<RavenOptions>(opts =>
//{
// opts.Indexes.Add<zero_Api_Languages_Listing>();
//});
}
}
@@ -1,172 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections;
using zero.Mapper;
namespace zero.Api.Endpoints.Integrations;
public class IntegrationsController : ZeroApiController
{
readonly IIntegrationTypeService IntegrationTypes;
readonly IIntegrationStore Store;
public IntegrationsController(IIntegrationTypeService integrationTypes, IIntegrationStore store)
{
IntegrationTypes = integrationTypes;
Store = store;
}
[HttpGet("types")]
//[ZeroAuthorize(SpacePermissions.Read)]
public virtual async Task<ActionResult<IEnumerable>> GetTypes()
{
IEnumerable<IntegrationTypeDisplay> result = Mapper.Map<IntegrationType, IntegrationTypeDisplay>(IntegrationTypes.GetAll()).ToList();
foreach (IntegrationTypeDisplay display in result)
{
Integration model = await Store.Load(display.Alias);
if (model != null)
{
display.IsConfigured = true;
display.IsActivated = model.IsActive;
display.ModelId = model.Id;
}
}
return Ok(result);
}
[HttpGet("types/{alias}")]
//[ZeroAuthorize(SpacePermissions.Read)]
public virtual async Task<ActionResult<IntegrationTypeDisplay>> GetType(string alias)
{
IntegrationTypeDisplay result = Mapper.Map<IntegrationType, IntegrationTypeDisplay>(IntegrationTypes.GetByAlias(alias));
if (result == null)
{
return NotFound();
}
Integration model = await Store.Load(result.Alias);
if (model != null)
{
result.IsConfigured = true;
result.IsActivated = model.IsActive;
result.ModelId = model.Id;
}
return Ok(result);
}
[HttpGet("empty/{alias}")]
//[ZeroAuthorize(CountryPermissions.Create)]
public virtual async Task<ActionResult<Integration>> Empty(string alias)
{
Integration model = await Store.Empty(alias);
if (model == null)
{
return NotFound();
}
return model;
}
[HttpGet("{alias}")]
//[ZeroAuthorize(CountryPermissions.Read)]
public virtual async Task<ActionResult<Integration>> Get(string alias)
{
Integration model = await Store.Load(alias);
if (model == null)
{
return NotFound();
}
HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model);
return model;
}
[HttpPost("")]
//[ZeroAuthorize(CountryPermissions.Create)]
public virtual async Task<ActionResult<Result>> Create(Integration saveModel)
{
Result<Integration> result = await Store.Create(saveModel);
bool minimalResponse = Hints.ResponsePreference == ApiResponsePreference.Minimal;
if (result.IsSuccess)
{
return Created("/", minimalResponse ? null : saveModel);
}
return result.WithoutModel();
}
[HttpPut("{alias}")]
//[ZeroAuthorize(CountryPermissions.Update)]
public virtual async Task<ActionResult<Result>> Update(string alias, Integration updateModel, [FromQuery] string changeToken = null)
{
if (alias != updateModel.Flavor)
{
return BadRequest(Result.Fail(nameof(alias), "@integration.errors.noaliasmatch"));
}
Result<Integration> result = await Store.Update(updateModel);
if (Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
return result;
}
[HttpPut("{alias}/activate")]
//[ZeroAuthorize(CountryPermissions.Update)]
public virtual async Task<ActionResult<Result>> Activate(string alias)
{
Result<Integration> result = await Store.Activate(alias);
if (Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
return result;
}
[HttpPut("{alias}/deactivate")]
//[ZeroAuthorize(CountryPermissions.Update)]
public virtual async Task<ActionResult<Result>> Deactivate(string alias)
{
Result<Integration> result = await Store.Deactivate(alias);
if (Hints.ResponsePreference == ApiResponsePreference.Minimal)
{
return result.WithoutModel();
}
return result;
}
[HttpDelete("{alias}")]
//[ZeroAuthorize(CountryPermissions.Delete)]
public virtual async Task<ActionResult<Result>> Delete(string alias)
{
Result<Integration> result = await Store.Delete(alias);
return result.WithoutModel();
}
}
@@ -1,20 +0,0 @@
namespace zero.Api.Endpoints.Integrations;
public class IntegrationMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<IntegrationType, IntegrationTypeDisplay>((source, ctx) => new(), Map);
}
protected virtual void Map(IntegrationType source, IntegrationTypeDisplay target, IZeroMapperContext ctx)
{
target.Description = source.Description;
target.Name = source.Name;
target.Alias = source.Alias;
target.EditorAlias = source.EditorAlias;
target.ImagePath = source.ImagePath;
target.Tags = source.Tags;
}
}
@@ -1,22 +0,0 @@
namespace zero.Api.Endpoints.Integrations;
public class IntegrationTypeDisplay
{
public string EditorAlias { get; set; }
public string Alias { get; set; }
public string Name { get; set; }
public List<string> Tags { get; set; } = new();
public string Description { get; set; }
public string ImagePath { get; set; }
public bool IsActivated { get; set; }
public bool IsConfigured { get; set; }
public string ModelId { get; set; }
}
@@ -1,18 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Languages;
public class zero_Api_Languages_Listing : ZeroIndex<Language>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
CreatedDate = item.CreatedDate,
IsDefault = item.IsDefault
});
Index(x => x.Name, FieldIndexing.Search);
}
}
@@ -1,18 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Languages;
public class LanguageModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, LanguagePermissions>();
services.AddSingleton<IMapperProfile, LanguageMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_Languages_Listing>();
});
}
}
@@ -1,29 +0,0 @@
namespace zero.Api.Endpoints.Languages;
public class LanguagePermissions : PermissionProvider
{
public const string Create = "zero.settings.language.create";
public const string Read = "zero.settings.language.read";
public const string Update = "zero.settings.language.update";
public const string Delete = "zero.settings.language.delete";
public override Task Configure(IPermissionContext context)
{
if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group))
{
group.Permissions.Add(new Permission("zero.settings.language", "@settings.application.languages.name")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
}
return Task.CompletedTask;
}
}
@@ -1,41 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Languages;
public class LanguagesController : ZeroApiEntityStoreController<Language, ILanguageStore>
{
public LanguagesController(ILanguageStore store) : base(store)
{
}
[HttpGet("empty")]
[ZeroAuthorize(LanguagePermissions.Create)]
public virtual Task<ActionResult<Language>> Empty(string flavor = null) => EmptyModel(flavor);
[HttpGet("{id}")]
[ZeroAuthorize(LanguagePermissions.Read)]
public virtual Task<ActionResult<Language>> Get(string id, string changeVector = null) => GetModel(id, changeVector);
[HttpGet("")]
[ZeroAuthorize(LanguagePermissions.Read)]
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<Language> query) => GetModelsByIndex<LanguageBasic, zero_Api_Languages_Listing>(query);
[HttpPost("")]
[ZeroAuthorize(LanguagePermissions.Create)]
public virtual Task<ActionResult<Result>> Create(Language saveModel) => CreateModel(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(LanguagePermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, Language updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(LanguagePermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
}
@@ -1,10 +0,0 @@
namespace zero.Api.Endpoints.Languages;
public class LanguageBasic : BasicModel<Language>
{
public string Code { get; set; }
public bool IsDefault { get; set; }
public string InheritedLanguageId { get; set; }
}
@@ -1,10 +0,0 @@
namespace zero.Api.Endpoints.Languages;
public class LanguageEdit : DisplayModel<Language>
{
public string Code { get; set; }
public bool IsDefault { get; set; }
public string InheritedLanguageId { get; set; }
}
@@ -1,36 +0,0 @@
namespace zero.Api.Endpoints.Languages;
public class LanguageMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<Language, LanguageBasic>((source, ctx) => new(), Map);
mapper.Define<Language, LanguageEdit>((source, ctx) => new(), Map);
mapper.Define<LanguageSave, Language>((source, ctx) => new(), Map);
}
protected virtual void Map(Language source, LanguageBasic target, IZeroMapperContext ctx)
{
this.MapBasicData(source, target);
target.Code = source.Code;
target.IsDefault = source.IsDefault;
target.InheritedLanguageId = source.InheritedLanguageId;
}
protected virtual void Map(Language source, LanguageEdit target, IZeroMapperContext ctx)
{
this.MapDisplayData(source, target);
target.Code = source.Code;
target.IsDefault = source.IsDefault;
target.InheritedLanguageId = source.InheritedLanguageId;
}
protected virtual void Map(LanguageSave source, Language target, IZeroMapperContext ctx)
{
this.MapSaveData(source, target);
target.Code = source.Code;
target.IsDefault = source.IsDefault;
target.InheritedLanguageId = source.InheritedLanguageId;
}
}
@@ -1,10 +0,0 @@
namespace zero.Api.Endpoints.Languages;
public class LanguageSave : SaveModel<Language>
{
public string Code { get; set; }
public bool IsDefault { get; set; }
public string InheritedLanguageId { get; set; }
}
@@ -1,21 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Mails;
public class zero_Api_MailTemplates_Listing : ZeroIndex<MailTemplate>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
item.Name,
item.Key,
item.Subject,
item.CreatedDate
});
Index(x => x.Name, FieldIndexing.Search);
Index(x => x.Key, FieldIndexing.Search);
Index(x => x.Subject, FieldIndexing.Search);
}
}
-18
View File
@@ -1,18 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Mails;
public class MailModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, MailPermissions>();
services.AddSingleton<IMapperProfile, MailMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_MailTemplates_Listing>();
});
}
}
@@ -1,29 +0,0 @@
namespace zero.Api.Endpoints.Mails;
public class MailPermissions : PermissionProvider
{
public const string Create = "zero.settings.mail.create";
public const string Read = "zero.settings.mail.read";
public const string Update = "zero.settings.mail.update";
public const string Delete = "zero.settings.mail.delete";
public override Task Configure(IPermissionContext context)
{
if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group))
{
group.Permissions.Add(new Permission("zero.settings.mail", "@settings.application.mails.name")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
}
return Task.CompletedTask;
}
}
@@ -1,45 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Mails;
public class MailTemplatesController : ZeroApiEntityStoreController<MailTemplate, IMailTemplatesStore>
{
public MailTemplatesController(IMailTemplatesStore store) : base(store)
{
}
[HttpGet("empty")]
[ZeroAuthorize(MailPermissions.Create)]
public virtual Task<ActionResult<MailEdit>> Empty(string flavor = null) => EmptyModel<MailEdit>(flavor);
[HttpGet("{id}")]
[ZeroAuthorize(MailPermissions.Read)]
public virtual Task<ActionResult<MailEdit>> Get(string id, string changeVector = null) => GetModel<MailEdit>(id, changeVector);
[HttpGet("")]
[ZeroAuthorize(MailPermissions.Read)]
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<MailTemplate> query)
{
query.SearchFor(entity => entity.Name, entity => entity.Key, entity => entity.Subject);
return GetModelsByIndex<MailBasic, zero_Api_MailTemplates_Listing>(query);
}
[HttpPost("")]
[ZeroAuthorize(MailPermissions.Create)]
public virtual Task<ActionResult<Result>> Create(MailSave saveModel) => CreateModel<MailSave, MailEdit>(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(MailPermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, MailSave updateModel, [FromQuery] string changeToken = null) => UpdateModel<MailSave, MailEdit>(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(MailPermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
}
@@ -1,6 +0,0 @@
namespace zero.Api.Endpoints.Mails;
public class MailBasic : BasicModel<MailTemplate>
{
public string Subject { get; set; }
}
-20
View File
@@ -1,20 +0,0 @@
namespace zero.Api.Endpoints.Mails;
public class MailEdit : DisplayModel<MailTemplate>
{
public string SenderEmail { get; set; }
public string SenderName { get; set; }
public string RecipientEmail { get; set; }
public string Cc { get; set; }
public string Bcc { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string Preheader { get; set; }
}
@@ -1,44 +0,0 @@
namespace zero.Api.Endpoints.Mails;
public class MailMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<MailTemplate, MailBasic>((source, ctx) => new(), Map);
mapper.Define<MailTemplate, MailEdit>((source, ctx) => new(), Map);
mapper.Define<MailSave, MailTemplate>((source, ctx) => new(), Map);
}
protected virtual void Map(MailTemplate source, MailBasic target, IZeroMapperContext ctx)
{
this.MapBasicData(source, target);
target.Subject = source.Subject;
}
protected virtual void Map(MailTemplate source, MailEdit target, IZeroMapperContext ctx)
{
this.MapDisplayData(source, target);
target.Subject = source.Subject;
target.SenderEmail = source.SenderEmail;
target.SenderName = source.SenderName;
target.RecipientEmail = source.RecipientEmail;
target.Cc = source.Cc;
target.Bcc = source.Bcc;
target.Body = source.Body;
target.Preheader = source.Preheader;
}
protected virtual void Map(MailSave source, MailTemplate target, IZeroMapperContext ctx)
{
this.MapSaveData(source, target);
target.Subject = source.Subject;
target.SenderEmail = source.SenderEmail;
target.SenderName = source.SenderName;
target.RecipientEmail = source.RecipientEmail;
target.Cc = source.Cc;
target.Bcc = source.Bcc;
target.Body = source.Body;
target.Preheader = source.Preheader;
}
}
-20
View File
@@ -1,20 +0,0 @@
namespace zero.Api.Endpoints.Mails;
public class MailSave : SaveModel<MailTemplate>
{
public string SenderEmail { get; set; }
public string SenderName { get; set; }
public string RecipientEmail { get; set; }
public string Cc { get; set; }
public string Bcc { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string Preheader { get; set; }
}
@@ -1,32 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Media;
public class zero_Api_Media_ChildCounts : ZeroIndex<zero.Media.Media, zero_Api_Media_ChildCounts.Result>
{
public class Result : ZeroIdEntity
{
public int ChildCount { get; set; }
public int ChildFolderCount { get; set; }
}
protected override void Create()
{
Map = items => items.Where(x => x.ParentId != null).Select(item => new Result
{
Id = item.ParentId,
ChildCount = 1,
ChildFolderCount = item.IsFolder ? 1 : 0
});
Reduce = results => results.GroupBy(x => new { x.Id }).Select(group => new Result()
{
Id = group.Key.Id,
ChildCount = group.Sum(x => x.ChildCount),
ChildFolderCount = group.Sum(x => x.ChildFolderCount)
});
StoreAllFields(FieldStorage.Yes);
}
}
@@ -1,28 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Media;
public class MediaTreeHierarchyIndexResult : ZeroTreeHierarchyIndexResult
{
public bool IsFolder { get; set; }
}
public class zero_Api_Media_Hierarchy : ZeroTreeHierarchyIndex<zero.Media.Media>
{
protected override void Create()
{
Map = items => items.Select(item => new MediaTreeHierarchyIndexResult
{
Id = item.Id,
IsFolder = item.IsFolder,
Path = Recurse(item, x => LoadDocument<zero.Media.Media>(x.ParentId))
.Where(x => x != null && x.Id != null && x.Id != item.Id)
.Reverse()
.Select(current => current.Id)
.ToList()
});
StoreAllFields(FieldStorage.Yes);
}
}
@@ -1,22 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Media;
public class zero_Api_Media_Listing : ZeroIndex<zero.Media.Media>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
ParentId = item.ParentId,
CreatedDate = item.CreatedDate,
IsFolder = item.IsFolder
});
Index(x => x.Name, FieldIndexing.Search);
Index(x => x.ParentId, FieldIndexing.Exact);
Index(x => x.CreatedDate, FieldIndexing.Exact);
Index(x => x.IsFolder, FieldIndexing.Exact);
}
}
@@ -1,18 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaBasic : ZeroIdEntity
{
public string ParentId { get; set; }
public string Name { get; set; }
public bool IsFolder { get; set; }
public string Source { get; set; }
public string Preview { get; set; }
public int Children { get; set; }
public long Size { get; set; }
}
@@ -1,6 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaBulkDeleteOperation
{
public string[] Ids { get; set; }
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaBulkMoveOperation
{
public string ParentId { get; set; }
public string[] Ids { get; set; }
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaDescendantStatistics
{
public int Folders { get; set; }
public int Files { get; set; }
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaEdit : DisplayModel<zero.Media.Media>
{
public bool IsFolder { get; set; }
public string ParentId { get; set; }
}
@@ -1,18 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaFileEdit : MediaEdit
{
public string AlternativeText { get; set; }
public string Caption { get; set; }
public string Path { get; set; }
public Dictionary<string, string> Thumbnails { get; set; } = new();
public long Size { get; set; }
public MediaImageMetadata ImageMeta { get; set; }
public MediaFocalPoint FocalPoint { get; set; }
}
@@ -1,6 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaFolderEdit : MediaEdit
{
}
@@ -1,77 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaMapperProfile : ZeroMapperProfile
{
protected IMediaFileSystem FileSystem { get; private set; }
public MediaMapperProfile(IMediaFileSystem fileSystem)
{
FileSystem = fileSystem;
}
public override void Configure(IZeroMapper mapper)
{
mapper.Define<zero.Media.Media, MediaBasic>((source, ctx) => new(), Map);
mapper.Define<zero.Media.Media, MediaEdit>((source, ctx) => new(), Map);
mapper.Define<zero.Media.Media, MediaFileEdit>((source, ctx) => new(), Map);
mapper.Define<zero.Media.Media, MediaFolderEdit>((source, ctx) => new(), Map);
mapper.Define<MediaSave, zero.Media.Media>((source, ctx) => new(), Map);
}
protected virtual void Map(zero.Media.Media source, MediaBasic target, IZeroMapperContext ctx)
{
target.Id = source.Id;
target.Name = source.Name;
target.ParentId = source.ParentId;
target.IsFolder = source.IsFolder;
target.Children = 0;
target.Size = source.Size;
if (source.Path.HasValue())
{
target.Source = FileSystem.MapToPublicPath(source.Path);
}
if (source.ImageMeta != null && source.ImageMeta.Thumbnails.Any())
{
string path = source.ImageMeta.Thumbnails.GetValueOrDefault("preview");
target.Preview = path.IsNullOrEmpty() ? null : FileSystem.MapToPublicPath(path);
}
}
protected virtual void Map(zero.Media.Media source, MediaEdit target, IZeroMapperContext ctx)
{
this.MapDisplayData(source, target);
target.IsFolder = source.IsFolder;
target.ParentId = source.ParentId;
}
protected virtual void Map(zero.Media.Media source, MediaFolderEdit target, IZeroMapperContext ctx)
{
Map(source, (MediaEdit)target, ctx);
}
protected virtual void Map(zero.Media.Media source, MediaFileEdit target, IZeroMapperContext ctx)
{
Map(source, (MediaEdit)target, ctx);
target.AlternativeText = source.ImageMeta?.AlternativeText;
target.Caption = source.Caption;
target.Path = source.Path;
target.Thumbnails = source.ImageMeta?.Thumbnails;
target.Size = source.Size;
target.ImageMeta = source.ImageMeta;
target.FocalPoint = source.ImageMeta?.FocalPoint;
}
protected virtual void Map(MediaSave source, zero.Media.Media target, IZeroMapperContext ctx)
{
this.MapSaveData(source, target);
}
}
@@ -1,6 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaSave : SaveModel<zero.Media.Media>
{
public bool IsFolder { get; set; }
}
@@ -1,6 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaSourceResult
{
public string Path { get; set; }
}
-380
View File
@@ -1,380 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Net.Http.Headers;
using Raven.Client.Documents;
using Raven.Client.Documents.Linq;
using System.IO;
namespace zero.Api.Endpoints.Media;
/// <summary>
/// GET /empty
/// GET /
/// GET /{id}
/// GET /{id}/hierarchy
/// GET /{id}/{size}.tmp
/// POS /
/// PUT /{id}
/// PUT /{id/move/{folderId}
/// DEL /{id}
///
/// GET /folders/empty
/// GET /folders/{id}
/// GET /folders/{id}/children
/// GET /folders/{id}/hierarchy
/// POS /folders/
/// PUT /folders/{id}
/// PUT /folders/{id/move/{folderId}
/// DEL /folders/{id}
///
/// GET /bulk/descendants
/// PUT /bulk/move
/// DEL /bulk/delete
/// </summary>
public class MediaController : ZeroApiTreeEntityStoreController<zero.Media.Media, IMediaStore>
{
IMediaManagement Media;
public MediaController(IMediaStore store, IMediaManagement media) : base(store)
{
Media = media;
}
#region bulk operations
[HttpPut("bulk/move")]
[ZeroAuthorize(MediaPermissions.Update)]
public virtual async Task<ActionResult<IEnumerable<Result>>> BulkMove(MediaBulkMoveOperation operation)
{
List<Result<string>> results = new();
foreach (string id in operation.Ids)
{
Result<zero.Media.Media> result = await Store.Move(id, NormalizeParentId(operation.ParentId));
results.Add(result.ConvertTo(id));
}
return results;
}
[HttpDelete("bulk/delete")]
[ZeroAuthorize(MediaPermissions.Update)]
public virtual async Task<ActionResult<IEnumerable<Result>>> BulkDelete(MediaBulkDeleteOperation operation)
{
List<Result<string>> results = new();
foreach (string id in operation.Ids)
{
Result<string[]> result = await Store.DeleteWithDescendants(id);
results.Add(result.ConvertTo(id));
}
return results;
}
[HttpGet("bulk/descendants")]
[ZeroAuthorize(MediaPermissions.Update)]
public virtual async Task<ActionResult<MediaDescendantStatistics>> GetDescendantStatistics([FromQuery] string[] ids)
{
List<Result<string>> results = new();
Dictionary<string, zero.Media.Media> parents = await Store.Load(ids);
int folderCount = parents.Count(x => x.Value != null && x.Value.IsFolder);
int fileCount = parents.Count(x => x.Value != null && !x.Value.IsFolder);
folderCount += await Store.Session.Query<MediaTreeHierarchyIndexResult, zero_Api_Media_Hierarchy>().CountAsync(x => x.Path.ContainsAny(ids) && x.IsFolder);
fileCount += await Store.Session.Query<MediaTreeHierarchyIndexResult, zero_Api_Media_Hierarchy>().CountAsync(x => x.Path.ContainsAny(ids) && !x.IsFolder);
return new MediaDescendantStatistics()
{
Files = fileCount,
Folders = folderCount
};
}
#endregion
#region folder operations
[HttpGet("folders/empty")]
[ZeroAuthorize(MediaPermissions.Create)]
public virtual async Task<ActionResult<zero.Media.Media>> EmptyFolder(string flavor = null) => await EmptyModel(flavor, x => x.IsFolder = true);
[HttpGet("folders")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual Task<ActionResult<Paged>> GetFoldersByQuery([FromQuery] ListQuery<zero.Media.Media> query)
{
query.AdditionalQuery = q => q.Where(x => x.IsFolder);
return GetModelsByIndex<MediaBasic, zero_Api_Media_Listing>(query);
}
[HttpGet("folders/{id}")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<zero.Media.Media>> GetFolder(string id, string changeVector = null) => await GetModel(id, changeVector);
[HttpGet("folders/{id}/children")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<Paged>> GetFolderChildren(string id, [FromQuery] ListQuery<zero.Media.Media> query, [FromQuery] bool files = true)
{
id = NormalizeParentId(id);
zero.Media.Media parent = null;
if (id.HasValue())
{
parent = await Store.Load(id);
if (parent == null)
{
return NotFound();
}
}
query.OrderQuery = q => q.OrderByDescending(x => x.IsFolder).ThenByDescending(x => x.CreatedDate);
Paged<zero.Media.Media> result = await Store.LoadChildren<zero_Api_Media_Listing>(id, query.Page, query.PageSize, q => q.WhereIf(x => x.IsFolder, !files).Filter(query));
Paged<MediaBasic> mappedResult = Mapper.Map<zero.Media.Media, MediaBasic>(result);
// get children for all folders
string[] folderIds = mappedResult.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray();
IList<zero_Api_Media_ChildCounts.Result> children = await Store.Session.Query<zero_Api_Media_ChildCounts.Result, zero_Api_Media_ChildCounts>()
.ProjectInto<zero_Api_Media_ChildCounts.Result>()
.Where(x => x.Id.In(folderIds))
.ToListAsync();
foreach (MediaBasic item in mappedResult.Items)
{
if (item.IsFolder)
{
zero_Api_Media_ChildCounts.Result childCounts = children.FirstOrDefault(x => x.Id == item.Id);
if (childCounts != null)
{
item.Children = !files ? childCounts.ChildFolderCount : childCounts.ChildCount;
}
}
}
mappedResult.Properties.Add("parentId", parent?.ParentId);
return mappedResult;
}
[HttpGet("folders/{id}/hierarchy")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<zero.Media.Media[]>> GetFolderHierarchy(string id)
{
return await Store.GetHierarchy<zero_Api_Media_Hierarchy>(NormalizeParentId(id));
}
[HttpPost("folders")]
[ZeroAuthorize(MediaPermissions.Create)]
public virtual Task<ActionResult<Result>> CreateFolder(zero.Media.Media saveModel)
{
saveModel.IsFolder = true;
return CreateModel(saveModel);
}
[HttpPut("folders/{id}")]
[ZeroAuthorize(MediaPermissions.Update)]
public virtual Task<ActionResult<Result>> UpdateFolder(string id, zero.Media.Media updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpPut("folders/{id}/move/{destinationId}")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<Result>> MoveFolder(string id, string destinationId) => await MoveModel(id, NormalizeParentId(destinationId));
[HttpDelete("folders/{id}")]
[ZeroAuthorize(MediaPermissions.Delete)]
public virtual Task<ActionResult<Result<string[]>>> DeleteFolder(string id) => DeleteModelWithDescendants(id);
#endregion
#region file operations
[HttpGet("empty")]
[ZeroAuthorize(MediaPermissions.Create)]
public virtual async Task<ActionResult<zero.Media.Media>> Empty(string flavor = null) => await EmptyModel(flavor, x => x.IsFolder = false);
[HttpGet("")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual Task<ActionResult<Paged>> GetByQuery([FromQuery] ListQuery<zero.Media.Media> query)
{
query.AdditionalQuery = q => q.Where(x => !x.IsFolder);
return GetModelsByIndex<MediaBasic, zero_Api_Media_Listing>(query);
}
[HttpGet("search")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<Paged>> Search([FromQuery] ListQuery<zero.Media.Media> query, [FromQuery(Name = "q")] string searchQuery, [FromQuery] string parent = null, [FromQuery] bool includeSubfolders = true)
{
query.OrderQuery = q => q.OrderByScoreDescending().ThenByDescending(x => x.IsFolder).ThenByDescending(x => x.CreatedDate);
query.Search = null;
if (searchQuery.IsNullOrWhiteSpace())
{
return NotFound();
}
if (parent.HasValue())
{
List<string> descendantIds = await Store.Session.Query<MediaTreeHierarchyIndexResult, zero_Api_Media_Hierarchy>().Where(x => x.Path.Contains(parent) && x.IsFolder).Select(x => x.Id).ToListAsync();
descendantIds.Add(parent);
query.AdditionalQuery = q => q.Where(x => x.ParentId.In(descendantIds));
}
Paged<zero.Media.Media> result = await Store.Load<zero_Api_Media_Listing>(query.Page, query.PageSize, q => q
.SearchIf(x => x.Name, searchQuery, "*", "*", Raven.Client.Documents.Queries.SearchOperator.And)
.Filter(query)
);
Paged<MediaBasic> mappedResult = Mapper.Map<zero.Media.Media, MediaBasic>(result);
// get children for all folders
string[] folderIds = mappedResult.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray();
IList<zero_Api_Media_ChildCounts.Result> children = await Store.Session.Query<zero_Api_Media_ChildCounts.Result, zero_Api_Media_ChildCounts>()
.ProjectInto<zero_Api_Media_ChildCounts.Result>()
.Where(x => x.Id.In(folderIds))
.ToListAsync();
foreach (MediaBasic item in mappedResult.Items)
{
if (item.IsFolder)
{
zero_Api_Media_ChildCounts.Result childCounts = children.FirstOrDefault(x => x.Id == item.Id);
item.Children = childCounts?.ChildCount ?? 0;
}
}
return mappedResult;
}
[HttpGet("{id}")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<zero.Media.Media>> Get(string id, string changeVector = null) => await GetModel(id, changeVector);
[HttpGet("{id}/source")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<MediaSourceResult>> GetSource(string id)
{
string path = await Media.GetPublicFilePath(id);
if (path.IsNullOrEmpty())
{
return NotFound();
}
return new MediaSourceResult()
{
Path = path
};
}
[HttpGet("{id}/hierarchy")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<zero.Media.Media[]>> GetHierarchy(string id) => await Store.GetHierarchy<zero_Api_Media_Hierarchy>(NormalizeParentId(id));
[HttpGet("{id}/search")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<Paged>> SearchByQueryAndParent(string id, [FromQuery] ListQuery<zero.Media.Media> query)
{
List<string> folderIds = await Store.Session.Query<MediaTreeHierarchyIndexResult, zero_Api_Media_Hierarchy>().Where(x => x.Path.Contains(id) && x.IsFolder).Select(x => x.Id).ToListAsync();
folderIds.Add(id);
query.AdditionalQuery = q => q.Where(x => x.ParentId.In(folderIds));
return await GetModelsByIndex<MediaBasic, zero_Api_Media_Listing>(query);
}
[HttpPost("")]
[ZeroAuthorize(MediaPermissions.Create)]
public virtual async Task<ActionResult<Result>> Create([FromForm] IFormFile file, [FromForm] string folderId = null)
{
Result<zero.Media.Media> result = await Media.UploadFile(file, folderId);
bool minimalResponse = Hints.ResponsePreference == ApiResponsePreference.Minimal;
if (result.IsSuccess)
{
return Created("/", minimalResponse ? null : result.Model); // TODO correct URL
}
return result.WithoutModel();
}
[HttpPut("{id}")]
[ZeroAuthorize(MediaPermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, zero.Media.Media updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpPut("{id}/move/{destinationId}")]
[ZeroAuthorize(MediaPermissions.Read)]
public virtual async Task<ActionResult<Result>> Move(string id, string destinationId) => await MoveModel(id, NormalizeParentId(destinationId));
[HttpDelete("{id}")]
[ZeroAuthorize(MediaPermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
[HttpGet("{id}/{size}.tmp")]
public async Task<IActionResult> GetThumbnail(string id, string size)
{
zero.Media.Media media = await Media.GetFile(id);
if (media == null)
{
return NotFound();
}
string path = Media.GetPublicFilePath(media);
if (path == null)
{
return NotFound();
}
if (path.StartsWith("url://"))
{
path = path.Substring(6);
}
FileExtensionContentTypeProvider provider = new();
string contentType;
if (!provider.TryGetContentType(Path.GetFileName(path), out contentType))
{
contentType = "application/octet-stream";
}
try
{
return File(await Media.GetFileStream(media), contentType, DateTimeOffset.Now, EntityTagHeaderValue.Any);
}
catch (FileSystemException)
{
return NotFound();
}
}
#endregion
}
-20
View File
@@ -1,20 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Media;
public class MediaModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, MediaPermissions>();
services.AddSingleton<IMapperProfile, MediaMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_Media_Listing>();
opts.Indexes.Add<zero_Api_Media_ChildCounts>();
opts.Indexes.Add<zero_Api_Media_Hierarchy>();
});
}
}
@@ -1,31 +0,0 @@
namespace zero.Api.Endpoints.Media;
public class MediaPermissions : PermissionProvider
{
public const string Group = "zero.media";
public const string Create = "zero.settings.media.create";
public const string Read = "zero.settings.media.read";
public const string Update = "zero.settings.media.update";
public const string Delete = "zero.settings.media.delete";
public override Task Configure(IPermissionContext context)
{
PermissionGroup group = new(Group, "@media.list");
group.Permissions.Add(new Permission("zero.media.defaults", "Default permissions")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
context.AddGroup(group);
return Task.CompletedTask;
}
}
@@ -1,72 +0,0 @@
//using Microsoft.AspNetCore.Http;
//using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.StaticFiles;
//using Microsoft.Net.Http.Headers;
//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Net.Http;
//using System.Threading.Tasks;
//using zero.Core;
//using zero.Core.Collections;
//using zero.Core.Entities;
//using zero.Core.Identity;
//using zero.Web.Models;
//namespace zero.Web.Controllers
//{
// [ZeroAuthorize(Permissions.Sections.Media, PermissionsValue.True)]
// public class MediaController : ZeroBackofficeCollectionController<Media, IMediaCollection>
// {
// IPaths Paths;
// public MediaController(IMediaCollection collection, IPaths paths) : base(collection)
// {
// Paths = paths;
// PreviewTransform = (item, model) => model.Icon = "fth-globe";
// }
// public async Task<Paged<MediaListItem>> GetListByQuery([FromQuery] MediaListItemQuery query)
// {
// query.IncludeInactive = true;
// return await Collection.Load(query);
// }
// [HttpPost]
// public async Task<Result<Media>> Upload(IFormFile file, [FromForm] string folderId) => await Collection.Save(await Collection.Upload(file, folderId));
// [HttpPost]
// public async Task<Media> UploadTemporary(IFormFile file, [FromForm] string folderId) => await Collection.Upload(file, folderId);
// [HttpPost]
// public async Task<Result<Media>> Move([FromBody] ActionCopyModel model) => await Collection.Move(model.Id, model.DestinationId);
// public async Task<MediaListResultModel> GetAll([FromQuery] MediaListQuery query)
// {
// query.IncludeInactive = true;
// Paged<MediaListModel> items = (await Collection.Load(query)).MapTo(x => new MediaListModel()
// {
// Id = x.Id,
// IsFolder = false,
// Name = x.Name,
// Size = x.Size,
// Source = x.PreviewSource ?? x.Source,
// Type = x.Type
// });
// IList<MediaFolder> hierarchy = null;
// MediaFolder folder = null;
// if (!String.IsNullOrEmpty(query.FolderId))
// {
// folder = await Collection.Folders.Load(query.FolderId);
// hierarchy = await Collection.Folders.GetHierarchy(query.FolderId);
// }
// return new MediaListResultModel(items, null, folder, hierarchy);
// }
// }
//}
@@ -1,26 +0,0 @@
//using Microsoft.AspNetCore.Mvc;
//using System.Collections.Generic;
//using System.Threading.Tasks;
//using zero.Core.Collections;
//using zero.Core.Entities;
//using zero.Core.Identity;
//using zero.Web.Models;
//namespace zero.Web.Controllers
//{
// [ZeroAuthorize(Permissions.Sections.Media, PermissionsValue.True)]
// public class MediaFolderController : ZeroBackofficeCollectionController<MediaFolder, IMediaFolderCollection>
// {
// public MediaFolderController(IMediaFolderCollection collection) : base(collection) { }
// public async Task<IList<MediaFolder>> GetHierarchy([FromQuery] string id) => await Collection.GetHierarchy(id);
// public async Task<IList<TreeItem>> GetAllAsTree([FromQuery] string parent = null, [FromQuery] string active = null) => await Collection.LoadAsTree(parent, active);
// [HttpPost]
// public async Task<Result<MediaFolder>> Move([FromBody] ActionCopyModel model) => await Collection.Move(model.Id, model.DestinationId);
// }
//}
@@ -1,250 +0,0 @@
//using Raven.Client.Documents;
//using Raven.Client.Documents.Linq;
//using Raven.Client.Documents.Session;
//namespace zero.Backoffice.Modules;
//public class MediaTreeService : IMediaTreeService
//{
// protected IMediaStore Media { get; private set; }
// protected PageOptions PageOptions { get; set; }
// public PageTreeService(IPagesStore pages, IZeroOptions options, IRoutes routes)
// {
// Media = pages;
// Routes = routes;
// PageOptions = options.For<PageOptions>();
// }
// /// <inheritdoc />
// /// FOR MEDIA
// public virtual async Task<Paged<MediaListItem>> Load(MediaListItemQuery query)
// {
// bool hasSearch = !query.Search.IsNullOrWhiteSpace();
// bool isRoot = query.FolderId.IsNullOrWhiteSpace();
// query.SearchFor(entity => entity.Name);
// query.OrderQuery = q => q
// .OrderByDescending(x => x.IsFolder)
// .ThenBy(query.OrderBy, query.OrderIsDescending, query.OrderType == ListQueryOrderType.String ? OrderingType.String : OrderingType.Double);
// IRavenQueryable<MediaListItem> dbQuery = Session.Query<MediaListItem, Media_ByParent>().ProjectInto<MediaListItem>();
// if (!hasSearch || !query.SearchIsGlobal)
// {
// dbQuery = dbQuery.WhereIf(x => x.ParentId == query.FolderId, !query.FolderId.IsNullOrEmpty(), x => x.ParentId == null);
// }
// Paged<MediaListItem> result = await dbQuery.ToQueriedListAsyncX(query);
// string[] ids = result.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray();
// List<Media_ByChildren.Result> children = await Session.Query<Media_ByChildren.Result, Media_ByChildren>()
// .Where(x => x.ParentId.In(ids))
// .ToListAsync();
// foreach (MediaListItem item in result.Items)
// {
// item.Children = children.FirstOrDefault(x => x.ParentId == item.Id)?.ChildrenCount ?? 0;
// }
// return result;
// }
// /// <inheritdoc />
// /// FOR MEDIA FOLDER
// public async Task<List<TreeItem>> LoadAsTree(string parentId = null, string activeId = null)
// {
// List<TreeItem> items = new();
// string[] openIds = Array.Empty<string>();
// IList<MediaFolder> folders = await Session.Query<MediaFolder>()
// .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null)
// .OrderByDescending(x => x.CreatedDate).ThenBy(x => x.Name)
// .ToListAsync();
// // get hierarchy so we know if we should set the folder to open
// if (!activeId.IsNullOrEmpty())
// {
// MediaFolder_ByHierarchy.Result result = await Session.Query<MediaFolder_ByHierarchy.Result, MediaFolder_ByHierarchy>()
// .ProjectInto<MediaFolder_ByHierarchy.Result>()
// .Include<MediaFolder_ByHierarchy.Result, MediaFolder>(x => x.Path.Select(p => p.Id))
// .FirstOrDefaultAsync(x => x.Id == activeId);
// if (result != null)
// {
// openIds = result.Path.Select(x => x.Id).ToArray();
// }
// }
// // get children for all folders
// string[] folderIds = folders.Select(x => x.Id).ToArray();
// IList<MediaFolders_WithChildren.Result> children = await Session.Query<MediaFolders_WithChildren.Result, MediaFolders_WithChildren>()
// .ProjectInto<MediaFolders_WithChildren.Result>()
// .Where(x => x.Id.In(folderIds))
// .ToListAsync();
// foreach (MediaFolder folder in folders)
// {
// int childCount = children.Count(x => x.Id == folder.Id);
// items.Add(new TreeItem()
// {
// Id = folder.Id,
// Name = folder.Name,
// HasChildren = childCount > 0,
// ChildCount = childCount,
// ParentId = folder.ParentId,
// Sort = folder.Sort,
// Icon = "fth-folder",
// IsOpen = openIds.Contains(folder.Id),
// IsInactive = !folder.IsActive,
// HasActions = true,
// Modifier = !folder.IsActive ? new TreeItemModifier()
// {
// Icon = "fth-minus-circle color-yellow",
// Name = "Inactive"
// } : null
// });
// }
// return items;
// }
// /// <inheritdoc />
// public async Task<IList<TreeItem>> GetChildren(string parentId = null, string activeId = null, string search = null)
// {
// IList<TreeItem> items = new List<TreeItem>();
// IReadOnlyCollection<PageType> pageTypes = PageOptions.GetAllItems();
// string[] openIds = new string[0] { };
// Paged<Page> pages = null;
// IList<Pages_WithChildren.Result> children = null;
// bool isSearch = !search.IsNullOrWhiteSpace();
// if (isSearch)
// {
// pages = await Media.Load(1, Int32.MaxValue, q => q.SearchIf(x => x.Name, search, "*").OrderBy(x => x.Sort, OrderingType.Long));
// var urls = await Routes.GetUrls(pages.Items.ToArray());
// foreach (Page page in pages.Items)
// {
// if (urls.TryGetValue(page, out string url))
// {
// page.Url = url;
// }
// }
// }
// else
// {
// pages = await Media.Load(1, Int32.MaxValue, q => q
// .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null)
// .OrderBy(x => x.Sort, OrderingType.Long));
// // get hierarchy so we know if we should set the page to open
// if (!activeId.IsNullOrEmpty())
// {
// Pages_ByHierarchy.Result result = await Media.Session.Query<Pages_ByHierarchy.Result, Pages_ByHierarchy>()
// .ProjectInto<Pages_ByHierarchy.Result>()
// .Include<Pages_ByHierarchy.Result, Page>(x => x.Path.Select(p => p.Id))
// .FirstOrDefaultAsync(x => x.Id == activeId);
// if (result != null)
// {
// openIds = result.Path.Select(x => x.Id).ToArray(); // .Union(new string[1] { activeId })
// }
// }
// // get children for all pages
// string[] pageIds = pages.Items.Select(x => x.Id).ToArray();
// children = await Media.Session.Query<Pages_WithChildren.Result, Pages_WithChildren>()
// .ProjectInto<Pages_WithChildren.Result>()
// .Where(x => x.Id.In(pageIds))
// .ToListAsync();
// }
// // function to get modifier icon
// TreeItemModifier GetModifier(Page page)
// {
// if (page.PublishDate > DateTimeOffset.Now || page.UnpublishDate > DateTimeOffset.Now)
// {
// return new TreeItemModifier("@page.schedule.scheduled", "fth-clock");
// }
// if (!page.IsActive)
// {
// return new TreeItemModifier("@ui.inactive", "fth-minus-circle color-red");
// }
// return null;
// }
// // build tree
// foreach (Page page in pages.Items)
// {
// PageType pageType = pageTypes.FirstOrDefault(x => x.Alias == page.PageTypeAlias);
// if (pageType == null)
// {
// continue;
// // TODO the page type does not exist anymore
// }
// int childCount = isSearch ? 0 : children.Count(x => x.Id == page.Id);
// items.Add(new TreeItem()
// {
// Id = page.Id,
// Name = page.Name,
// HasChildren = childCount > 0,
// ChildCount = childCount,
// ParentId = page.ParentId,
// Sort = page.Sort,
// Icon = pageType.Icon,
// IsOpen = openIds.Contains(page.Id),
// IsInactive = !page.IsActive,
// HasActions = true,
// Modifier = GetModifier(page),
// Description = isSearch ? page.Url : null
// });
// }
// if (parentId.IsNullOrEmpty())
// {
// items.Add(new TreeItem()
// {
// Id = "recyclebin",
// ParentId = null,
// Sort = 99999,
// Name = "@recyclebin.name",
// Icon = "fth-trash",
// HasChildren = false,
// HasActions = true
// });
// }
// return items;
// }
//}
//public interface IMediaTreeService
//{
// /// <summary>
// /// Get media children as tree items
// /// </summary>
// Task<IList<TreeItem>> GetChildren(string parentId = null, string activeId = null, string search = null);
//}
@@ -1,11 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.NotFound;
public class NotFoundZeroApiController : Controller
{
public virtual ActionResult Index()
{
return NotFound();
}
}
@@ -1,12 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.PageModules;
public class PageModuleModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, PageModulePermissions>();
}
}
@@ -1,31 +0,0 @@
namespace zero.Api.Endpoints.PageModules;
public class PageModulePermissions : PermissionProvider
{
public const string Group = "zero.pagemodules";
public const string Create = "zero.pagemodules.create";
public const string Read = "zero.pagemodules.read";
public const string Update = "zero.pagemodules.update";
public const string Delete = "zero.pagemodules.delete";
public override Task Configure(IPermissionContext context)
{
PermissionGroup group = new(Group, "@module.list");
group.Permissions.Add(new Permission("zero.pagemodules.defaults", "Default permissions")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
context.AddGroup(group);
return Task.CompletedTask;
}
}
@@ -1,38 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.PageModules;
public class PageModulesController : ZeroApiController
{
readonly IPageModuleTypeService ModuleTypeService;
public PageModulesController(IPageModuleTypeService moduleTypeService)
{
ModuleTypeService = moduleTypeService;
}
[HttpGet("")]
[ZeroAuthorize(PageModulePermissions.Read)]
public async Task<ActionResult<IList<PageModuleType>>> GetModuleTypes([FromQuery] string[] tags = default, [FromQuery] string pageId = default) => Ok(await ModuleTypeService.GetModuleTypes(tags, pageId));
[HttpGet("{alias}")]
[ZeroAuthorize(PageModulePermissions.Read)]
public ActionResult<PageModuleType> GetModuleType(string alias) => Ok(ModuleTypeService.GetModuleType(alias));
[HttpGet("{alias}/empty")]
[ZeroAuthorize(PageModulePermissions.Read)]
public ActionResult<PageModule> GetEmpty(string alias)
{
PageModule module = ModuleTypeService.GetEmpty(alias);
if (module == null)
{
return NotFound();
}
return module;
}
}
@@ -1,28 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Pages;
public class zero_Api_Pages_ChildCounts : ZeroIndex<Page, zero_Api_Pages_ChildCounts.Result>
{
public class Result : ZeroIdEntity
{
public int ChildCount { get; set; }
}
protected override void Create()
{
Map = items => items.Where(x => x.ParentId != null).Select(item => new Result
{
Id = item.ParentId,
ChildCount = 1
});
Reduce = results => results.GroupBy(x => new { x.Id }).Select(group => new Result()
{
Id = group.Key.Id,
ChildCount = group.Sum(x => x.ChildCount)
});
StoreAllFields(FieldStorage.Yes);
}
}
@@ -1,22 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Pages;
public class zero_Api_Pages_Listing : ZeroIndex<Page>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
ParentId = item.ParentId,
CreatedDate = item.CreatedDate,
Sort = item.Sort
});
Index(x => x.Name, FieldIndexing.Search);
Index(x => x.ParentId, FieldIndexing.Exact);
Index(x => x.CreatedDate, FieldIndexing.Exact);
Index(x => x.Sort, FieldIndexing.Exact);
}
}
@@ -1,10 +0,0 @@
namespace zero.Api.Endpoints.Pages;
public class PageBasic : ZeroIdEntity
{
public string ParentId { get; set; }
public string Name { get; set; }
public int Children { get; set; }
}
-13
View File
@@ -1,13 +0,0 @@
namespace zero.Api.Endpoints.Pages;
public class PageEdit : ZeroIdEntity
{
// we can't use Page as property type here
// cause that would serialize flavors to Page and remove additional properties.
// according to the System.Text.Json docs using "object" will serialize to the implementing type
public object Page { get; set; }
public FlavorConfig PageType { get; set; }
public List<string> Urls { get; set; } = new();
}
@@ -1,23 +0,0 @@
namespace zero.Api.Endpoints.Pages;
public class PageMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<Page, PageBasic>((source, ctx) => new(), Map);
// mapper.Define<CountrySave, Country>((source, ctx) => new(), Map);
}
protected virtual void Map(Page source, PageBasic target, IZeroMapperContext ctx)
{
//this.MapBasicData(source, target);
}
//protected virtual void Map(CountrySave source, Country target, IZeroMapperContext ctx)
//{
// this.MapSaveData(source, target);
// target.Code = source.Code;
// target.IsPreferred = source.IsPreferred;
//}
}
@@ -1,40 +0,0 @@
//using Microsoft.AspNetCore.Mvc;
//using System;
//using System.Collections.Generic;
//using System.Threading.Tasks;
//using zero.Core.Api;
//using zero.Core.Entities;
//using zero.Core.Utils;
//using zero.Web.Models;
//namespace zero.Web.Controllers
//{
// public class ModulesController : BackofficeController
// {
// IModulesApi Api;
// public ModulesController(IModulesApi api)
// {
// Api = api;
// }
// public async Task<IList<ModuleType>> GetModuleTypes([FromQuery] string[] tags = default, [FromQuery] string pageId = default) => await Api.GetModuleTypes(tags, pageId);
// public ModuleType GetModuleType([FromQuery] string alias) => Api.GetModuleType(alias);
// public EditModel<Module> GetEmpty(string alias)
// {
// ModuleType moduleType = Api.GetModuleType(alias);
// Module module = Activator.CreateInstance(moduleType.ContentType) as Module;
// module.ModuleTypeAlias = moduleType.Alias;
// module.Id = IdGenerator.Create(8);
// module.IsActive = true;
// return Edit(module);
// }
// }
//}
-19
View File
@@ -1,19 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Pages;
public class PageModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, PagePermissions>();
services.AddSingleton<IMapperProfile, PageMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_Pages_Listing>();
opts.Indexes.Add<zero_Api_Pages_ChildCounts>();
});
}
}
@@ -1,31 +0,0 @@
namespace zero.Api.Endpoints.Pages;
public class PagePermissions : PermissionProvider
{
public const string Group = "zero.page";
public const string Create = "zero.page.create";
public const string Read = "zero.page.read";
public const string Update = "zero.page.update";
public const string Delete = "zero.page.delete";
public override Task Configure(IPermissionContext context)
{
PermissionGroup group = new(Group, "@page.list");
group.Permissions.Add(new Permission("zero.page.defaults", "Default permissions")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
context.AddGroup(group);
return Task.CompletedTask;
}
}
-110
View File
@@ -1,110 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Pages;
public class PagesController : ZeroApiTreeEntityStoreController<Page, IPagesStore>
{
IPageTypeService PageTypeService;
IRoutes Routes;
public PagesController(IPagesStore store, IPageTypeService pageTypeService, IRoutes routes) : base(store)
{
PageTypeService = pageTypeService;
Routes = routes;
}
[HttpGet("empty")]
[ZeroAuthorize(PagePermissions.Create)]
public virtual async Task<ActionResult<object>> Empty(string flavor, string parentId = null)
{
Page page = await Store.Empty(flavor, parentId);
if (page == null)
{
return NotFound();
}
if (!await Store.IsAllowedAsChild(page, parentId))
{
return BadRequest(Result.Fail("@errors.childnotallowed"));
}
return page;
}
[HttpGet("{id}/flavors")]
[ZeroAuthorize(PagePermissions.Read)]
public async Task<ActionResult<IEnumerable<FlavorConfig>>> GetAllowedFlavors(string id) => Ok(await PageTypeService.GetAllowedTypes(NormalizeParentId(id)));
[HttpGet("{id}")]
[ZeroAuthorize(PagePermissions.Read)]
public virtual Task<ActionResult<Page>> Get(string id, string changeVector = null) => GetModel(id, changeVector);
[HttpGet("{id}/children")]
[ZeroAuthorize(PagePermissions.Read)]
public virtual async Task<ActionResult<Paged>> GetChildren(string id, [FromQuery] ListQuery<Page> query)
{
query.SearchFor(x => x.Name);
query.OrderQuery = q => q.OrderByDescending(x => x.Sort).ThenByDescending(x => x.CreatedDate);
Paged<Page> result = await Store.LoadChildren<zero_Api_Pages_Listing>(id, query.Page, query.PageSize, q => q.Filter(query));
return result;
}
[HttpGet("")]
[ZeroAuthorize(PagePermissions.Read)]
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<Page> query)
{
query.SearchFor(x => x.Name);
query.OrderQuery = q => q.OrderByDescending(x => x.Sort).ThenByDescending(x => x.CreatedDate);
return GetModelsByIndex<zero_Api_Pages_Listing>(query);
}
[HttpGet("{id}/url")]
[ZeroAuthorize(PagePermissions.Read)]
public async Task<ActionResult<UrlResult>> GetUrl(string id)
{
string url = await Routes.GetUrl<Page>(id);
return new UrlResult(ZeroContext.Application.Domains.FirstOrDefault(), url);
}
[HttpPost("")]
[ZeroAuthorize(PagePermissions.Create)]
public virtual Task<ActionResult<Result>> Create(Page saveModel) => CreateModel(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(PagePermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, Page updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(PagePermissions.Delete)]
public virtual Task<ActionResult<Result<string[]>>> Delete(string id) => DeleteModelWithDescendants(id);
[HttpPut("{id}/move/{destinationId}")]
[ZeroAuthorize(PagePermissions.Update)]
public virtual Task<ActionResult<Result>> Move(string id, string destinationId) => MoveModel(id, NormalizeParentId(destinationId));
[HttpPut("{id}/copy/{destinationId}")]
[ZeroAuthorize(PagePermissions.Update)]
public virtual Task<ActionResult<Result>> Copy(string id, string destinationId, [FromQuery] bool includeDescendants = false)
{
destinationId = NormalizeParentId(destinationId);
return includeDescendants ?
CopyModelWithDescendants(id, destinationId)
: CopyModel(id, destinationId);
}
[HttpPut("sort")]
[ZeroAuthorize(PagePermissions.Update)]
public virtual Task<ActionResult<Result>> Sort([FromBody] string[] ids) => SortModels(ids);
}
@@ -1,104 +0,0 @@
//using Microsoft.AspNetCore.Mvc;
//using Raven.Client.Documents;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading.Tasks;
//using zero.Core.Api;
//using zero.Core.Collections;
//using zero.Core.Entities;
//using zero.Core.Extensions;
//using zero.Core.Routing;
//using zero.Web.Models;
//namespace zero.Web.Controllers
//{
// public class PagesController : BackofficeCollectionController<Page, IPageService>
// {
// IRoutes Routes;
// public PagesController(IPageService collection, IRoutes routes) : base(collection)
// {
// Routes = routes;
// }
// public override async Task<EditModel<Page>> GetById([FromQuery] string id, [FromQuery] string changeVector = null)
// {
// Page entity = changeVector.IsNullOrEmpty() ? await Collection.GetById(id) : await Collection.GetRevision(changeVector);
// return entity == null ? null : Edit<Page, PageEditModel<Page>>(new PageEditModel<Page>()
// {
// Entity = entity,
// PageType = Collection.GetPageType(entity.PageTypeAlias),
// Urls = new List<string>() { await Routes.GetUrl(entity) }
// });
// }
// public override async Task<IList<PickerPreviewModel>> GetPreviews([FromQuery] List<string> ids)
// {
// IReadOnlyCollection<PageType> pageTypes = Options.Pages.GetAllItems();
// Dictionary<string, Page> pages = await Collection.GetByIds(ids.ToArray());
// Dictionary<Page, Route> routes = await Routes.GetRoutes(pages.Where(x => x.Value != null).Select(x => x.Value).ToArray());
// return Previews(pages, item =>
// {
// routes.TryGetValue(item, out Route route);
// PickerPreviewModel model = new()
// {
// Id = item.Id,
// Icon = pageTypes.FirstOrDefault(x => x.Alias == item.PageTypeAlias)?.Icon ?? "fth-folder",
// Name = item.Name,
// Text = route?.Url.Or("No URL found")
// };
// PreviewTransform?.Invoke(item, model);
// return model;
// });
// }
// public async Task<IList<TreeItem>> GetChildren([FromQuery] string parent = null, [FromQuery] string active = null, [FromQuery] string search = null)
// {
// return await Collection.GetChildren(parent, active, search);
// }
// public PageType GetPageType([FromQuery] string alias) => Collection.GetPageType(alias);
// public async Task<List<string>> GetUrls([FromQuery] string pageId)
// {
// string url = await Routes.GetUrl<Page>(pageId);
// return url.HasValue() ? new List<string>() { url } : new List<string>();
// }
// public async Task<IList<PageType>> GetAllowedPageTypes([FromQuery] string parent = null) => await Collection.GetAllowedPageTypes(parent);
// public async Task<EditModel<Page>> GetEmptyByType([FromQuery] string type, [FromQuery] string parent = null) => Edit(await Collection.GetEmpty(type, parent));
// [HttpPost]
// public async Task<Result<IList<Page>>> SaveSorting([FromBody] string[] ids) => await Collection.SaveSorting(ids);
// [HttpPost]
// public async Task<Result<Page>> Move([FromBody] ActionCopyModel model) => await Collection.Move(model.Id, model.DestinationId);
// [HttpPost]
// public async Task<Result<Page>> Copy([FromBody] ActionCopyModel model) => await Collection.Copy(model.Id, model.DestinationId, model.IncludeDescendants);
// [HttpPost]
// public async Task<Result<string[]>> Restore([FromBody] ActionCopyModel model) => await Collection.Restore(model.Id, model.IncludeDescendants);
// [HttpDelete]
// public async Task<Result<string[]>> DeleteRecursive([FromQuery] string id) => await Collection.Delete(id, recursive: true, moveToRecycleBin: true);
// }
//}
@@ -1,36 +0,0 @@
//using Microsoft.AspNetCore.Mvc;
//using System.Threading.Tasks;
//using zero.Core.Api;
//using zero.Core.Entities;
//namespace zero.Web.Controllers
//{
// public class RecycleBinController : BackofficeController
// {
// IRecycleBinApi Api;
// public RecycleBinController(IRecycleBinApi api)
// {
// Api = api;
// }
// public async Task<Paged<RecycledEntity>> GetByQuery([FromQuery] RecycleBinListQuery query)
// {
// query.IncludeInactive = true;
// return await Api.GetByQuery(query);
// }
// public async Task<int> GetCountByOperation([FromQuery] string operationId) => await Api.GetCountByOperation(operationId);
// [HttpDelete]
// public async Task<Result<RecycledEntity>> Delete([FromQuery] string id) => await Api.Delete(id);
// [HttpDelete]
// public async Task<Result<RecycledEntity>> DeleteByGroup([FromQuery] string group) => await Api.DeleteByGroup(group);
// }
//}
@@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using zero.Search;
namespace zero.Api.Endpoints.Search;
public class SearchController : ZeroApiController
{
protected ISearchService Service { get; set; }
public SearchController(ISearchService service)
{
Service = service;
}
[HttpGet("")]
public async Task<ActionResult<Paged>> Query([FromQuery] ListQuery<SearchResult> query)
{
if (!query.Search.HasValue())
{
return new Paged<SearchResult>(new List<SearchResult>(), 0, query.Page, query.PageSize);
}
return await Service.Query(query.Search, query.Page, query.PageSize);
}
}
-12
View File
@@ -1,12 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Search;
public class SearchModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, SearchPermissions>();
}
}
@@ -1,19 +0,0 @@
namespace zero.Api.Endpoints.Search;
public class SearchPermissions : PermissionProvider
{
public const string Group = "zero.search";
public const string Search = "zero.search.use";
public override Task Configure(IPermissionContext context)
{
PermissionGroup group = new(Group, "@search.permissions.search_group");
group.Permissions.Add(new Permission(Search, "@search.permissions.search"));
context.AddGroup(group);
return Task.CompletedTask;
}
}
@@ -1,19 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Spaces;
public class zero_Api_Spaces_Listing : ZeroIndex<Space>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
IsActive = item.IsActive,
Flavor = item.Flavor,
CreatedDate = item.CreatedDate
});
Index(x => x.Name, FieldIndexing.Search);
}
}
-18
View File
@@ -1,18 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Spaces;
public class SpaceModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, SpacePermissions>();
//services.AddSingleton<IMapperProfile, LanguageMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_Spaces_Listing>();
});
}
}
@@ -1,31 +0,0 @@
namespace zero.Api.Endpoints.Spaces;
public class SpacePermissions : PermissionProvider
{
public const string Group = "zero.space";
public const string Create = "zero.space.create";
public const string Read = "zero.space.read";
public const string Update = "zero.space.update";
public const string Delete = "zero.space.delete";
public override Task Configure(IPermissionContext context)
{
PermissionGroup group = new(Group, "@space.list");
group.Permissions.Add(new Permission("zero.space.defaults", "Default permissions")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
context.AddGroup(group);
return Task.CompletedTask;
}
}
@@ -1,72 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections;
namespace zero.Api.Endpoints.Spaces;
public class SpacesController : ZeroApiEntityStoreController<Space, ISpaceStore>
{
ISpaceTypeService SpaceTypes;
public SpacesController(ISpaceStore store, ISpaceTypeService spaceTypes) : base(store)
{
SpaceTypes = spaceTypes;
}
[HttpGet("types")]
[ZeroAuthorize(SpacePermissions.Read)]
public virtual ActionResult<IEnumerable> GetTypes() => Ok(SpaceTypes.GetAll());
[HttpGet("types/{alias}")]
[ZeroAuthorize(SpacePermissions.Read)]
public virtual ActionResult<SpaceType> GetType(string alias) => Ok(SpaceTypes.GetByAlias(alias));
[HttpGet("{alias}")]
[ZeroAuthorize(SpacePermissions.Read)]
public virtual async Task<ActionResult<object>> Get(string alias, [FromQuery] ListQuery<Space> query = null)
{
SpaceType space = SpaceTypes.GetByAlias(alias);
if (space == null)
{
return NotFound();
}
if (space.View != SpaceView.Editor)
{
query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate);
query.SearchSelector ??= x => x.Name;
Paged<Space> result = await Store.Load<zero_Api_Spaces_Listing>(query.Page, query.PageSize, q => q.Where(x => x.Flavor == alias).Filter(query));
return result;
}
var stream = Store.Stream(q => q.Where(x => x.Flavor == alias));
Space item = (await stream.FirstOrDefaultAsync()) ?? (await Store.Empty<Space>(alias));
return item;
}
[HttpGet("{alias}/empty")]
[ZeroAuthorize(SpacePermissions.Create)]
public virtual Task<ActionResult<Space>> Empty(string alias) => EmptyModel(alias);
[HttpGet("{alias}/{id}")]
[ZeroAuthorize(SpacePermissions.Read)]
public virtual Task<ActionResult<Space>> Get(string alias, string id, string changeVector = null) => GetModel(id, changeVector);
[HttpPost("")]
[ZeroAuthorize(SpacePermissions.Create)]
public virtual Task<ActionResult<Result>> Create([FromBody] Space saveModel) => CreateModel(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(SpacePermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, [FromBody] Space updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(SpacePermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
}
@@ -1,21 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Translations;
public class zero_Api_Translations_Listing : ZeroIndex<Translation>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
Value = item.Value,
Key = item.Key,
CreatedDate = item.CreatedDate
});
Index(x => x.Name, FieldIndexing.Search);
Index(x => x.Key, FieldIndexing.Search);
Index(x => x.Value, FieldIndexing.Search);
}
}
@@ -1,14 +0,0 @@
namespace zero.Api.Endpoints.Translations;
public class TranslationBasic : ZeroIdEntity
{
public string Key { get; set; }
public DateTimeOffset CreatedDate { get; set; }
public string Flavor { get; set; }
public string Value { get; set; }
public TranslationDisplay Display { get; set; }
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Translations;
public class TranslationEdit : DisplayModel<Translation>
{
public string Value { get; set; }
public TranslationDisplay Display { get; set; }
}
@@ -1,36 +0,0 @@
namespace zero.Api.Endpoints.Translations;
public class TranslationMapperProfile : ZeroMapperProfile
{
public override void Configure(IZeroMapper mapper)
{
mapper.Define<Translation, TranslationBasic>((source, ctx) => new(), Map);
mapper.Define<Translation, TranslationEdit>((source, ctx) => new(), Map);
mapper.Define<TranslationSave, Translation>((source, ctx) => new(), Map);
}
protected virtual void Map(Translation source, TranslationBasic target, IZeroMapperContext ctx)
{
target.Id = source.Id;
target.Key = source.Key;
target.Flavor = source.Flavor;
target.CreatedDate = source.CreatedDate;
target.Value = source.Value;
target.Display = source.Display;
}
protected virtual void Map(Translation source, TranslationEdit target, IZeroMapperContext ctx)
{
this.MapDisplayData(source, target);
target.Value = source.Value;
target.Display = source.Display;
}
protected virtual void Map(TranslationSave source, Translation target, IZeroMapperContext ctx)
{
this.MapSaveData(source, target);
target.Value = source.Value;
target.Display = source.Display;
}
}
@@ -1,8 +0,0 @@
namespace zero.Api.Endpoints.Translations;
public class TranslationSave : SaveModel<Translation>
{
public string Value { get; set; }
public TranslationDisplay Display { get; set; }
}
@@ -1,18 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace zero.Api.Endpoints.Translations;
public class TranslationModule : ZeroModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IPermissionProvider, TranslationPermissions>();
services.AddSingleton<IMapperProfile, TranslationMapperProfile>();
services.Configure<RavenOptions>(opts =>
{
opts.Indexes.Add<zero_Api_Translations_Listing>();
});
}
}
@@ -1,29 +0,0 @@
namespace zero.Api.Endpoints.Translations;
public class TranslationPermissions : PermissionProvider
{
public const string Create = "zero.settings.translation.create";
public const string Read = "zero.settings.translation.read";
public const string Update = "zero.settings.translation.update";
public const string Delete = "zero.settings.translation.delete";
public override Task Configure(IPermissionContext context)
{
if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group))
{
group.Permissions.Add(new Permission("zero.settings.translation", "@settings.application.translations.name")
{
Children = new()
{
new(Create, "@permission.states.create"),
new(Read, "@permission.states.read"),
new(Update, "@permission.states.update"),
new(Delete, "@permission.states.delete")
}
});
}
return Task.CompletedTask;
}
}
@@ -1,45 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace zero.Api.Endpoints.Translations;
public class TranslationsController : ZeroApiEntityStoreController<Translation, ITranslationStore>
{
public TranslationsController(ITranslationStore store) : base(store)
{
}
[HttpGet("empty")]
[ZeroAuthorize(TranslationPermissions.Create)]
public virtual Task<ActionResult<Translation>> Empty(string flavor = null) => EmptyModel(flavor);
[HttpGet("{id}")]
[ZeroAuthorize(TranslationPermissions.Read)]
public virtual Task<ActionResult<Translation>> Get(string id, string changeVector = null) => GetModel(id, changeVector);
[HttpGet("")]
[ZeroAuthorize(TranslationPermissions.Read)]
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<Translation> query)
{
query.SearchFor(x => x.Key, x => x.Value);
return GetModelsByIndex<TranslationBasic, zero_Api_Translations_Listing>(query);
}
[HttpPost("")]
[ZeroAuthorize(TranslationPermissions.Create)]
public virtual Task<ActionResult<Result>> Create(Translation saveModel) => CreateModel(saveModel);
[HttpPut("{id}")]
[ZeroAuthorize(TranslationPermissions.Update)]
public virtual Task<ActionResult<Result>> Update(string id, Translation updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken);
[HttpDelete("{id}")]
[ZeroAuthorize(TranslationPermissions.Delete)]
public virtual Task<ActionResult<Result>> Delete(string id) => DeleteModel(id);
}
@@ -1,17 +0,0 @@
using Raven.Client.Documents.Indexes;
namespace zero.Api.Endpoints.Users;
public class zero_Api_Users_Listing : ZeroIndex<ZeroUser>
{
protected override void Create()
{
Map = items => items.Select(item => new
{
Name = item.Name,
CreatedDate = item.CreatedDate
});
Index(x => x.Name, FieldIndexing.Search);
}
}
@@ -1,12 +0,0 @@
namespace zero.Api.Endpoints.Users;
public class UserBasic : ZeroIdEntity
{
public string Name { get; set; }
public bool IsActive { get; set; }
public string Email { get; set; }
public string AvatarId { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More