Skip to content

Commit

Permalink
Merged in feature/SHIBUI-1382 (pull request #359)
Browse files Browse the repository at this point in the history
SHIBUI-1382 Implementation for restore page

Approved-by: Dmitriy Kopylenko <dkopylenko@unicon.net>
  • Loading branch information
rmathis committed Aug 30, 2019
2 parents 93bb031 + 483a446 commit 6e2baee
Show file tree
Hide file tree
Showing 25 changed files with 430 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package edu.internet2.tier.shibboleth.admin.ui.controller

import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor
import edu.internet2.tier.shibboleth.admin.ui.domain.Organization
import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationDisplayName
import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationName
import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationURL
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation
import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
import org.springframework.http.MediaType
import org.springframework.test.annotation.DirtiesContext
import org.springframework.test.context.ActiveProfiles
import spock.lang.Specification

Expand Down Expand Up @@ -100,6 +111,46 @@ class EntityDescriptorControllerVersionEndpointsIntegrationTests extends Specifi
edv2.body.serviceProviderName == 'SP2'
}

@DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
def 'SHIBUI-1414'() {
given:
def ed = new EntityDescriptor(entityID: 'testme', serviceProviderName: 'testme').with {
entityDescriptorRepository.save(it)
}.with {
it.setOrganization(new Organization().with {
it.organizationNames = [new OrganizationName(value: 'testme', XMLLang: 'en')]
it.organizationDisplayNames = [new OrganizationDisplayName(value: 'testme', XMLLang: 'en')]
it.organizationURLs = [new OrganizationURL(value: 'http://testme.org', XMLLang: 'en')]
it
})
entityDescriptorRepository.save(it)
}

when:
def headers = new HttpHeaders().with {
it.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
it
}

def allVersions = getAllEntityDescriptorVersions(ed.resourceId, List)
def edv1 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[0].id, String).body
def tedv2 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[1].id, EntityDescriptorRepresentation).body

def aedv1 = new JsonSlurper().parseText(edv1).with {
it.put('version', tedv2.version)
it
}.with {
JsonOutput.toJson(it)
}

def request = new HttpEntity(aedv1, headers)
def response = this.restTemplate.exchange("/api/EntityDescriptor/${ed.resourceId}", HttpMethod.PUT, request, String)

then:
response.statusCodeValue != 400
noExceptionThrown()
}

private getAllEntityDescriptorVersions(String resourceId, responseType) {
this.restTemplate.getForEntity(resourceUriFor(ALL_VERSIONS_URI, resourceId), responseType)
}
Expand Down
1 change: 1 addition & 0 deletions backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true

# spring.jackson.default-property-inclusion=non_absent
spring.jackson.default-property-inclusion=NON_NULL

# Database Configuration PostgreSQL
#spring.datasource.url=jdbc:postgresql://localhost:5432/shibui
Expand Down
5 changes: 5 additions & 0 deletions backend/src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ action.xml=XML
action.manage=Manage
action.close=Close
action.back-to-top=Back to Top
action.restore=Restore

value.enabled=Enabled
value.disabled=Disabled
Expand Down Expand Up @@ -416,6 +417,7 @@ label.check-to-select=Check to select
label.current=Current
label.restore=Restore
label.compare-selected=Compare Selected
label.restore-version=Restore Version ({ date })

label.saved=Saved
label.by=By
Expand Down Expand Up @@ -471,6 +473,9 @@ message.database-constraint=There was a database constraint problem processing t
message.no-filters=No Filters
message.no-filters-added=No filters have been added to this Metadata Provider

message.create-new-version-from-version=Create New Version from Previous Settings
message.restoring-this-version-will-copy=Restoring this version will copy the Version ({ date }) configuration and create a new Version from the selected version settings. You can then edit the configuration before saving the new version.

tooltip.entity-id=Entity ID
tooltip.service-provider-name=Service Provider Name (Dashboard Display Only)
tooltip.force-authn=Disallows use (or reuse) of authentication results and login flows that don\u0027t provide a real-time proof of user presence in the login process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Profile
import org.springframework.core.io.ResourceLoader
import org.springframework.test.context.ActiveProfiles
import spock.lang.Specification
Expand All @@ -23,7 +24,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResour
* @author Dmitriy Kopylenko
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("no-auth")
@ActiveProfiles(["no-auth", "badjson"])
class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Specification {

@Autowired
Expand All @@ -42,6 +43,7 @@ class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Speci
}

@TestConfiguration
@Profile('badjson')
static class Config {
@Bean
JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,16 @@ class EntitiesControllerIntegrationTests extends Specification {
def "GET /api/entities returns the proper json"() {
given:
def expectedBody = '''
{
"id":null,
"serviceProviderName":null,
"entityId":"http://test.scaldingspoon.org/test1",
"organization":null,
"contacts":null,
"mdui":null,
{
"entityId":"http://test.scaldingspoon.org/test1",
"serviceProviderSsoDescriptor": {
"protocolSupportEnum":"SAML 2",
"nameIdFormats":["urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"]
},
"logoutEndpoints":null,
"securityInfo":null,
},
"assertionConsumerServices":[
{"locationUrl":"https://test.scaldingspoon.org/test1/acs","binding":"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST","makeDefault":false}
],
"serviceEnabled":false,
"createdDate":null,
"modifiedDate":null,
"serviceEnabled":false,
"relyingPartyOverrides":{},
"attributeRelease":["givenName","employeeNumber"]
}
Expand Down
31 changes: 30 additions & 1 deletion ui/src/app/metadata/configuration/action/restore.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,39 @@ export enum RestoreActionTypes {
SELECT_VERSION_SUCCESS = '[Restore Version] Select Version Success',
SELECT_VERSION_ERROR = '[Restore Version] Select Version Error',
SELECT_VERSION_REQUEST = '[Restore Version] Select Version Request',

RESTORE_VERSION_REQUEST = '[Restore Version] Restore Version Request',
RESTORE_VERSION_SUCCESS = '[Restore Version] Restore Version Success',
RESTORE_VERSION_ERROR = '[Restore Version] Restore Version Error',

CLEAR_VERSION = '[Restore Version] Clear Versions'
}

export interface VersionRequest {
type: string;
id: string;
version: string;
}

export class RestoreVersionRequest implements Action {
readonly type = RestoreActionTypes.RESTORE_VERSION_REQUEST;
constructor(public payload: VersionRequest) { }
}

export class RestoreVersionSuccess implements Action {
readonly type = RestoreActionTypes.RESTORE_VERSION_SUCCESS;
constructor(public payload: { id: string, type: string, model: Metadata }) { }
}

export class RestoreVersionError implements Action {
readonly type = RestoreActionTypes.RESTORE_VERSION_ERROR;
constructor(public payload: any) { }
}

export class SelectVersionRestoreRequest implements Action {
readonly type = RestoreActionTypes.SELECT_VERSION_REQUEST;

constructor(public payload: { type: string, id: string, version: string }) { }
constructor(public payload: VersionRequest) { }
}

export class SelectVersionRestoreSuccess implements Action {
Expand All @@ -33,4 +59,7 @@ export type RestoreActionsUnion =
| SelectVersionRestoreRequest
| SelectVersionRestoreError
| SelectVersionRestoreSuccess
| RestoreVersionRequest
| RestoreVersionSuccess
| RestoreVersionError
| ClearVersionRestore;
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<td>
<button class="btn btn-text btn-link" (click)="restore.emit(version)" *ngIf="i > 0">
<i class="fa fa-undo"></i>&nbsp;
<translate-i18n key="label.restore">Restore</translate-i18n>
<translate-i18n key="action.restore">Restore</translate-i18n>
</button>
</td>
</tr>
Expand Down
6 changes: 4 additions & 2 deletions ui/src/app/metadata/configuration/configuration.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CommonModule, DatePipe } from '@angular/common';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { RouterModule } from '@angular/router';
Expand Down Expand Up @@ -63,7 +63,9 @@ import { RestoreVersionEffects } from './effect/restore.effect';
SharedModule
],
exports: [],
providers: []
providers: [
DatePipe
]
})
export class MetadataConfigurationModule {
static forRoot(): ModuleWithProviders {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,12 @@ describe('Metadata Configuration Page Component', () => {
it('should load metadata objects', async(() => {
expect(app).toBeTruthy();
}));

describe('hasVersion function', () => {
it('should determine if a version is defined', () => {
expect(app.hasVersion([[{id: 'foo'}], { version: 'foo' }])).toBe('foo');
expect(app.hasVersion([[{ id: 'foo' }], {}])).toBe('foo');
expect(app.hasVersion([[], {}])).toBeNull();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class ConfigurationComponent implements OnDestroy {
name$: Observable<string>;
type$: Observable<string>;

hasVersion = ([collection, params]) => params.version || collection && collection.length > 0 ? collection[0].id : null;

constructor(
private store: Store<fromConfiguration.ConfigurationState>,
private routerState: ActivatedRoute
Expand All @@ -37,7 +39,7 @@ export class ConfigurationComponent implements OnDestroy {
type,
version
}))
).subscribe(store);
).subscribe(this.store);

this.routerState.params.pipe(
takeUntil(this.ngUnsubscribe),
Expand All @@ -50,10 +52,8 @@ export class ConfigurationComponent implements OnDestroy {
withLatestFrom(
this.routerState.queryParams
),
map(([collection, params]) => params.version || collection && collection.length ? collection[0].id : null)
).subscribe(version => {
this.store.dispatch(new SelectVersion(version));
});
map(this.hasVersion)
).subscribe(version => this.store.dispatch(new SelectVersion(version)));

this.name$ = this.store.select(fromReducer.getConfigurationModelName);
this.type$ = this.store.select(fromReducer.getConfigurationModelType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export class MetadataHistoryComponent {
this.router.navigate(
[ '../', 'restore' ],
{
queryParams: { version: version.id },
relativeTo: this.route
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,11 @@ describe('Metadata Xml Page Component', () => {
expect(app).toBeTruthy();
expect(store.select).toHaveBeenCalledTimes(3);
}));

describe('preview method', () => {
it('should dispatch an action', () => {
app.preview();
expect(store.dispatch).toHaveBeenCalled();
});
});
});
18 changes: 13 additions & 5 deletions ui/src/app/metadata/configuration/container/restore.component.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
<h2 class="mb-4">
Restore Version
<h2 class="mb-4" *ngIf="date$ | async">
<translate-i18n key="label.restore-version" [params]="{ 'date': date$ | async }">
Restore Version ( date )
</translate-i18n>
</h2>
<div class="d-flex justify-content-center align-items-center">
<div class="card m-4 w-50">
<div class="card-body">
<h3 class="card-title">Create new version from {{ date | date:DATE_FORMAT }} settings</h3>
<p>Restoring this version will copy the configuration from the selected version and create a new version from these settings. You can then edit the configuration before saving the new version.</p>
<a href="#" class="btn btn-light">Cancel</a>&nbsp;<a href="#" class="btn btn-primary">Restore</a>
<h3 class="card-title" translate="message.create-new-version-from-version">
Create New Version from Previous Settings
</h3>
<p translate="message.restoring-this-version-will-copy"
[translateParams]="{ 'date': date$ | async }">
Restoring this version will copy the Version ( date ) configuration and create a new Version from the selected version settings. You can then edit the configuration before saving the new version.
</p>
<a [routerLink]="['../', 'history']" class="btn btn-light" translate="action.cancel">Cancel</a>&nbsp;
<button class="btn btn-primary" (click)="restore()" translate="action.restore">Restore</button>
</div>
</div>
</div>
Loading

0 comments on commit 6e2baee

Please sign in to comment.