Browse Source

Closes #54 Back-Navigation does not work correctly in Web Frontend.

Closes #53 Editors and Developers have wrong security level.
pull/65/head
Sebastian Stehle 9 years ago
parent
commit
5a05123daa
  1. 4
      src/Squidex.Write/Schemas/Commands/AddField.cs
  2. 3
      src/Squidex/Controllers/Api/History/HistoryController.cs
  3. 8
      src/Squidex/Controllers/Api/Schemas/SchemasController.cs
  4. 5
      src/Squidex/Controllers/Api/Statistics/UsagesController.cs
  5. 4
      src/Squidex/Pipeline/AppApiFilter.cs
  6. 2
      src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.html
  7. 2
      src/Squidex/app/features/administration/pages/users/users-page.component.html
  8. 2
      src/Squidex/app/features/assets/pages/assets-page.component.html
  9. 13
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  10. 10
      src/Squidex/app/features/content/pages/contents/content-item.component.ts
  11. 2
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  12. 7
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  13. 2
      src/Squidex/app/features/content/pages/schemas/schemas-page.component.html
  14. 2
      src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html
  15. 2
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts
  16. 2
      src/Squidex/app/features/settings/settings-area.component.html
  17. 9
      src/Squidex/app/framework/angular/parent-link.directive.ts
  18. 6
      src/Squidex/app/shared/services/auth.service.ts

4
src/Squidex.Write/Schemas/Commands/AddField.cs

@ -25,12 +25,12 @@ namespace Squidex.Write.Schemas.Commands
{
if (!Partitioning.IsValidPartitioning())
{
errors.Add(new ValidationError($"Partitioning is not valid.", nameof(Partitioning)));
errors.Add(new ValidationError("Partitioning is not valid.", nameof(Partitioning)));
}
if (!Name.IsPropertyName())
{
errors.Add(new ValidationError("Name must be a valid property name", nameof(Name)));
errors.Add(new ValidationError("Name must be a valid property name.", nameof(Name)));
}
if (Properties == null)

3
src/Squidex/Controllers/Api/History/HistoryController.cs

@ -15,7 +15,6 @@ using Squidex.Controllers.Api.History.Models;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Reflection;
using Squidex.Pipeline;
using Squidex.Read.Apps.Services;
using Squidex.Read.History.Repositories;
namespace Squidex.Controllers.Api.History
@ -23,7 +22,7 @@ namespace Squidex.Controllers.Api.History
/// <summary>
/// Readonly API to get an event stream.
/// </summary>
[Authorize]
[MustBeAppEditor]
[ApiExceptionFilter]
[AppApi]
[SwaggerTag("History")]

8
src/Squidex/Controllers/Api/Schemas/SchemasController.cs

@ -25,7 +25,6 @@ namespace Squidex.Controllers.Api.Schemas
/// <summary>
/// Manages and retrieves information about schemas.
/// </summary>
[MustBeAppDeveloper]
[ApiExceptionFilter]
[AppApi]
[SwaggerTag("Schemas")]
@ -47,6 +46,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 200 => Schemas returned.
/// 404 => App not found.
/// </returns>
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/schemas/")]
[ProducesResponseType(typeof(SchemaDto[]), 200)]
@ -69,6 +69,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 200 => Schema found.
/// 404 => Schema or app not found.
/// </returns>
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/schemas/{name}/")]
[ProducesResponseType(typeof(SchemaDetailsDto[]), 200)]
@ -99,6 +100,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 400 => Schema name or properties are not valid.
/// 409 => Schema name already in use.
/// </returns>
[MustBeAppDeveloper]
[HttpPost]
[Route("apps/{app}/schemas/")]
[ProducesResponseType(typeof(EntityCreatedDto), 201)]
@ -125,6 +127,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 400 => Schema properties are not valid.
/// 404 => Schema or app not found.
/// </returns>
[MustBeAppDeveloper]
[HttpPut]
[Route("apps/{app}/schemas/{name}/")]
[ApiCosts(1)]
@ -147,6 +150,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 400 => Schema is already published.
/// 404 => Schema or app not found.
/// </returns>
[MustBeAppDeveloper]
[HttpPut]
[Route("apps/{app}/schemas/{name}/publish")]
[ProducesResponseType(typeof(ErrorDto), 400)]
@ -168,6 +172,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 400 => Schema is not published.
/// 404 => Schema or app not found.
/// </returns>
[MustBeAppDeveloper]
[HttpPut]
[Route("apps/{app}/schemas/{name}/unpublish")]
[ProducesResponseType(typeof(ErrorDto), 400)]
@ -188,6 +193,7 @@ namespace Squidex.Controllers.Api.Schemas
/// 204 => Schema has been deleted.
/// 404 => Schema or app not found.
/// </returns>
[MustBeAppDeveloper]
[HttpDelete]
[Route("apps/{app}/schemas/{name}/")]
[ApiCosts(1)]

5
src/Squidex/Controllers/Api/Statistics/UsagesController.cs

@ -23,6 +23,7 @@ namespace Squidex.Controllers.Api.Statistics
/// <summary>
/// Retrieves usage information for apps.
/// </summary>
[MustBeAppEditor]
[ApiExceptionFilter]
[AppApi]
[SwaggerTag("Statistics")]
@ -53,7 +54,6 @@ namespace Squidex.Controllers.Api.Statistics
/// 200 => Usage tracking results returned.
/// 404 => App not found.
/// </returns>
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/usages/calls/month")]
[ProducesResponseType(typeof(CurrentCallsDto), 200)]
@ -78,7 +78,6 @@ namespace Squidex.Controllers.Api.Statistics
/// 404 => App not found.
/// 400 => Range between from date and to date is not valid or has more than 100 days.
/// </returns>
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/usages/calls/{fromDate}/{toDate}")]
[ProducesResponseType(typeof(CallsUsageDto[]), 200)]
@ -110,7 +109,6 @@ namespace Squidex.Controllers.Api.Statistics
/// 200 => Storage usage returned.
/// 404 => App not found.
/// </returns>
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/usages/storage/today")]
[ProducesResponseType(typeof(CurrentStorageDto), 200)]
@ -135,7 +133,6 @@ namespace Squidex.Controllers.Api.Statistics
/// 404 => App not found.
/// 400 => Range between from date and to date is not valid or has more than 100 days.
/// </returns>
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/usages/storage/{fromDate}/{toDate}")]
[ProducesResponseType(typeof(StorageUsageDto[]), 200)]

4
src/Squidex/Pipeline/AppApiFilter.cs

@ -82,11 +82,11 @@ namespace Squidex.Pipeline
defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppDeveloper));
defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppEditor));
break;
case PermissionLevel.Editor:
case PermissionLevel.Developer:
defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppDeveloper));
defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppEditor));
break;
case PermissionLevel.Developer:
case PermissionLevel.Editor:
defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppEditor));
break;
}

2
src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.html

@ -6,7 +6,7 @@
<h3 class="panel-title">Event Consumers</h3>
</div>
<a class="panel-close" routerLink="['..']">
<a class="panel-close" sqxParentLink isLazyLoaded="true">
<i class="icon-close"></i>
</a>
</div>

2
src/Squidex/app/features/administration/pages/users/users-page.component.html

@ -18,7 +18,7 @@
<h3 class="panel-title">Users</h3>
</div>
<a class="panel-close" sqxParentLink>
<a class="panel-close" sqxParentLink isLazyLoaded="true">
<i class="icon-close"></i>
</a>
</div>

2
src/Squidex/app/features/assets/pages/assets-page.component.html

@ -18,7 +18,7 @@
<h3 class="panel-title">Assets</h3>
</div>
<a class="panel-close" sqxParentLink>
<a class="panel-close" sqxParentLink isLazyLoaded="true">
<i class="icon-close"></i>
</a>
</div>

13
src/Squidex/app/features/content/pages/content/content-page.component.ts

@ -6,7 +6,6 @@
*/
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { AbstractControl, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subject, Subscription } from 'rxjs';
@ -62,7 +61,6 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
constructor(apps: AppsStoreService, notifications: NotificationService,
private readonly contentsService: ContentsService,
private readonly location: Location,
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly messageBus: MessageBus
@ -151,10 +149,8 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
this.messageBus.publish(new ContentCreated(created.id, created.data, this.version.value, publish));
this.finishCreation();
this.notifyInfo('Content created successfully.');
this.enable();
this.finish();
}, error => {
this.notifyError(error);
this.enable();
@ -177,11 +173,8 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
}
}
private finishCreation() {
const newUrl = this.router.createUrlTree(['../', this.contentId], { relativeTo: this.route, replaceUrl: true });
this.location.replaceState(newUrl.toString());
this.isNewMode = false;
private finish() {
this.router.navigate(['../'], { relativeTo: this.route, replaceUrl: true });
}
private enable() {

10
src/Squidex/app/features/content/pages/contents/content-item.component.ts

@ -93,12 +93,18 @@ export class ContentItemComponent extends AppComponentBase implements OnInit, On
if (value) {
if (properties.fieldType === 'Json') {
value = 'Json';
value = '<Json />';
} else if (properties.fieldType === 'Geolocation') {
value = `${value.longitude}, ${value.latitude}`;
} else if (properties.fieldType === 'Boolean') {
value = value ? '✔' : '-';
} else if (properties.fieldType === 'DateTime') {
}else if (properties.fieldType === 'Assets') {
try {
value = `${value.length} Assets`;
} catch (ex) {
value = '0 Assets';
}
} else if (properties.fieldType === 'DateTime') {
try {
const parsed = DateTime.parseISO_UTC(value);

2
src/Squidex/app/features/content/pages/contents/contents-page.component.html

@ -18,7 +18,7 @@
<sqx-language-selector class="languages-buttons" (selectedLanguageChanged)="selectLanguage($event)" [languages]="languages"></sqx-language-selector>
</span>
<button class="btn btn-success" [routerLink]="['new']">
<button class="btn btn-success" (click)="gotoNew()">
<i class="icon-plus"></i> New
</button>
</div>

7
src/Squidex/app/features/content/pages/contents/contents-page.component.ts

@ -7,7 +7,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import {
@ -59,6 +59,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
private readonly authService: AuthService,
private readonly contentsService: ContentsService,
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly messageBus: MessageBus
) {
super(notifications, apps);
@ -187,6 +188,10 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.load();
}
public gotoNew() {
this.router.navigate(['./new'], { relativeTo: this.route });
}
private updateContents(id: string, p: boolean | undefined, data: any, version: string) {
this.contentItems = this.contentItems.replaceAll(x => x.id === id, c => this.updateContent(c, p === undefined ? c.isPublished : p, data, version));
}

2
src/Squidex/app/features/content/pages/schemas/schemas-page.component.html

@ -6,7 +6,7 @@
<h3 class="panel-title">Schemas</h3>
</div>
<a class="panel-close" sqxParentLink>
<a class="panel-close" sqxParentLink isLazyLoaded="true">
<i class="icon-close"></i>
</a>

2
src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html

@ -6,7 +6,7 @@
<h3 class="panel-title">Schemas</h3>
</div>
<a class="panel-close" sqxParentLink>
<a class="panel-close" sqxParentLink isLazyLoaded="true">
<i class="icon-close"></i>
</a>

2
src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts

@ -74,7 +74,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni
];
public get canAddContributor() {
return this.addContributorForm.valid && (this.maxContributors < -1 || this.appContributors.length < this.maxContributors);
return this.addContributorForm.valid && (this.maxContributors <= -1 || this.appContributors.length < this.maxContributors);
}
public addContributorForm: FormGroup =

2
src/Squidex/app/features/settings/settings-area.component.html

@ -6,7 +6,7 @@
<h3 class="panel-title">Settings</h3>
</div>
<a class="panel-close" sqxParentLink>
<a class="panel-close" sqxParentLink isLazyLoaded="true">
<i class="icon-close"></i>
</a>
</div>

9
src/Squidex/app/framework/angular/parent-link.directive.ts

@ -5,7 +5,7 @@
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Directive, ElementRef, HostListener, OnDestroy, OnInit, Renderer } from '@angular/core';
import { Directive, ElementRef, HostListener, Input, OnDestroy, OnInit, Renderer } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
@ -16,6 +16,9 @@ export class ParentLinkDirective implements OnInit, OnDestroy {
private urlSubscription: Subscription;
private url: string;
@Input()
public isLazyLoaded = false;
constructor(
private readonly router: Router,
private readonly route: ActivatedRoute,
@ -31,7 +34,9 @@ export class ParentLinkDirective implements OnInit, OnDestroy {
public ngOnInit() {
this.urlSubscription =
this.route.url.subscribe(() => {
this.url = this.router.createUrlTree(['.'], { relativeTo: this.route.parent.parent }).toString();
this.url = this.isLazyLoaded ?
this.router.createUrlTree(['.'], { relativeTo: this.route.parent.parent }).toString() :
this.router.createUrlTree(['.'], { relativeTo: this.route.parent }).toString();
this.renderer.setElementAttribute(this.element.nativeElement, 'href', this.url);
});

6
src/Squidex/app/shared/services/auth.service.ts

@ -203,16 +203,14 @@ export class AuthService {
}
})
.catch((error: Response) => {
if (error.status >= 401 && error.status <= 404 && (!this.user || this.user.user.expired)) {
if (error.status === 404 && (!this.user || this.user.user.expired)) {
this.logoutRedirect();
return Observable.empty<Response>();
} else if (error.status === 401) {
} else if (error.status === 401 || error.status === 403) {
this.logoutRedirect();
return Observable.empty<Response>();
} else if (error.status === 403) {
error.status = 404;
}
return Observable.throw(error);
});

Loading…
Cancel
Save