/** * Copyright 2012 Universitat Pompeu Fabra. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * */ package org.onexus.resource.authorization.internal; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import org.apache.commons.io.monitor.FileAlterationMonitor; import org.apache.commons.io.monitor.FileAlterationObserver; import org.onexus.resource.api.IAuthorizationManager; import org.onexus.resource.api.ORI; import org.onexus.resource.api.session.LoginContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Properties; import java.util.Set; public class AuthorizationManager implements IAuthorizationManager { private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizationManager.class); public static final String ANONYMOUS_USER = "anonymous"; private String authorizationFile; private Properties properties; private FileAlterationMonitor monitor; @Override public boolean check(String privilege, ORI resourceOri) { // Service context always have read-only privilege LoginContext ctx = LoginContext.get(); if (ctx == LoginContext.SERVICE_CONTEXT) { return true; } // Check private projects String projectUrl = resourceOri.getProjectUrl(); if (projectUrl.startsWith("private://")) { int end = projectUrl.indexOf('/', 10); if (end == -1) { return false; } String userName = projectUrl.substring(10, end); if (userName == null || !userName.equals(ctx.getUserName())) { return false; } } // Check privileges return getPrivileges(resourceOri).contains(privilege); } @Override public Set<String> getPrivileges(ORI resourceOri) { LoginContext ctx = LoginContext.get(); if (ctx == null) { return Collections.emptySet(); } Set<String> result = new HashSet<String>(); // First load roles privileges for (String role : ctx.getRoles()) { result.addAll(loadPrivileges("role-" + role, resourceOri)); } // Load user privileges result.addAll(loadPrivileges(ctx.getUserName(), resourceOri)); return result; } private Set<String> loadPrivileges(String key, ORI resourceOri) { Set<String> result = new HashSet<String>(); if (key == null) { key = ANONYMOUS_USER; } String value = properties.getProperty(key); if (value == null || value.isEmpty()) { return result; } String items[] = value.split(","); for (String item : items) { String pair[] = item.split("\\|\\|"); String regex = pair[0].trim(); String privileges[] = pair[1].split("\\|"); if (resourceOri.toString().matches(regex)) { for (String privilege : privileges) { result.add(privilege.trim().toLowerCase()); } } } return result; } public void load() { try { this.properties = loadProperties(); } catch (IOException e) { LOGGER.error("Loading authorization config file", e); } // Watch file changes and fire a reload monitor = new FileAlterationMonitor(2000); File file = new File(authorizationFile); FileAlterationObserver observer = new FileAlterationObserver(file.getParent(), FileFilterUtils.nameFileFilter(file.getName())); observer.addListener(new FileAlterationListenerAdaptor() { @Override public void onFileChange(File file) { try { properties = AuthorizationManager.this.loadProperties(); } catch (IOException e) { LOGGER.error("Loading authorization config file", e); } } }); monitor.addObserver(observer); try { monitor.start(); } catch (Exception e) { LOGGER.error("On start authorization config file monitor", e); } } private synchronized Properties loadProperties() throws IOException { LOGGER.info("Loading authorization config file"); Properties properties = new Properties(); File file = new File(authorizationFile); if (!file.exists()) { properties.setProperty("role-admin", ".*||read|write|load|unload|grant"); properties.setProperty(ANONYMOUS_USER, ".*||read"); properties.setProperty("role-registered", ".*||read"); properties.store(new FileOutputStream(file), "Syntax: username = [regular expression to match against ORI] || [privilege 1] | [privilege 2] | ... , more..."); } else { properties.load(new FileInputStream(authorizationFile)); } return properties; } public String getAuthorizationFile() { return authorizationFile; } public void setAuthorizationFile(String authorizationFile) { this.authorizationFile = authorizationFile; } }