/* | |
* Copyright 2011 gitblit.com. | |
* | |
* 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 com.gitblit; | |
import java.io.IOException; | |
import java.text.MessageFormat; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import org.eclipse.jgit.lib.Repository; | |
import com.gitblit.Constants.RpcRequest; | |
import com.gitblit.models.RefModel; | |
import com.gitblit.models.RepositoryModel; | |
import com.gitblit.models.ServerSettings; | |
import com.gitblit.models.TeamModel; | |
import com.gitblit.models.UserModel; | |
import com.gitblit.utils.HttpUtils; | |
import com.gitblit.utils.JGitUtils; | |
import com.gitblit.utils.RpcUtils; | |
/** | |
* Handles remote procedure calls. | |
* | |
* @author James Moger | |
* | |
*/ | |
public class RpcServlet extends JsonServlet { | |
private static final long serialVersionUID = 1L; | |
public static final int PROTOCOL_VERSION = 2; | |
public RpcServlet() { | |
super(); | |
} | |
/** | |
* Processes an rpc request. | |
* | |
* @param request | |
* @param response | |
* @throws javax.servlet.ServletException | |
* @throws java.io.IOException | |
*/ | |
@Override | |
protected void processRequest(HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException { | |
RpcRequest reqType = RpcRequest.fromName(request.getParameter("req")); | |
String objectName = request.getParameter("name"); | |
logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType, | |
request.getRemoteAddr())); | |
UserModel user = (UserModel) request.getUserPrincipal(); | |
boolean allowManagement = user != null && user.canAdmin | |
&& GitBlit.getBoolean(Keys.web.enableRpcManagement, false); | |
boolean allowAdmin = user != null && user.canAdmin | |
&& GitBlit.getBoolean(Keys.web.enableRpcAdministration, false); | |
Object result = null; | |
if (RpcRequest.GET_PROTOCOL.equals(reqType)) { | |
// Return the protocol version | |
result = PROTOCOL_VERSION; | |
} else if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) { | |
// Determine the Gitblit clone url | |
String gitblitUrl = HttpUtils.getGitblitURL(request); | |
StringBuilder sb = new StringBuilder(); | |
sb.append(gitblitUrl); | |
sb.append(Constants.GIT_PATH); | |
sb.append("{0}"); | |
String cloneUrl = sb.toString(); | |
// list repositories | |
List<RepositoryModel> list = GitBlit.self().getRepositoryModels(user); | |
Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>(); | |
for (RepositoryModel model : list) { | |
String url = MessageFormat.format(cloneUrl, model.name); | |
repositories.put(url, model); | |
} | |
result = repositories; | |
} else if (RpcRequest.LIST_BRANCHES.equals(reqType)) { | |
// list all local branches in all repositories accessible to user | |
Map<String, List<String>> localBranches = new HashMap<String, List<String>>(); | |
List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user); | |
for (RepositoryModel model : models) { | |
if (!model.hasCommits) { | |
// skip empty repository | |
continue; | |
} | |
// get local branches | |
Repository repository = GitBlit.self().getRepository(model.name); | |
List<RefModel> refs = JGitUtils.getLocalBranches(repository, false, -1); | |
if (model.showRemoteBranches) { | |
// add remote branches if repository displays them | |
refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1)); | |
} | |
if (refs.size() > 0) { | |
List<String> branches = new ArrayList<String>(); | |
for (RefModel ref : refs) { | |
branches.add(ref.getName()); | |
} | |
localBranches.put(model.name, branches); | |
} | |
repository.close(); | |
} | |
result = localBranches; | |
} else if (RpcRequest.LIST_USERS.equals(reqType)) { | |
// list users | |
List<String> names = GitBlit.self().getAllUsernames(); | |
List<UserModel> users = new ArrayList<UserModel>(); | |
for (String name : names) { | |
users.add(GitBlit.self().getUserModel(name)); | |
} | |
result = users; | |
} else if (RpcRequest.LIST_TEAMS.equals(reqType)) { | |
// list teams | |
List<String> names = GitBlit.self().getAllTeamnames(); | |
List<TeamModel> teams = new ArrayList<TeamModel>(); | |
for (String name : names) { | |
teams.add(GitBlit.self().getTeamModel(name)); | |
} | |
result = teams; | |
} else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) { | |
// create repository | |
RepositoryModel model = deserialize(request, response, RepositoryModel.class); | |
try { | |
GitBlit.self().updateRepositoryModel(model.name, model, true); | |
} catch (GitBlitException e) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) { | |
// edit repository | |
RepositoryModel model = deserialize(request, response, RepositoryModel.class); | |
// name specifies original repository name in event of rename | |
String repoName = objectName; | |
if (repoName == null) { | |
repoName = model.name; | |
} | |
try { | |
GitBlit.self().updateRepositoryModel(repoName, model, false); | |
} catch (GitBlitException e) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) { | |
// delete repository | |
RepositoryModel model = deserialize(request, response, RepositoryModel.class); | |
GitBlit.self().deleteRepositoryModel(model); | |
} else if (RpcRequest.CREATE_USER.equals(reqType)) { | |
// create user | |
UserModel model = deserialize(request, response, UserModel.class); | |
try { | |
GitBlit.self().updateUserModel(model.username, model, true); | |
} catch (GitBlitException e) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.EDIT_USER.equals(reqType)) { | |
// edit user | |
UserModel model = deserialize(request, response, UserModel.class); | |
// name parameter specifies original user name in event of rename | |
String username = objectName; | |
if (username == null) { | |
username = model.username; | |
} | |
try { | |
GitBlit.self().updateUserModel(username, model, false); | |
} catch (GitBlitException e) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.DELETE_USER.equals(reqType)) { | |
// delete user | |
UserModel model = deserialize(request, response, UserModel.class); | |
if (!GitBlit.self().deleteUser(model.username)) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.CREATE_TEAM.equals(reqType)) { | |
// create team | |
TeamModel model = deserialize(request, response, TeamModel.class); | |
try { | |
GitBlit.self().updateTeamModel(model.name, model, true); | |
} catch (GitBlitException e) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.EDIT_TEAM.equals(reqType)) { | |
// edit team | |
TeamModel model = deserialize(request, response, TeamModel.class); | |
// name parameter specifies original team name in event of rename | |
String teamname = objectName; | |
if (teamname == null) { | |
teamname = model.name; | |
} | |
try { | |
GitBlit.self().updateTeamModel(teamname, model, false); | |
} catch (GitBlitException e) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.DELETE_TEAM.equals(reqType)) { | |
// delete team | |
TeamModel model = deserialize(request, response, TeamModel.class); | |
if (!GitBlit.self().deleteTeam(model.name)) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) { | |
// get repository members | |
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName); | |
result = GitBlit.self().getRepositoryUsers(model); | |
} else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) { | |
// update repository access list | |
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName); | |
Collection<String> names = deserialize(request, response, RpcUtils.NAMES_TYPE); | |
List<String> users = new ArrayList<String>(names); | |
if (!GitBlit.self().setRepositoryUsers(model, users)) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) { | |
// get repository teams | |
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName); | |
result = GitBlit.self().getRepositoryTeams(model); | |
} else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) { | |
// update repository team access list | |
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName); | |
Collection<String> names = deserialize(request, response, RpcUtils.NAMES_TYPE); | |
List<String> teams = new ArrayList<String>(names); | |
if (!GitBlit.self().setRepositoryTeams(model, teams)) { | |
response.setStatus(failureCode); | |
} | |
} else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) { | |
// return the list of federation registrations | |
if (allowAdmin) { | |
result = GitBlit.self().getFederationRegistrations(); | |
} else { | |
response.sendError(notAllowedCode); | |
} | |
} else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) { | |
// return the list of federation result registrations | |
if (allowAdmin && GitBlit.canFederate()) { | |
result = GitBlit.self().getFederationResultRegistrations(); | |
} else { | |
response.sendError(notAllowedCode); | |
} | |
} else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) { | |
// return the list of federation proposals | |
if (allowAdmin && GitBlit.canFederate()) { | |
result = GitBlit.self().getPendingFederationProposals(); | |
} else { | |
response.sendError(notAllowedCode); | |
} | |
} else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) { | |
// return the list of federation sets | |
if (allowAdmin && GitBlit.canFederate()) { | |
String gitblitUrl = HttpUtils.getGitblitURL(request); | |
result = GitBlit.self().getFederationSets(gitblitUrl); | |
} else { | |
response.sendError(notAllowedCode); | |
} | |
} else if (RpcRequest.LIST_SETTINGS.equals(reqType)) { | |
// return the server's settings | |
ServerSettings settings = GitBlit.self().getSettingsModel(); | |
if (allowAdmin) { | |
// return all settings | |
result = settings; | |
} else { | |
// anonymous users get a few settings to allow browser launching | |
List<String> keys = new ArrayList<String>(); | |
keys.add(Keys.web.siteName); | |
keys.add(Keys.web.mountParameters); | |
keys.add(Keys.web.syndicationEntries); | |
if (allowManagement) { | |
// keys necessary for repository and/or user management | |
keys.add(Keys.realm.minPasswordLength); | |
keys.add(Keys.realm.passwordStorage); | |
keys.add(Keys.federation.sets); | |
} | |
// build the settings | |
ServerSettings managementSettings = new ServerSettings(); | |
for (String key : keys) { | |
managementSettings.add(settings.get(key)); | |
} | |
if (allowManagement) { | |
managementSettings.pushScripts = settings.pushScripts; | |
} | |
result = managementSettings; | |
} | |
} else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) { | |
// update settings on the server | |
if (allowAdmin) { | |
Map<String, String> settings = deserialize(request, response, | |
RpcUtils.SETTINGS_TYPE); | |
GitBlit.self().updateSettings(settings); | |
} else { | |
response.sendError(notAllowedCode); | |
} | |
} else if (RpcRequest.LIST_STATUS.equals(reqType)) { | |
// return the server's status information | |
if (allowAdmin) { | |
result = GitBlit.self().getStatus(); | |
} else { | |
response.sendError(notAllowedCode); | |
} | |
} | |
// send the result of the request | |
serialize(response, result); | |
} | |
} |