James Moger
2012-03-20 aebae04b6d44d90434f5829c2b2242b1aa1f9f7b
commit | author | age
93f0b1 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit;
17
ca9d0f 18 import java.io.IOException;
93f0b1 19 import java.text.MessageFormat;
JM 20 import java.util.ArrayList;
31abc2 21 import java.util.Collection;
93f0b1 22 import java.util.HashMap;
JM 23 import java.util.List;
24 import java.util.Map;
25
ca9d0f 26 import javax.servlet.ServletException;
JM 27 import javax.servlet.http.HttpServletRequest;
93f0b1 28 import javax.servlet.http.HttpServletResponse;
JM 29
c75304 30 import org.eclipse.jgit.lib.Repository;
JM 31
93f0b1 32 import com.gitblit.Constants.RpcRequest;
c75304 33 import com.gitblit.models.RefModel;
93f0b1 34 import com.gitblit.models.RepositoryModel;
284a7b 35 import com.gitblit.models.ServerSettings;
f08aab 36 import com.gitblit.models.TeamModel;
93f0b1 37 import com.gitblit.models.UserModel;
JM 38 import com.gitblit.utils.HttpUtils;
c75304 39 import com.gitblit.utils.JGitUtils;
31abc2 40 import com.gitblit.utils.RpcUtils;
93f0b1 41
JM 42 /**
43  * Handles remote procedure calls.
44  * 
45  * @author James Moger
46  * 
47  */
48 public class RpcServlet extends JsonServlet {
49
50     private static final long serialVersionUID = 1L;
f08aab 51
e9de3f 52     public static final int PROTOCOL_VERSION = 3;
93f0b1 53
JM 54     public RpcServlet() {
55         super();
56     }
57
58     /**
59      * Processes an rpc request.
60      * 
61      * @param request
62      * @param response
63      * @throws javax.servlet.ServletException
64      * @throws java.io.IOException
65      */
66     @Override
ca9d0f 67     protected void processRequest(HttpServletRequest request, HttpServletResponse response)
JM 68             throws ServletException, IOException {
93f0b1 69         RpcRequest reqType = RpcRequest.fromName(request.getParameter("req"));
31abc2 70         String objectName = request.getParameter("name");
93f0b1 71         logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType,
JM 72                 request.getRemoteAddr()));
284a7b 73
ca9d0f 74         UserModel user = (UserModel) request.getUserPrincipal();
ec5a88 75
JM 76         boolean allowManagement = user != null && user.canAdmin
77                 && GitBlit.getBoolean(Keys.web.enableRpcManagement, false);
78
79         boolean allowAdmin = user != null && user.canAdmin
80                 && GitBlit.getBoolean(Keys.web.enableRpcAdministration, false);
93f0b1 81
JM 82         Object result = null;
f08aab 83         if (RpcRequest.GET_PROTOCOL.equals(reqType)) {
JM 84             // Return the protocol version
85             result = PROTOCOL_VERSION;
86         } else if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) {
93f0b1 87             // Determine the Gitblit clone url
JM 88             String gitblitUrl = HttpUtils.getGitblitURL(request);
89             StringBuilder sb = new StringBuilder();
90             sb.append(gitblitUrl);
91             sb.append(Constants.GIT_PATH);
92             sb.append("{0}");
93             String cloneUrl = sb.toString();
94
ca9d0f 95             // list repositories
93f0b1 96             List<RepositoryModel> list = GitBlit.self().getRepositoryModels(user);
JM 97             Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>();
98             for (RepositoryModel model : list) {
99                 String url = MessageFormat.format(cloneUrl, model.name);
100                 repositories.put(url, model);
101             }
102             result = repositories;
c75304 103         } else if (RpcRequest.LIST_BRANCHES.equals(reqType)) {
17820f 104             // list all local branches in all repositories accessible to user
JM 105             Map<String, List<String>> localBranches = new HashMap<String, List<String>>();
c75304 106             List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user);
JM 107             for (RepositoryModel model : models) {
108                 if (!model.hasCommits) {
109                     // skip empty repository
110                     continue;
111                 }
17820f 112                 // get local branches
c75304 113                 Repository repository = GitBlit.self().getRepository(model.name);
JM 114                 List<RefModel> refs = JGitUtils.getLocalBranches(repository, false, -1);
17820f 115                 if (model.showRemoteBranches) {
JM 116                     // add remote branches if repository displays them
117                     refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1));
118                 }
c75304 119                 if (refs.size() > 0) {
JM 120                     List<String> branches = new ArrayList<String>();
121                     for (RefModel ref : refs) {
122                         branches.add(ref.getName());
123                     }
17820f 124                     localBranches.put(model.name, branches);
c75304 125                 }
JM 126                 repository.close();
127             }
17820f 128             result = localBranches;
93f0b1 129         } else if (RpcRequest.LIST_USERS.equals(reqType)) {
JM 130             // list users
131             List<String> names = GitBlit.self().getAllUsernames();
132             List<UserModel> users = new ArrayList<UserModel>();
133             for (String name : names) {
134                 users.add(GitBlit.self().getUserModel(name));
135             }
136             result = users;
f08aab 137         } else if (RpcRequest.LIST_TEAMS.equals(reqType)) {
JM 138             // list teams
139             List<String> names = GitBlit.self().getAllTeamnames();
140             List<TeamModel> teams = new ArrayList<TeamModel>();
141             for (String name : names) {
142                 teams.add(GitBlit.self().getTeamModel(name));
143             }
144             result = teams;
31abc2 145         } else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) {
JM 146             // create repository
147             RepositoryModel model = deserialize(request, response, RepositoryModel.class);
b2fde8 148             try {
JM 149                 GitBlit.self().updateRepositoryModel(model.name, model, true);
150             } catch (GitBlitException e) {
151                 response.setStatus(failureCode);
152             }
31abc2 153         } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) {
JM 154             // edit repository
155             RepositoryModel model = deserialize(request, response, RepositoryModel.class);
bcc616 156             // name specifies original repository name in event of rename
31abc2 157             String repoName = objectName;
JM 158             if (repoName == null) {
159                 repoName = model.name;
160             }
b2fde8 161             try {
JM 162                 GitBlit.self().updateRepositoryModel(repoName, model, false);
163             } catch (GitBlitException e) {
164                 response.setStatus(failureCode);
165             }
31abc2 166         } else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) {
JM 167             // delete repository
168             RepositoryModel model = deserialize(request, response, RepositoryModel.class);
169             GitBlit.self().deleteRepositoryModel(model);
170         } else if (RpcRequest.CREATE_USER.equals(reqType)) {
171             // create user
172             UserModel model = deserialize(request, response, UserModel.class);
b2fde8 173             try {
JM 174                 GitBlit.self().updateUserModel(model.username, model, true);
175             } catch (GitBlitException e) {
176                 response.setStatus(failureCode);
177             }
31abc2 178         } else if (RpcRequest.EDIT_USER.equals(reqType)) {
JM 179             // edit user
180             UserModel model = deserialize(request, response, UserModel.class);
181             // name parameter specifies original user name in event of rename
182             String username = objectName;
183             if (username == null) {
184                 username = model.username;
185             }
b2fde8 186             try {
JM 187                 GitBlit.self().updateUserModel(username, model, false);
188             } catch (GitBlitException e) {
189                 response.setStatus(failureCode);
190             }
31abc2 191         } else if (RpcRequest.DELETE_USER.equals(reqType)) {
JM 192             // delete user
193             UserModel model = deserialize(request, response, UserModel.class);
b2fde8 194             if (!GitBlit.self().deleteUser(model.username)) {
JM 195                 response.setStatus(failureCode);
196             }
f08aab 197         } else if (RpcRequest.CREATE_TEAM.equals(reqType)) {
JM 198             // create team
199             TeamModel model = deserialize(request, response, TeamModel.class);
200             try {
201                 GitBlit.self().updateTeamModel(model.name, model, true);
202             } catch (GitBlitException e) {
203                 response.setStatus(failureCode);
204             }
205         } else if (RpcRequest.EDIT_TEAM.equals(reqType)) {
206             // edit team
207             TeamModel model = deserialize(request, response, TeamModel.class);
208             // name parameter specifies original team name in event of rename
209             String teamname = objectName;
210             if (teamname == null) {
211                 teamname = model.name;
212             }
213             try {
214                 GitBlit.self().updateTeamModel(teamname, model, false);
215             } catch (GitBlitException e) {
216                 response.setStatus(failureCode);
217             }
218         } else if (RpcRequest.DELETE_TEAM.equals(reqType)) {
219             // delete team
220             TeamModel model = deserialize(request, response, TeamModel.class);
221             if (!GitBlit.self().deleteTeam(model.name)) {
222                 response.setStatus(failureCode);
223             }
31abc2 224         } else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) {
JM 225             // get repository members
226             RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
227             result = GitBlit.self().getRepositoryUsers(model);
228         } else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) {
229             // update repository access list
230             RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
231             Collection<String> names = deserialize(request, response, RpcUtils.NAMES_TYPE);
232             List<String> users = new ArrayList<String>(names);
233             if (!GitBlit.self().setRepositoryUsers(model, users)) {
f08aab 234                 response.setStatus(failureCode);
JM 235             }
236         } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) {
237             // get repository teams
238             RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
239             result = GitBlit.self().getRepositoryTeams(model);
240         } else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) {
241             // update repository team access list
242             RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
243             Collection<String> names = deserialize(request, response, RpcUtils.NAMES_TYPE);
244             List<String> teams = new ArrayList<String>(names);
245             if (!GitBlit.self().setRepositoryTeams(model, teams)) {
b2fde8 246                 response.setStatus(failureCode);
31abc2 247             }
JM 248         } else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) {
249             // return the list of federation registrations
284a7b 250             if (allowAdmin) {
JM 251                 result = GitBlit.self().getFederationRegistrations();
252             } else {
253                 response.sendError(notAllowedCode);
254             }
31abc2 255         } else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) {
JM 256             // return the list of federation result registrations
284a7b 257             if (allowAdmin && GitBlit.canFederate()) {
31abc2 258                 result = GitBlit.self().getFederationResultRegistrations();
JM 259             } else {
b2fde8 260                 response.sendError(notAllowedCode);
31abc2 261             }
JM 262         } else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) {
263             // return the list of federation proposals
284a7b 264             if (allowAdmin && GitBlit.canFederate()) {
31abc2 265                 result = GitBlit.self().getPendingFederationProposals();
JM 266             } else {
b2fde8 267                 response.sendError(notAllowedCode);
31abc2 268             }
JM 269         } else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) {
270             // return the list of federation sets
284a7b 271             if (allowAdmin && GitBlit.canFederate()) {
31abc2 272                 String gitblitUrl = HttpUtils.getGitblitURL(request);
JM 273                 result = GitBlit.self().getFederationSets(gitblitUrl);
274             } else {
b2fde8 275                 response.sendError(notAllowedCode);
31abc2 276             }
da0269 277         } else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {
JM 278             // return the server's settings
97d3af 279             ServerSettings settings = GitBlit.self().getSettingsModel();
284a7b 280             if (allowAdmin) {
JM 281                 // return all settings
282                 result = settings;
d03aff 283             } else {
ec5a88 284                 // anonymous users get a few settings to allow browser launching
JM 285                 List<String> keys = new ArrayList<String>();
286                 keys.add(Keys.web.siteName);
287                 keys.add(Keys.web.mountParameters);
9bdb91 288                 keys.add(Keys.web.syndicationEntries);
f08aab 289
ec5a88 290                 if (allowManagement) {
JM 291                     // keys necessary for repository and/or user management
292                     keys.add(Keys.realm.minPasswordLength);
293                     keys.add(Keys.realm.passwordStorage);
294                     keys.add(Keys.federation.sets);
295                 }
296                 // build the settings
97d3af 297                 ServerSettings managementSettings = new ServerSettings();
284a7b 298                 for (String key : keys) {
JM 299                     managementSettings.add(settings.get(key));
300                 }
4bd203 301                 if (allowManagement) {
97d3af 302                     managementSettings.pushScripts = settings.pushScripts;
4bd203 303                 }
284a7b 304                 result = managementSettings;
d03aff 305             }
JM 306         } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) {
307             // update settings on the server
284a7b 308             if (allowAdmin) {
97a20e 309                 Map<String, String> settings = deserialize(request, response,
d03aff 310                         RpcUtils.SETTINGS_TYPE);
JM 311                 GitBlit.self().updateSettings(settings);
312             } else {
313                 response.sendError(notAllowedCode);
314             }
84c1d5 315         } else if (RpcRequest.LIST_STATUS.equals(reqType)) {
b75734 316             // return the server's status information
284a7b 317             if (allowAdmin) {
486ee1 318                 result = GitBlit.self().getStatus();
JM 319             } else {
320                 response.sendError(notAllowedCode);
321             }
93f0b1 322         }
JM 323
324         // send the result of the request
325         serialize(response, result);
326     }
327 }