You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RpcServlet.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  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.servlet;
  17. import java.io.IOException;
  18. import java.text.MessageFormat;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;
  24. import javax.inject.Inject;
  25. import javax.inject.Singleton;
  26. import javax.servlet.ServletException;
  27. import javax.servlet.http.HttpServletRequest;
  28. import javax.servlet.http.HttpServletResponse;
  29. import org.eclipse.jgit.lib.Repository;
  30. import com.gitblit.Constants;
  31. import com.gitblit.Constants.RpcRequest;
  32. import com.gitblit.GitBlitException;
  33. import com.gitblit.IStoredSettings;
  34. import com.gitblit.Keys;
  35. import com.gitblit.manager.IFederationManager;
  36. import com.gitblit.manager.IGitblitManager;
  37. import com.gitblit.manager.IRepositoryManager;
  38. import com.gitblit.manager.IRuntimeManager;
  39. import com.gitblit.manager.IUserManager;
  40. import com.gitblit.models.RefModel;
  41. import com.gitblit.models.RegistrantAccessPermission;
  42. import com.gitblit.models.RepositoryModel;
  43. import com.gitblit.models.ServerSettings;
  44. import com.gitblit.models.TeamModel;
  45. import com.gitblit.models.UserModel;
  46. import com.gitblit.utils.DeepCopier;
  47. import com.gitblit.utils.HttpUtils;
  48. import com.gitblit.utils.JGitUtils;
  49. import com.gitblit.utils.RpcUtils;
  50. import com.gitblit.utils.StringUtils;
  51. /**
  52. * Handles remote procedure calls.
  53. *
  54. * @author James Moger
  55. *
  56. */
  57. @Singleton
  58. public class RpcServlet extends JsonServlet {
  59. private static final long serialVersionUID = 1L;
  60. public static final int PROTOCOL_VERSION = 6;
  61. private final IStoredSettings settings;
  62. private final IRuntimeManager runtimeManager;
  63. private final IUserManager userManager;
  64. private final IRepositoryManager repositoryManager;
  65. private final IFederationManager federationManager;
  66. private final IGitblitManager gitblitManager;
  67. @Inject
  68. public RpcServlet(
  69. IRuntimeManager runtimeManager,
  70. IUserManager userManager,
  71. IRepositoryManager repositoryManager,
  72. IFederationManager federationManager,
  73. IGitblitManager gitblitManager) {
  74. super();
  75. this.settings = runtimeManager.getSettings();
  76. this.runtimeManager = runtimeManager;
  77. this.userManager = userManager;
  78. this.repositoryManager = repositoryManager;
  79. this.federationManager = federationManager;
  80. this.gitblitManager = gitblitManager;
  81. }
  82. /**
  83. * Processes an rpc request.
  84. *
  85. * @param request
  86. * @param response
  87. * @throws javax.servlet.ServletException
  88. * @throws java.io.IOException
  89. */
  90. @Override
  91. protected void processRequest(HttpServletRequest request, HttpServletResponse response)
  92. throws ServletException, IOException {
  93. RpcRequest reqType = RpcRequest.fromName(request.getParameter("req"));
  94. String objectName = request.getParameter("name");
  95. logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType,
  96. request.getRemoteAddr()));
  97. UserModel user = (UserModel) request.getUserPrincipal();
  98. boolean allowManagement = user != null && user.canAdmin()
  99. && settings.getBoolean(Keys.web.enableRpcManagement, false);
  100. boolean allowAdmin = user != null && user.canAdmin()
  101. && settings.getBoolean(Keys.web.enableRpcAdministration, false);
  102. Object result = null;
  103. if (RpcRequest.GET_PROTOCOL.equals(reqType)) {
  104. // Return the protocol version
  105. result = PROTOCOL_VERSION;
  106. } else if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) {
  107. // Determine the Gitblit clone url
  108. String gitblitUrl = HttpUtils.getGitblitURL(request);
  109. StringBuilder sb = new StringBuilder();
  110. sb.append(gitblitUrl);
  111. sb.append(Constants.R_PATH);
  112. sb.append("{0}");
  113. String cloneUrl = sb.toString();
  114. // list repositories
  115. List<RepositoryModel> list = repositoryManager.getRepositoryModels(user);
  116. Map<String, RepositoryModel> repositories = new HashMap<String, RepositoryModel>();
  117. for (RepositoryModel model : list) {
  118. String url = MessageFormat.format(cloneUrl, model.name);
  119. repositories.put(url, model);
  120. }
  121. result = repositories;
  122. } else if (RpcRequest.LIST_BRANCHES.equals(reqType)) {
  123. // list all local branches in all repositories accessible to user
  124. Map<String, List<String>> localBranches = new HashMap<String, List<String>>();
  125. List<RepositoryModel> models = repositoryManager.getRepositoryModels(user);
  126. for (RepositoryModel model : models) {
  127. if (!model.hasCommits) {
  128. // skip empty repository
  129. continue;
  130. }
  131. if (model.isCollectingGarbage) {
  132. // skip garbage collecting repository
  133. logger.warn(MessageFormat.format("Temporarily excluding {0} from RPC, busy collecting garbage", model.name));
  134. continue;
  135. }
  136. // get local branches
  137. Repository repository = repositoryManager.getRepository(model.name);
  138. List<RefModel> refs = JGitUtils.getLocalBranches(repository, false, -1);
  139. if (model.showRemoteBranches) {
  140. // add remote branches if repository displays them
  141. refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1));
  142. }
  143. if (refs.size() > 0) {
  144. List<String> branches = new ArrayList<String>();
  145. for (RefModel ref : refs) {
  146. branches.add(ref.getName());
  147. }
  148. localBranches.put(model.name, branches);
  149. }
  150. repository.close();
  151. }
  152. result = localBranches;
  153. } else if (RpcRequest.GET_USER.equals(reqType)) {
  154. if (StringUtils.isEmpty(objectName)) {
  155. if (UserModel.ANONYMOUS.equals(user)) {
  156. response.sendError(forbiddenCode);
  157. } else {
  158. // return the current user, reset credentials
  159. UserModel requestedUser = DeepCopier.copy(user);
  160. result = requestedUser;
  161. }
  162. } else {
  163. if (user.canAdmin() || objectName.equals(user.username)) {
  164. // return the specified user
  165. UserModel requestedUser = userManager.getUserModel(objectName);
  166. if (requestedUser == null) {
  167. response.setStatus(failureCode);
  168. } else {
  169. result = requestedUser;
  170. }
  171. } else {
  172. response.sendError(forbiddenCode);
  173. }
  174. }
  175. } else if (RpcRequest.LIST_USERS.equals(reqType)) {
  176. // list users
  177. List<String> names = userManager.getAllUsernames();
  178. List<UserModel> users = new ArrayList<UserModel>();
  179. for (String name : names) {
  180. users.add(userManager.getUserModel(name));
  181. }
  182. result = users;
  183. } else if (RpcRequest.LIST_TEAMS.equals(reqType)) {
  184. // list teams
  185. List<String> names = userManager.getAllTeamNames();
  186. List<TeamModel> teams = new ArrayList<TeamModel>();
  187. for (String name : names) {
  188. teams.add(userManager.getTeamModel(name));
  189. }
  190. result = teams;
  191. } else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) {
  192. // create repository
  193. RepositoryModel model = deserialize(request, response, RepositoryModel.class);
  194. try {
  195. repositoryManager.updateRepositoryModel(model.name, model, true);
  196. } catch (GitBlitException e) {
  197. response.setStatus(failureCode);
  198. }
  199. } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) {
  200. // edit repository
  201. RepositoryModel model = deserialize(request, response, RepositoryModel.class);
  202. // name specifies original repository name in event of rename
  203. String repoName = objectName;
  204. if (repoName == null) {
  205. repoName = model.name;
  206. }
  207. try {
  208. repositoryManager.updateRepositoryModel(repoName, model, false);
  209. } catch (GitBlitException e) {
  210. response.setStatus(failureCode);
  211. }
  212. } else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) {
  213. // delete repository
  214. RepositoryModel model = deserialize(request, response, RepositoryModel.class);
  215. repositoryManager.deleteRepositoryModel(model);
  216. } else if (RpcRequest.CREATE_USER.equals(reqType)) {
  217. // create user
  218. UserModel model = deserialize(request, response, UserModel.class);
  219. try {
  220. gitblitManager.updateUserModel(model.username, model, true);
  221. } catch (GitBlitException e) {
  222. response.setStatus(failureCode);
  223. }
  224. } else if (RpcRequest.EDIT_USER.equals(reqType)) {
  225. // edit user
  226. UserModel model = deserialize(request, response, UserModel.class);
  227. // name parameter specifies original user name in event of rename
  228. String username = objectName;
  229. if (username == null) {
  230. username = model.username;
  231. }
  232. try {
  233. gitblitManager.updateUserModel(username, model, false);
  234. } catch (GitBlitException e) {
  235. response.setStatus(failureCode);
  236. }
  237. } else if (RpcRequest.DELETE_USER.equals(reqType)) {
  238. // delete user
  239. UserModel model = deserialize(request, response, UserModel.class);
  240. if (!userManager.deleteUser(model.username)) {
  241. response.setStatus(failureCode);
  242. }
  243. } else if (RpcRequest.CREATE_TEAM.equals(reqType)) {
  244. // create team
  245. TeamModel model = deserialize(request, response, TeamModel.class);
  246. try {
  247. gitblitManager.updateTeamModel(model.name, model, true);
  248. } catch (GitBlitException e) {
  249. response.setStatus(failureCode);
  250. }
  251. } else if (RpcRequest.EDIT_TEAM.equals(reqType)) {
  252. // edit team
  253. TeamModel model = deserialize(request, response, TeamModel.class);
  254. // name parameter specifies original team name in event of rename
  255. String teamname = objectName;
  256. if (teamname == null) {
  257. teamname = model.name;
  258. }
  259. try {
  260. gitblitManager.updateTeamModel(teamname, model, false);
  261. } catch (GitBlitException e) {
  262. response.setStatus(failureCode);
  263. }
  264. } else if (RpcRequest.DELETE_TEAM.equals(reqType)) {
  265. // delete team
  266. TeamModel model = deserialize(request, response, TeamModel.class);
  267. if (!userManager.deleteTeam(model.name)) {
  268. response.setStatus(failureCode);
  269. }
  270. } else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) {
  271. // get repository members
  272. RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
  273. result = repositoryManager.getRepositoryUsers(model);
  274. } else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) {
  275. // rejected since 1.2.0
  276. response.setStatus(failureCode);
  277. } else if (RpcRequest.LIST_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) {
  278. // get repository member permissions
  279. RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
  280. result = repositoryManager.getUserAccessPermissions(model);
  281. } else if (RpcRequest.SET_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) {
  282. // set the repository permissions for the specified users
  283. RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
  284. Collection<RegistrantAccessPermission> permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
  285. result = repositoryManager.setUserAccessPermissions(model, permissions);
  286. } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) {
  287. // get repository teams
  288. RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
  289. result = repositoryManager.getRepositoryTeams(model);
  290. } else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) {
  291. // rejected since 1.2.0
  292. response.setStatus(failureCode);
  293. } else if (RpcRequest.LIST_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) {
  294. // get repository team permissions
  295. RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
  296. result = repositoryManager.getTeamAccessPermissions(model);
  297. } else if (RpcRequest.SET_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) {
  298. // set the repository permissions for the specified teams
  299. RepositoryModel model = repositoryManager.getRepositoryModel(objectName);
  300. Collection<RegistrantAccessPermission> permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
  301. result = repositoryManager.setTeamAccessPermissions(model, permissions);
  302. } else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) {
  303. // return the list of federation registrations
  304. if (allowAdmin) {
  305. result = federationManager.getFederationRegistrations();
  306. } else {
  307. response.sendError(notAllowedCode);
  308. }
  309. } else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) {
  310. // return the list of federation result registrations
  311. if (allowAdmin && federationManager.canFederate()) {
  312. result = federationManager.getFederationResultRegistrations();
  313. } else {
  314. response.sendError(notAllowedCode);
  315. }
  316. } else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) {
  317. // return the list of federation proposals
  318. if (allowAdmin && federationManager.canFederate()) {
  319. result = federationManager.getPendingFederationProposals();
  320. } else {
  321. response.sendError(notAllowedCode);
  322. }
  323. } else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) {
  324. // return the list of federation sets
  325. if (allowAdmin && federationManager.canFederate()) {
  326. String gitblitUrl = HttpUtils.getGitblitURL(request);
  327. result = federationManager.getFederationSets(gitblitUrl);
  328. } else {
  329. response.sendError(notAllowedCode);
  330. }
  331. } else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {
  332. // return the server's settings
  333. ServerSettings serverSettings = runtimeManager.getSettingsModel();
  334. if (allowAdmin) {
  335. // return all settings
  336. result = serverSettings;
  337. } else {
  338. // anonymous users get a few settings to allow browser launching
  339. List<String> keys = new ArrayList<String>();
  340. keys.add(Keys.web.siteName);
  341. keys.add(Keys.web.mountParameters);
  342. keys.add(Keys.web.syndicationEntries);
  343. if (allowManagement) {
  344. // keys necessary for repository and/or user management
  345. keys.add(Keys.realm.minPasswordLength);
  346. keys.add(Keys.realm.passwordStorage);
  347. keys.add(Keys.federation.sets);
  348. }
  349. // build the settings
  350. ServerSettings managementSettings = new ServerSettings();
  351. for (String key : keys) {
  352. managementSettings.add(serverSettings.get(key));
  353. }
  354. if (allowManagement) {
  355. managementSettings.pushScripts = serverSettings.pushScripts;
  356. }
  357. result = managementSettings;
  358. }
  359. } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) {
  360. // update settings on the server
  361. if (allowAdmin) {
  362. Map<String, String> map = deserialize(request, response,
  363. RpcUtils.SETTINGS_TYPE);
  364. runtimeManager.updateSettings(map);
  365. } else {
  366. response.sendError(notAllowedCode);
  367. }
  368. } else if (RpcRequest.LIST_STATUS.equals(reqType)) {
  369. // return the server's status information
  370. if (allowAdmin) {
  371. result = runtimeManager.getStatus();
  372. } else {
  373. response.sendError(notAllowedCode);
  374. }
  375. } else if (RpcRequest.CLEAR_REPOSITORY_CACHE.equals(reqType)) {
  376. // clear the repository list cache
  377. if (allowManagement) {
  378. repositoryManager.resetRepositoryListCache();
  379. } else {
  380. response.sendError(notAllowedCode);
  381. }
  382. }
  383. // send the result of the request
  384. serialize(response, result);
  385. }
  386. }