/*******************************************************************************
* Copyright (c) 2010, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.internal.server.servlets.workspace.authorization;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.orion.internal.server.servlets.Activator;
import org.eclipse.orion.server.core.OrionConfiguration;
import org.eclipse.orion.server.core.PreferenceHelper;
import org.eclipse.orion.server.core.ProtocolConstants;
import org.eclipse.orion.server.core.ServerConstants;
import org.eclipse.orion.server.core.ServerStatus;
import org.eclipse.orion.server.core.metastore.UserInfo;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Handles access and persistence of user authorization information.
*/
public class AuthorizationService {
public static final int POST = 1;
public static final int PUT = 2;
public static final int GET = 4;
public static final int DELETE = 8;
private static final String PREFIX_EXPORT = "/xfer/export/"; //$NON-NLS-1$
private static final String PREFIX_IMPORT = "/xfer/import/"; //$NON-NLS-1$
private static final String ANONYMOUS_LOGIN_VALUE = "Anonymous"; //$NON-NLS-1$
/**
* Adds the right for the given user to put, post, get, or delete the given URI.
* @param userId The user name
* @param uri The URI to grant access to
* @throws CoreException If an error occurred persisting user rights.
*/
public static void addUserRight(String userId, String uri) throws CoreException {
try {
//TODO probably want caller to pass in UserInfo for performance
UserInfo user = OrionConfiguration.getMetaStore().readUser(userId);
JSONArray userRightArray = AuthorizationReader.getAuthorizationData(user);
// adds all rights for the uri
JSONObject userRight = createUserRight(uri);
//check if we already have this right
for (int i = 0; i < userRightArray.length(); i++) {
if (userRight.toString().equals(userRightArray.get(i).toString()))
return;
}
//add the new right
userRightArray.put(userRight);
AuthorizationReader.saveRights(user, userRightArray);
} catch (Exception e) {
String msg = "Error persisting user rights";
throw new CoreException(new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e));
}
}
public static boolean checkRights(String userId, String uri, String method) throws CoreException {
if (uri.equals(Activator.LOCATION_WORKSPACE_SERVLET) && !ANONYMOUS_LOGIN_VALUE.equals(userId))
return true;
// any user can access their site configurations
if (uri.startsWith("/site") && !ANONYMOUS_LOGIN_VALUE.equals(userId)) //$NON-NLS-1$
return true;
// any user can access their own profile
if (uri.equals("/users/" + userId) && !ANONYMOUS_LOGIN_VALUE.equals(userId)) //$NON-NLS-1$
return true;
// any user can access tasks
if (uri.startsWith("/task")) //$NON-NLS-1$
return true;
// import/export rights depend on access to the file content
if (uri.startsWith(PREFIX_EXPORT) && uri.endsWith(".zip")) { //$NON-NLS-1$
uri = "/file/" + uri.substring(13, uri.length() - 4) + '/'; //$NON-NLS-1$
} else if (uri.startsWith(PREFIX_IMPORT)) {
uri = "/file/" + uri.substring(PREFIX_IMPORT.length()); //$NON-NLS-1$
if (!uri.endsWith("/")) //$NON-NLS-1$
uri += '/';
}
// allow anonymous read if the corresponding property is set
String projectWorldReadable = PreferenceHelper.getString(ServerConstants.CONFIG_FILE_ANONYMOUS_READ, "false"); //$NON-NLS-1$
int methodMask = getMethod(method);
if (methodMask == GET && uri.startsWith("/file/") && "true".equalsIgnoreCase(projectWorldReadable)) {//$NON-NLS-1$ //$NON-NLS-2$
// except don't allow access to metadata
if ("/file/".equals(uri) || uri.startsWith("/file/.metadata/")) //$NON-NLS-1$//$NON-NLS-2$
return false;
return true;
}
UserInfo user = OrionConfiguration.getMetaStore().readUser(userId);
JSONArray userRightArray = AuthorizationReader.getAuthorizationData(user);
for (int i = 0; i < userRightArray.length(); i++) {
try {
JSONObject userRight = (JSONObject) userRightArray.get(i);
String patternToMatch = userRight.getString(ProtocolConstants.KEY_USER_RIGHT_URI);
int methodToMatch = userRight.getInt(ProtocolConstants.KEY_USER_RIGHT_METHOD);
if (wildCardMatch(uri, patternToMatch) && ((methodMask & methodToMatch) == methodMask))
return true;
} catch (JSONException e) {
//sk
}
}
return false;
}
/**
* Create a new user rights object granting all permissions to the given URI.
* @throws JSONException
*/
static JSONObject createUserRight(String uri) throws JSONException {
JSONObject userRight = new JSONObject();
userRight.put(ProtocolConstants.KEY_USER_RIGHT_URI, uri);
userRight.put(ProtocolConstants.KEY_USER_RIGHT_METHOD, POST | PUT | GET | DELETE);
return userRight;
}
private static int getMethod(String methodName) {
if (methodName.equals("POST")) //$NON-NLS-1$
return 1;
if (methodName.equals("PUT")) //$NON-NLS-1$
return 2;
if (methodName.equals("GET")) //$NON-NLS-1$
return 4;
if (methodName.equals("DELETE")) //$NON-NLS-1$
return 8;
return 0;
}
/**
* Removes the right for the given user to put, post, get, or delete the given URI.
* @param userId The user name
* @param uri The URI to remove access to
* @throws CoreException If an error occurred persisting user rights.
*/
public static void removeUserRight(String userId, String uri) throws CoreException {
try {
@SuppressWarnings("unused")
Activator r = Activator.getDefault();
UserInfo user = OrionConfiguration.getMetaStore().readUser(userId);
JSONArray userRightArray = AuthorizationReader.getAuthorizationData(user);
for (int i = 0; i < userRightArray.length(); i++) {
if (uri.equals(((JSONObject) userRightArray.get(i)).get(ProtocolConstants.KEY_USER_RIGHT_URI)))
userRightArray.remove(i);
}
AuthorizationReader.saveRights(user, userRightArray);
} catch (Exception e) {
throw new CoreException(new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error persisting user rights", e));
}
}
private static boolean wildCardMatch(String text, String pattern) {
String[] cards = pattern.split("\\*"); //$NON-NLS-1$
if (!pattern.startsWith("*") && !text.startsWith(cards[0])) { //$NON-NLS-1$
return false;
}
if (!pattern.endsWith("*") && !text.endsWith(cards[cards.length - 1])) { //$NON-NLS-1$
return false;
}
for (String card : cards) {
int idex = text.indexOf(card);
if (idex == -1) {
return false;
}
text = text.substring(idex + card.length());
}
return true;
}
}