Skip to content

Commit

Permalink
Read only mode for rule events.
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianStehle committed Jun 28, 2022
1 parent 2115b00 commit c0965bf
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 33 deletions.
4 changes: 4 additions & 0 deletions backend/src/Squidex.Shared/Permissions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ public static class Permissions
public const string AppRules = "squidex.apps.{app}.rules";
public const string AppRulesRead = "squidex.apps.{app}.rules.read";
public const string AppRulesEvents = "squidex.apps.{app}.rules.events";
public const string AppRulesEventsRun = "squidex.apps.{app}.rules.events.run";
public const string AppRulesEventsRead = "squidex.apps.{app}.rules.events.read";
public const string AppRulesEventsUpdate = "squidex.apps.{app}.rules.events.update";
public const string AppRulesEventsDelete = "squidex.apps.{app}.rules.events.delete";
public const string AppRulesCreate = "squidex.apps.{app}.rules.create";
public const string AppRulesUpdate = "squidex.apps.{app}.rules.update";
public const string AppRulesDisable = "squidex.apps.{app}.rules.disable";
Expand Down
11 changes: 10 additions & 1 deletion backend/src/Squidex.Web/Resources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,16 @@ public sealed class Resources
public bool CanDeleteRule => IsAllowed(Permissions.AppRulesDelete);

[Lazy]
public bool CanReadRuleEvents => IsAllowed(Permissions.AppRulesEvents);
public bool CanReadRuleEvents => IsAllowed(Permissions.AppRulesEventsRead);

[Lazy]
public bool CanUpdateRuleEvents => IsAllowed(Permissions.AppRulesEventsUpdate);

[Lazy]
public bool CanRunRuleEvents => IsAllowed(Permissions.AppRulesEventsRun);

[Lazy]
public bool CanDeleteRuleEvents => IsAllowed(Permissions.AppRulesEventsDelete);

// Users
[Lazy]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private RuleDto CreateLinks(Resources resources, IEnrichedRuleEntity rule, bool
AddPutLink("update", resources.Url<RulesController>(x => nameof(x.PutRule), values));
}

if (resources.CanReadRuleEvents)
if (resources.CanRunRuleEvents)
{
AddPutLink("trigger", resources.Url<RulesController>(x => nameof(x.TriggerRule), values));

Expand All @@ -141,7 +141,10 @@ private RuleDto CreateLinks(Resources resources, IEnrichedRuleEntity rule, bool

AddPutLink("run/snapshots", resources.Url<RulesController>(x => nameof(x.PutRuleRun), snaphshotValues));
}
}

if (resources.CanReadRuleEvents)
{
AddGetLink("logs", resources.Url<RulesController>(x => nameof(x.GetEvents), values));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,12 @@ private RuleEventDto CreateLinks(Resources resources)
{
var values = new { app = resources.App, id = Id };

AddPutLink("update", resources.Url<RulesController>(x => nameof(x.PutEvent), values));
if (resources.CanUpdateRuleEvents)
{
AddPutLink("update", resources.Url<RulesController>(x => nameof(x.PutEvent), values));
}

if (NextAttempt != null)
if (resources.CanDeleteRuleEvents && NextAttempt != null)
{
AddDeleteLink("cancel", resources.Url<RulesController>(x => nameof(x.DeleteEvent), values));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ private RuleEventsDto CreateLinks(Resources resources, DomainId? ruleId)

AddSelfLink(resources.Url<RulesController>(x => nameof(x.GetEvents), values));

if (ruleId != null)
if (resources.CanDeleteRuleEvents)
{
var routeValeus = new { values.app, id = ruleId };

AddDeleteLink("cancel", resources.Url<RulesController>(x => nameof(x.DeleteRuleEvents), routeValeus));
}
else
{
AddDeleteLink("cancel", resources.Url<RulesController>(x => nameof(x.DeleteEvents), values));
if (ruleId != null)
{
var routeValues = new { values.app, id = ruleId };

AddDeleteLink("cancel", resources.Url<RulesController>(x => nameof(x.DeleteRuleEvents), routeValues));
}
else
{
AddDeleteLink("cancel", resources.Url<RulesController>(x => nameof(x.DeleteEvents), values));
}
}

return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ private RulesDto CreateLinks(Resources resources, DomainId? runningRuleId)
if (resources.CanReadRuleEvents)
{
AddGetLink("events", resources.Url<RulesController>(x => nameof(x.GetEvents), values));
}

if (runningRuleId != null)
{
AddDeleteLink("run/cancel", resources.Url<RulesController>(x => nameof(x.DeleteRuleRun), values));
}
if (resources.CanDeleteRuleEvents && runningRuleId != null)
{
AddDeleteLink("run/cancel", resources.Url<RulesController>(x => nameof(x.DeleteRuleRun), values));
}

return this;
Expand Down
20 changes: 10 additions & 10 deletions backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public async Task<IActionResult> PostRule(string app, [FromBody] CreateRuleDto r
[HttpDelete]
[Route("apps/{app}/rules/run")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsUpdate)]
[ApiCosts(1)]
public async Task<IActionResult> DeleteRuleRun(string app)
{
Expand Down Expand Up @@ -231,7 +231,7 @@ public async Task<IActionResult> DisableRule(string app, DomainId id)
/// </returns>
[HttpPut]
[Route("apps/{app}/rules/{id}/trigger/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRun)]
[ApiCosts(1)]
public async Task<IActionResult> TriggerRule(string app, DomainId id)
{
Expand All @@ -254,7 +254,7 @@ public async Task<IActionResult> TriggerRule(string app, DomainId id)
[HttpPut]
[Route("apps/{app}/rules/{id}/run")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRun)]
[ApiCosts(1)]
public async Task<IActionResult> PutRuleRun(string app, DomainId id, [FromQuery] bool fromSnapshots = false)
{
Expand All @@ -274,7 +274,7 @@ public async Task<IActionResult> PutRuleRun(string app, DomainId id, [FromQuery]
[HttpDelete]
[Route("apps/{app}/rules/{id}/events/")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsDelete)]
[ApiCosts(1)]
public async Task<IActionResult> DeleteRuleEvents(string app, DomainId id)
{
Expand All @@ -295,7 +295,7 @@ public async Task<IActionResult> DeleteRuleEvents(string app, DomainId id)
[HttpPost]
[Route("apps/{app}/rules/simulate/")]
[ProducesResponseType(typeof(SimulatedRuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRead)]
[ApiCosts(5)]
public async Task<IActionResult> Simulate(string app, [FromBody] CreateRuleDto request)
{
Expand All @@ -320,7 +320,7 @@ public async Task<IActionResult> Simulate(string app, [FromBody] CreateRuleDto r
[HttpGet]
[Route("apps/{app}/rules/{id}/simulate/")]
[ProducesResponseType(typeof(SimulatedRuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRead)]
[ApiCosts(5)]
public async Task<IActionResult> Simulate(string app, DomainId id)
{
Expand Down Expand Up @@ -372,7 +372,7 @@ public async Task<IActionResult> DeleteRule(string app, DomainId id)
[HttpGet]
[Route("apps/{app}/rules/events/")]
[ProducesResponseType(typeof(RuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesRead)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRead)]
[ApiCosts(0)]
public async Task<IActionResult> GetEvents(string app, [FromQuery] DomainId? ruleId = null, [FromQuery] int skip = 0, [FromQuery] int take = 20)
{
Expand All @@ -394,7 +394,7 @@ public async Task<IActionResult> GetEvents(string app, [FromQuery] DomainId? rul
/// </returns>
[HttpPut]
[Route("apps/{app}/rules/events/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsUpdate)]
[ApiCosts(0)]
public async Task<IActionResult> PutEvent(string app, DomainId id)
{
Expand All @@ -420,7 +420,7 @@ public async Task<IActionResult> PutEvent(string app, DomainId id)
[HttpDelete]
[Route("apps/{app}/rules/events/")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsDelete)]
[ApiCosts(1)]
public async Task<IActionResult> DeleteEvents(string app)
{
Expand All @@ -440,7 +440,7 @@ public async Task<IActionResult> DeleteEvents(string app)
/// </returns>
[HttpDelete]
[Route("apps/{app}/rules/events/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsDelete)]
[ApiCosts(0)]
public async Task<IActionResult> DeleteEvent(string app, DomainId id)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ <h4>{{ 'rules.ruleEvents.lastInvokedLabel' | sqxTranslate }}</h4>
{{ 'rules.ruleEvents.nextAttemptLabel' | sqxTranslate }}: <ng-container *ngIf="event.nextAttempt">{{event.nextAttempt | sqxFromNow}}</ng-container>
</div>
<div class="col-3 text-end">
<button type="button" class="btn btn-danger me-1" [class.hidden]="!event.nextAttempt"
<button type="button" class="btn btn-danger me-1" *ngIf="event.canDelete"
(sqxConfirmClick)="cancel.emit()"
confirmTitle="i18n:rules.ruleEvents.cancelConfirmTitle"
confirmText="i18n:rules.ruleEvents.cancelConfirmText"
confirmRememberKey="cancelRuleEvent">
{{ 'common.cancel' | sqxTranslate }}
</button>

<button type="button" class="btn btn-success" (click)="enqueue.emit()">
<button type="button" class="btn btn-success" (click)="enqueue.emit()" *ngIf="event.canUpdate">
{{ 'rules.ruleEvents.enqueue' | sqxTranslate }}
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ td {
&-stats {
font-size: $font-smallest;
font-weight: normal;
height: 4rem;
}

&-header {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[isRequired]="false">
</sqx-editable-title>
</div>
<div class="col-auto" *ngIf="rule.canDelete || rule.canRun">
<div class="col-auto" [class.invisible]="!rule.canDelete && !rule.canRun">
<button type="button" class="btn btn-text-secondary" (click)="dropdown.toggle()" #buttonOptions>
<i class="icon-dots"></i>
</button>
Expand Down Expand Up @@ -109,8 +109,8 @@ <h3>{{ 'rules.ruleSyntax.then' | sqxTranslate }}</h3>
<div class="col">
{{ 'common.lastExecuted' | sqxTranslate }}: <span>{{rule.lastExecuted | sqxFromNow:'-'}}</span>
</div>
<div class="col-auto">
<a routerLink="events" [queryParams]="{ ruleId: rule.id }" *ngIf="rule.canTrigger">
<div class="col-auto" *ngIf="rule.canReadLogs">
<a routerLink="events" [queryParams]="{ ruleId: rule.id }">
{{ 'common.logs' | sqxTranslate }}
</a>

Expand Down
6 changes: 4 additions & 2 deletions frontend/src/app/shared/services/rules.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export class RuleDto {
public readonly canDelete: boolean;
public readonly canDisable: boolean;
public readonly canEnable: boolean;
public readonly canReadLogs: boolean;
public readonly canRun: boolean;
public readonly canRunFromSnapshots: boolean;
public readonly canTrigger: boolean;
Expand Down Expand Up @@ -155,9 +156,10 @@ export class RuleDto {
this.canDelete = hasAnyLink(links, 'delete');
this.canDisable = hasAnyLink(links, 'disable');
this.canEnable = hasAnyLink(links, 'enable');
this.canReadLogs = hasAnyLink(links, 'logs');
this.canRun = hasAnyLink(links, 'run');
this.canRunFromSnapshots = hasAnyLink(links, 'run/snapshots');
this.canTrigger = hasAnyLink(links, 'logs');
this.canTrigger = hasAnyLink(links, 'trigger');
this.canUpdate = hasAnyLink(links, 'update');
}
}
Expand Down Expand Up @@ -186,7 +188,7 @@ export class RuleEventDto extends Model<RuleEventDto> {

this._links = links;

this.canDelete = hasAnyLink(links, 'delete');
this.canDelete = hasAnyLink(links, 'cancel');
this.canUpdate = hasAnyLink(links, 'update');
}
}
Expand Down

0 comments on commit c0965bf

Please sign in to comment.