Skip to content

Commit

Permalink
#62 - update categories' options
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Sep 30, 2015
1 parent 8c10344 commit 13c53ab
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 200 deletions.
29 changes: 15 additions & 14 deletions src/main/java/alfio/config/WebSecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,21 @@ protected void configure(HttpSecurity http) throws Exception {
configurer.requireCsrfProtectionMatcher(new NegatedRequestMatcher((r) -> whiteList.matcher(r.getMethod()).matches() || r.getRequestURI().equals("/report-csp-violation")));
}
configurer.csrfTokenRepository(getCsrfTokenRepository())
.and()
.authorizeRequests()
.antMatchers(ADMIN_API + "/organizations/new", ADMIN_API + "/users/**", ADMIN_API + "/configuration/**").hasRole(ADMIN)
.antMatchers(ADMIN_API + "/check-in/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers(HttpMethod.GET, ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers(ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**/export/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/authentication")
.loginProcessingUrl("/authentication")
.failureUrl("/authentication?failed");
.and()
.authorizeRequests()
.antMatchers(ADMIN_API + "/configuration/organizations/**").hasAnyRole(ADMIN, OWNER)
.antMatchers(ADMIN_API + "/organizations/new", ADMIN_API + "/users/**", ADMIN_API + "/configuration/**").hasRole(ADMIN)
.antMatchers(ADMIN_API + "/check-in/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers(HttpMethod.GET, ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers(ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**/export/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/authentication")
.loginProcessingUrl("/authentication")
.failureUrl("/authentication?failed");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
import alfio.model.plugin.PluginConfigOption;
import alfio.model.system.Configuration;
import alfio.model.system.ConfigurationKeys;
import alfio.model.user.Organization;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Expand All @@ -51,22 +54,39 @@ public SettingsApiController(ConfigurationManager configurationManager, PluginMa
}

@RequestMapping(value = "/configuration/load", method = GET)
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> loadConfiguration() {
return configurationManager.loadAllSystemConfigurationIncludingMissing();
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> loadConfiguration(Principal principal) {
return configurationManager.loadAllSystemConfigurationIncludingMissing(principal.getName());
}

@RequestMapping(value = "/configuration/update", method = POST)
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> updateConfiguration(@RequestBody ConfigurationModification configuration) {
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> updateConfiguration(@RequestBody ConfigurationModification configuration, Principal principal) {
configurationManager.saveSystemConfiguration(ConfigurationKeys.fromValue(configuration.getKey()), configuration.getValue());
return loadConfiguration();
return loadConfiguration(principal);
}

@RequestMapping(value = "/configuration/update-bulk", method = POST)
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> updateConfiguration(@RequestBody Map<ConfigurationKeys.SettingCategory, List<ConfigurationModification>> input) {
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> updateConfiguration(@RequestBody Map<ConfigurationKeys.SettingCategory, List<ConfigurationModification>> input,
Principal principal) {
Objects.requireNonNull(input);
List<ConfigurationModification> list = input.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
configurationManager.saveAllSystemConfiguration(list);
return loadConfiguration();
return loadConfiguration(principal);
}

@RequestMapping(value = "/configuration/organizations/load", method = GET)
public List<OrganizationConfig> loadOrganizationsConfiguration(Principal principal) {
return configurationManager.loadAllOrganizationConfiguration(principal.getName()).entrySet()
.stream()
.map(e -> new OrganizationConfig(e.getKey(), e.getValue()))
.collect(Collectors.toList());
}

@RequestMapping(value = "/configuration/organizations/{organizationId}/update", method = POST)
public List<OrganizationConfig> updateOrganizationsConfiguration(@PathVariable("organizationId") int organizationId,
@RequestBody Map<ConfigurationKeys.SettingCategory, List<ConfigurationModification>> input,
Principal principal) {
configurationManager.saveAllOrganizationConfiguration(organizationId, input.values().stream().flatMap(Collection::stream).collect(Collectors.toList()));
return loadOrganizationsConfiguration(principal);
}

@RequestMapping(value = "/configuration/plugin/load", method = GET)
Expand All @@ -86,4 +106,10 @@ public boolean deleteKey(@PathVariable("key") String key) {
configurationManager.deleteKey(key);
return true;
}

@Data
class OrganizationConfig {
private final Organization organization;
private final Map<ConfigurationKeys.SettingCategory, List<Configuration>> config;
}
}
77 changes: 70 additions & 7 deletions src/main/java/alfio/manager/system/ConfigurationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,28 @@
*/
package alfio.manager.system;

import alfio.manager.user.UserManager;
import alfio.model.modification.ConfigurationModification;
import alfio.model.system.Configuration;
import alfio.model.system.Configuration.*;
import alfio.model.system.ConfigurationKeys;
import alfio.model.system.ConfigurationPathLevel;
import alfio.model.user.Organization;
import alfio.model.user.User;
import alfio.model.user.join.UserOrganization;
import alfio.repository.system.ConfigurationRepository;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import static alfio.util.OptionalWrapper.optionally;
Expand All @@ -38,11 +47,18 @@
@Log4j2
public class ConfigurationManager {

private static final Map<ConfigurationKeys.SettingCategory, List<Configuration>> TICKET_CATEGORY_CONFIGURATION = ConfigurationKeys.byPathLevel(ConfigurationPathLevel.ORGANIZATION)
.stream()
.map(mapEmptyKeys(ConfigurationPathLevel.ORGANIZATION))
.collect(groupByCategory());

private final ConfigurationRepository configurationRepository;
private final UserManager userManager;

@Autowired
public ConfigurationManager(ConfigurationRepository configurationRepository) {
public ConfigurationManager(ConfigurationRepository configurationRepository, UserManager userManager) {
this.configurationRepository = configurationRepository;
this.userManager = userManager;
}

//TODO: refactor, not the most beautiful code, find a better solution...
Expand Down Expand Up @@ -121,6 +137,19 @@ public void saveAllSystemConfiguration(List<ConfigurationModification> list) {
list.forEach(c -> saveSystemConfiguration(ConfigurationKeys.fromValue(c.getKey()), c.getValue()));
}

public void saveAllOrganizationConfiguration(int organizationId, List<ConfigurationModification> list) {
list.stream()
.filter(c -> c.getId() > -1 || !StringUtils.isBlank(c.getValue()))
.forEach(c -> {
Optional<Configuration> existing = configurationRepository.findByKeyAtOrganizationLevel(organizationId, c.getKey());
if (existing.isPresent()) {
configurationRepository.updateOrganizationLevel(organizationId, c.getKey(), c.getValue());
} else {
configurationRepository.insertOrganizationLevel(organizationId, c.getKey(), c.getValue(), ConfigurationKeys.fromValue(c.getKey()).getDescription());
}
});
}

public void saveSystemConfiguration(ConfigurationKeys key, String value) {
Optional<Configuration> conf = optionally(() -> findByConfigurationPathAndKey(Configuration.system(), key));
Optional<String> valueOpt = Optional.ofNullable(value);
Expand All @@ -144,26 +173,60 @@ public boolean isBasicConfigurationNeeded() {
return ConfigurationKeys.basic().stream()
.anyMatch(key -> {
boolean absent = !configurationRepository.findOptionalByKey(key.getValue()).isPresent();
if(absent) {
log.warn("cannot find a value for "+key.getValue());
if (absent) {
log.warn("cannot find a value for " + key.getValue());
}
return absent;
});
}

public Map<Organization, Map<ConfigurationKeys.SettingCategory, List<Configuration>>> loadAllOrganizationConfiguration(String username) {
User user = userManager.findUserByUsername(username);
if(!userManager.isOwner(user)) {
return Collections.emptyMap();
}
return userManager.findUserOrganizations(user).stream()
.collect(Collectors.toMap(Function.identity(), o -> {
Map<ConfigurationKeys.SettingCategory, List<Configuration>> existing = configurationRepository.findOrganizationConfiguration(o.getId()).stream().collect(groupByCategory());
return TICKET_CATEGORY_CONFIGURATION.entrySet().stream()
.map(e -> {
Set<Configuration> entries = new LinkedHashSet<>();
ConfigurationKeys.SettingCategory key = e.getKey();
entries.addAll(e.getValue());
if(existing.containsKey(key)) {
List<Configuration> configurations = existing.get(key);
entries.removeAll(configurations);
entries.addAll(configurations);
}
return Pair.of(key, new ArrayList<>(entries));
})
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
}));
}

public Map<ConfigurationKeys.SettingCategory, List<Configuration>> loadAllSystemConfigurationIncludingMissing() {
final List<Configuration> existing = configurationRepository.findAll()
public Map<ConfigurationKeys.SettingCategory, List<Configuration>> loadAllSystemConfigurationIncludingMissing(String username) {
if(!userManager.isAdmin(userManager.findUserByUsername(username))) {
return Collections.emptyMap();
}
final List<Configuration> existing = configurationRepository.findSystemConfiguration()
.stream()
.filter(c -> !ConfigurationKeys.fromValue(c.getKey()).isInternal())
.collect(Collectors.toList());
final List<Configuration> missing = Arrays.stream(ConfigurationKeys.visible())
.filter(k -> existing.stream().noneMatch(c -> c.getKey().equals(k.getValue())))
.map(k -> new Configuration(-1, k.getValue(), null, k.getDescription(), ConfigurationPathLevel.SYSTEM))
.map(mapEmptyKeys(ConfigurationPathLevel.SYSTEM))
.collect(Collectors.toList());
List<Configuration> result = new LinkedList<>(existing);
result.addAll(missing);
return result.stream().collect(Collectors.groupingBy(c -> c.getConfigurationKey().getCategory()));
return result.stream().collect(groupByCategory());
}

private static Collector<Configuration, ?, Map<ConfigurationKeys.SettingCategory, List<Configuration>>> groupByCategory() {
return Collectors.groupingBy(c -> c.getConfigurationKey().getCategory());
}

private static Function<ConfigurationKeys, Configuration> mapEmptyKeys(ConfigurationPathLevel level) {
return k -> new Configuration(-1, k.getValue(), null, k.getDescription(), level);
}

public void deleteKey(String key) {
Expand Down
17 changes: 15 additions & 2 deletions src/main/java/alfio/manager/user/UserManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Predicate;

import static java.util.stream.Collectors.toList;

Expand Down Expand Up @@ -78,6 +79,10 @@ public List<User> findAllUsers(String username) {
.collect(toList());
}

public User findUserByUsername(String username) {
return userRepository.findEnabledByUsername(username).orElseThrow(IllegalArgumentException::new);
}

public User findUser(int id) {
return userRepository.findById(id);
}
Expand Down Expand Up @@ -105,7 +110,15 @@ public List<Organization> findUserOrganizations(User user) {
}

public boolean isAdmin(User user) {
return getUserAuthorities(user).stream().anyMatch(a -> a.getRole().equals(AuthorityRepository.ROLE_ADMIN));
return checkRole(user, a -> a.getRole().equals(AuthorityRepository.ROLE_ADMIN));
}

public boolean isOwner(User user) {
return checkRole(user, a -> a.getRole().equals(AuthorityRepository.ROLE_ADMIN) || a.getRole().equals(AuthorityRepository.ROLE_OWNER));
}

private boolean checkRole(User user, Predicate<Authority> matcher) {
return getUserAuthorities(user).stream().anyMatch(matcher);
}

@Transactional
Expand Down Expand Up @@ -161,7 +174,7 @@ public UserWithPassword resetPassword(int userId) {

@Transactional
public void deleteUser(int userId, String currentUsername) {
User currentUser = userRepository.findEnabledByUsername(currentUsername);
User currentUser = userRepository.findEnabledByUsername(currentUsername).orElseThrow(IllegalArgumentException::new);
Assert.isTrue(userId != currentUser.getId(), "sorry but you cannot commit suicide");
Assert.isTrue(userRepository.toggleEnabled(userId, false) == 1, "unexpected update result");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package alfio.model.modification;

import alfio.model.system.Configuration;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
Expand All @@ -34,4 +35,8 @@ public ConfigurationModification(@JsonProperty("id") Integer id,
this.key = key;
this.value = value;
}

public static ConfigurationModification fromConfiguration(Configuration in) {
return new ConfigurationModification(in.getId(), in.getKey(), in.getValue());
}
}
25 changes: 24 additions & 1 deletion src/main/java/alfio/model/system/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

@Getter
@EqualsAndHashCode
public class Configuration {

private final int id;
Expand Down Expand Up @@ -334,4 +335,26 @@ public static ConfigurationPathKey notifyForEachWaitingQueueSubscription(Event e
public static ConfigurationPathKey waitingQueueReservationTimeout(Event event) {
return new ConfigurationPathKey(event(event), ConfigurationKeys.WAITING_QUEUE_RESERVATION_TIMEOUT);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Configuration that = (Configuration) o;

return new EqualsBuilder()
.append(key, that.key)
.append(configurationKey, that.configurationKey)
.isEquals();
}

@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(key)
.append(configurationKey)
.toHashCode();
}
}
Loading

0 comments on commit 13c53ab

Please sign in to comment.