Skip to content

Commit

Permalink
Showing 20 changed files with 3,465 additions and 9,722 deletions.
3 changes: 3 additions & 0 deletions backend/build.gradle
@@ -139,6 +139,9 @@ dependencies {

//JSON schema validator
compile 'org.sharegov:mjson:1.4.1'

// CSV file support
compile 'com.opencsv:opencsv:4.4'
}

def generatedSrcDir = new File(buildDir, 'generated/src/main/java')
@@ -0,0 +1,48 @@
package edu.internet2.tier.shibboleth.admin.ui.service

import com.opencsv.CSVReader
import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration
import edu.internet2.tier.shibboleth.admin.ui.security.model.Role
import edu.internet2.tier.shibboleth.admin.ui.security.model.User
import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository
import groovy.util.logging.Slf4j
import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.event.EventListener
import org.springframework.stereotype.Component

import javax.transaction.Transactional

@Component
@Slf4j
class UserBootstrap {
private final ShibUIConfiguration shibUIConfiguration
private final UserRepository userRepository
private final RoleRepository roleRepository

UserBootstrap(ShibUIConfiguration shibUIConfiguration, UserRepository userRepository, RoleRepository roleRepository) {
this.shibUIConfiguration = shibUIConfiguration
this.userRepository = userRepository
this.roleRepository = roleRepository
}

@Transactional
@EventListener
void bootstrapUsersAndRoles(ApplicationStartedEvent e) {
if (shibUIConfiguration.userBootstrapResource) {
log.info("configuring users from ${shibUIConfiguration.userBootstrapResource.URI}")
new CSVReader(new InputStreamReader(shibUIConfiguration.userBootstrapResource.inputStream)).each { it ->
def (username, password, firstName, lastName, roleName) = it
def role = roleRepository.findByName(roleName).orElse(roleRepository.save(new Role(name: roleName)))
def user = userRepository.findByUsername(username).orElse(new User(username: username)).with {
it.password = password
it.firstName = firstName
it.lastName = lastName
it.roles.add(role)
it
}
userRepository.save(user)
}
}
}
}
@@ -4,8 +4,10 @@
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;

import java.util.List;
import java.util.Optional;

@Configuration
@ConfigurationProperties(prefix = "shibui")
@@ -17,4 +19,19 @@ public class ShibUIConfiguration {
* sources from using attributes that they might not have the rights to use.
*/
private List<String> protectedAttributeNamespaces;

/**
* A Resource containing a CSV of users to bootstrap into the system. Currently, this must be in format
*
* <code>
* username,password,firstName,lastName,role
* </code>
*
* Note that the password must be encrypted in the file. Ensure that you prepend the encoder to the value, e.g.
*
* <code>
* {bcrypt}$2a$10$ssM2LpFqceRQ/ta0JehGcu0BawFQDbxjQGSyVmKS6qa09hHLigtAO
* </code>
*/
private Resource userBootstrapResource;
}
@@ -25,35 +25,6 @@
"@type",
"content"
],
"anyOf": [
{
"properties": {
"@type": {
"enum": [
"Regex"
]
}
},
"required": [
"@type",
"content",
"match"
]
},
{
"properties": {
"@type": {
"enum": [
"MetadataQueryProtocol"
]
}
},
"required": [
"@type",
"content"
]
}
],
"properties": {
"@type": {
"title": "label.md-request-type",
10 changes: 7 additions & 3 deletions backend/src/main/resources/i18n/messages_en.properties
@@ -304,7 +304,7 @@ label.metadata-provider-type=Metadata Provider Type
label.metadata-provider-name=Metadata Provider Name
label.select-metadata-type=Select a metadata provider type
label.metadata-provider-status=Metadata Provider Status
label.enable-provider-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP
label.enable-provider-upon-saving=Enable Metadata Provider?
label.certificate-type=Type

label.metadata-file=Metadata File
@@ -391,6 +391,10 @@ message.org-displayName-required=Organization Name is required.
message.org-url-required=Organization Name is required.
message.org-incomplete=These three fields must all be entered if any single field has a value.

message.type-required=Missing required property: Type
message.match-required=Missing required property: Match
message.value-required=Missing required property: Value

message.conflict=Conflict
message.data-version-contention=Data Version Contention
message.contention-new-version=A newer version of this metadata source has been saved. Below are a list of changes. You can use your changes or their changes.
@@ -437,7 +441,7 @@ tooltip.assertion-consumer-service-location-binding=Assertion Consumer Service L
tooltip.mark-as-default=Mark as Default
tooltip.protocol-support-enumeration=Protocol Support Enumeration
tooltip.nameid-format=Content is name identifier format which is added to all the applicable roles of the entities which match any of the following <Entity> or {{<ConditionRef>}}elements.
tooltip.enable-this-service-upon-saving=Enable this service upon saving
tooltip.enable-this-service-upon-saving=If checkbox is clicked, the metadata provider is enabled for integration with the IdP
tooltip.authentication-requests-signed=Authentication Requests Signed
tooltip.want-assertions-signed=Want Assertions Signed
tooltip.certificate-name=Certificate Name
@@ -523,7 +527,7 @@ tooltip.source-directory=Convenience mechanism for wiring a FilesystemLoadSaveMa
tooltip.remove-idle-entity-data=Flag indicating whether idle metadata should be removed.

tooltip.do-resolver-initialization=Initialize this resolver? In the case of Filesystem resolvers, this will cause the system to read the file and index the resolver.
tooltip.md-request-type=Options are 1) Metadata Query Protocol, 2) Template, 3) Regex.
tooltip.md-request-type=Options are 1) Metadata Query Protocol, 2) Regex.
tooltip.md-request-value=Content of the element.
tooltip.transform-ref=A reference to a transform function for the entityID. If used, the child element must be empty.
tooltip.encoding-style=Determines whether and how the entityID value will be URL encoded prior to replacement. Allowed values are: 1) "none" - no encoding is performed, 2) "form" - encoded using URL form parameter encoding (for query parameters), 3) "path" - encoded using URL path encoding, or 4) "fragment" - encoded using URL fragment encoding. The precise definition of these terms is defined in the documentation for the methods of the Guava library\u0027s UrlEscapers class.
@@ -0,0 +1,47 @@
package edu.internet2.tier.shibboleth.admin.ui.service

import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration
import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration
import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration
import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration
import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration
import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.core.io.ClassPathResource
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.test.annotation.DirtiesContext
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification

@DataJpaTest
@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, TestConfiguration, InternationalizationConfiguration, ShibUIConfiguration])
@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"])
@EntityScan(["edu.internet2.tier.shibboleth.admin.ui", "edu.internet2.tier.shibboleth.admin.ui.security.model"])
@DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
class UserBootstrapTests extends Specification {
@Autowired
ShibUIConfiguration shibUIConfiguration

@Autowired
UserRepository userRepository

@Autowired
RoleRepository roleRepository

def "simple test"() {
setup:
shibUIConfiguration.userBootstrapResource = new ClassPathResource('/conf/1044.csv')
def userBootstrap = new UserBootstrap(shibUIConfiguration, userRepository, roleRepository)

when:
userBootstrap.bootstrapUsersAndRoles(null)

then:
noExceptionThrown()
assert userRepository.findAll().size() == 2
assert roleRepository.findAll().size() == 2
}
}
2 changes: 2 additions & 0 deletions backend/src/test/resources/conf/1044.csv
@@ -0,0 +1,2 @@
"user1","password1","firstName1","lastName1","ROLE_ADMIN"
"user2","password2","firstName2","lastName2","ROLE_USER"

0 comments on commit 5becd15

Please sign in to comment.