From 813a1fab72a462bdd9387ac3f137055853a69710 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Thu, 08 May 2014 11:13:10 -0400 Subject: [PATCH] Revise, complete, and fully test the FORK rpc --- src/main/java/com/gitblit/utils/RpcUtils.java | 21 ++++-- /dev/null | 11 --- src/main/java/com/gitblit/servlet/RpcServlet.java | 50 ++++++++++------ src/test/config/test-users.conf | 1 src/main/java/com/gitblit/Constants.java | 7 +- src/site/rpc.mkd | 8 +- src/test/java/com/gitblit/tests/RpcTests.java | 69 +++++++++++++++++++++-- releases.moxie | 6 + 8 files changed, 122 insertions(+), 51 deletions(-) diff --git a/releases.moxie b/releases.moxie index aac46f0..228fc7e 100644 --- a/releases.moxie +++ b/releases.moxie @@ -11,9 +11,11 @@ security: ~ fixes: ~ changes: ~ - additions: ~ + additions: + - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) dependencyChanges: ~ - contributors: ~ + contributors: + - Manisha Gayathri } # diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index cbbc0ca..c8ce83c 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -350,10 +350,11 @@ * a client. */ public static enum RpcRequest { - // Order is important here. anything above LIST_SETTINGS requires + // Order is important here. anything after LIST_SETTINGS requires // administrator privileges and web.allowRpcManagement. - CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, LIST_SETTINGS, - CREATE_REPOSITORY, FORK_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, + CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, + FORK_REPOSITORY, LIST_SETTINGS, + CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER, LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM, LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS, diff --git a/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java b/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java deleted file mode 100644 index 122bb3b..0000000 --- a/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gitblit.models; - -/* - * 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. - */ - - -import com.gitblit.utils.StringUtils; - -import java.io.Serializable; - -public class UserRepositoryCompositeModel implements Serializable { - - private static final long serialVersionUID = 1L; - - public UserModel userModel; - public RepositoryModel repositoryModel; - - public UserModel getUserModel() { - return userModel; - } - - public void setUserModel(UserModel userModel) { - this.userModel = userModel; - } - - public RepositoryModel getRepositoryModel() { - return repositoryModel; - } - - public void setRepositoryModel(RepositoryModel repositoryModel) { - this.repositoryModel = repositoryModel; - } - -} \ No newline at end of file diff --git a/src/main/java/com/gitblit/servlet/RpcServlet.java b/src/main/java/com/gitblit/servlet/RpcServlet.java index 80c5071..b3016ad 100644 --- a/src/main/java/com/gitblit/servlet/RpcServlet.java +++ b/src/main/java/com/gitblit/servlet/RpcServlet.java @@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.gitblit.models.*; import org.eclipse.jgit.lib.Repository; import com.gitblit.Constants; @@ -36,6 +35,12 @@ import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.manager.IGitblit; +import com.gitblit.models.RefModel; +import com.gitblit.models.RegistrantAccessPermission; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.ServerSettings; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; import com.gitblit.utils.DeepCopier; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.JGitUtils; @@ -53,7 +58,7 @@ private static final long serialVersionUID = 1L; - public static final int PROTOCOL_VERSION = 7; + public static final int PROTOCOL_VERSION = 8; private IStoredSettings settings; @@ -191,22 +196,31 @@ response.setStatus(failureCode); } } else if (RpcRequest.FORK_REPOSITORY.equals(reqType)) { - // fork repository - UserRepositoryCompositeModel userRepositoryCompositeModel = deserialize(request, response, - UserRepositoryCompositeModel.class); - RepositoryModel repoModel = userRepositoryCompositeModel.getRepositoryModel(); - UserModel userModel = userRepositoryCompositeModel.getUserModel(); - try { - if (repoModel != null && userModel != null) { - gitblit.fork(repoModel, userModel); - } else { - System.out.println("Non existing user model or repo model"); - response.setStatus(failureCode); - } - - } catch (GitBlitException e) { - response.setStatus(failureCode); - } + // fork repository + RepositoryModel origin = gitblit.getRepositoryModel(objectName); + if (origin == null) { + // failed to find repository, error is logged by the repository manager + response.setStatus(failureCode); + } else { + if (user == null || !user.canFork(origin)) { + logger.error("User {} is not permitted to fork '{}'!", + user == null ? "anonymous" : user.username, objectName); + response.setStatus(failureCode); + } else { + try { + // fork the origin + RepositoryModel fork = gitblit.fork(origin, user); + if (fork == null) { + logger.error("Failed to fork repository '{}'!", objectName); + response.setStatus(failureCode); + } else { + logger.info("User {} has forked '{}'!", user.username, objectName); + } + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } + } } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) { // edit repository RepositoryModel model = deserialize(request, response, RepositoryModel.class); diff --git a/src/main/java/com/gitblit/utils/RpcUtils.java b/src/main/java/com/gitblit/utils/RpcUtils.java index 904461c..8220215 100644 --- a/src/main/java/com/gitblit/utils/RpcUtils.java +++ b/src/main/java/com/gitblit/utils/RpcUtils.java @@ -25,7 +25,16 @@ import com.gitblit.Constants; import com.gitblit.Constants.RpcRequest; import com.gitblit.GitBlitException.UnknownRequestException; -import com.gitblit.models.*; +import com.gitblit.models.FederationModel; +import com.gitblit.models.FederationProposal; +import com.gitblit.models.FederationSet; +import com.gitblit.models.FeedModel; +import com.gitblit.models.RegistrantAccessPermission; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.ServerSettings; +import com.gitblit.models.ServerStatus; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; import com.google.gson.reflect.TypeToken; /** @@ -195,20 +204,16 @@ } /** - * Create a fork of an already existing repo + * Create a fork of a repository. * * @param repository - * @param user * @return true if the action succeeded * @throws IOException */ - public static boolean forkRpository(RepositoryModel repository, UserModel user, String serverUrl, + public static boolean forkRepository(RepositoryModel repository, String serverUrl, String account, char[] password) throws IOException { - UserRepositoryCompositeModel userRepositoryCompositeModel = new UserRepositoryCompositeModel(); - userRepositoryCompositeModel.setRepositoryModel(repository); - userRepositoryCompositeModel.setUserModel(user); - return doAction(RpcRequest.FORK_REPOSITORY, null, userRepositoryCompositeModel, serverUrl, account, password); + return doAction(RpcRequest.FORK_REPOSITORY, repository.name, null, serverUrl, account, password); } diff --git a/src/site/rpc.mkd b/src/site/rpc.mkd index b86fd9a..2e502e2 100644 --- a/src/site/rpc.mkd +++ b/src/site/rpc.mkd @@ -57,9 +57,10 @@ <tr><td>Gitblit v0.8.0</td><td>2</td></tr> <tr><td>Gitblit v0.9.0 - v1.0.0</td><td>3</td></tr> <tr><td>Gitblit v1.1.0</td><td>4</td></tr> -<tr><td>Gitblit v1.2.0+</td><td>5</td></tr> -<tr><td>Gitblit v1.3.1+</td><td>6</td></tr> -<tr><td>Gitblit v1.4.0+</td><td>7</td></tr> +<tr><td>Gitblit v1.2.0</td><td>5</td></tr> +<tr><td>Gitblit v1.3.1</td><td>6</td></tr> +<tr><td>Gitblit v1.4.0</td><td>7</td></tr> +<tr><td>Gitblit v1.6.0</td><td>8</td></tr> </tbody> </table> @@ -81,6 +82,7 @@ <tr><td>LIST_BRANCHES</td><td>-</td><td>-</td><td>1</td><td>-</td><td>Map<String, List<String>></td></tr> <tr><td>LIST_SETTINGS</td><td>-</td><td><em>-</em></td><td>1</td><td>-</td><td>ServerSettings (basic keys)</td></tr> <tr><td>GET_USER</td><td>user name</td><td>-</td><td>6</td><td>-</td><td>UserModel</td></tr> +<tr><td>FORK_REPOSITORY</td><td>repository name</td><td><em>-</em></td><td>8</td><td>-</td><td>-</td></tr> <tr><td colspan='6'><em>web.enableRpcManagement=true</em></td></tr> <tr><td>CREATE_REPOSITORY</td><td>repository name</td><td><em>admin</em></td><td>1</td><td>RepositoryModel</td><td>-</td></tr> <tr><td>EDIT_REPOSITORY</td><td>repository name</td><td><em>admin</em></td><td>1</td><td>RepositoryModel</td><td>-</td></tr> diff --git a/src/test/config/test-users.conf b/src/test/config/test-users.conf index 4e00903..1d01f84 100644 --- a/src/test/config/test-users.conf +++ b/src/test/config/test-users.conf @@ -6,6 +6,7 @@ role = "#notfederated" [user "sampleuser"] password = sampleuser + cookie = 6e07ed42149fc166206319faffdfba2e2ec82e43 accountType = LOCAL role = "#none" [team "admins"] diff --git a/src/test/java/com/gitblit/tests/RpcTests.java b/src/test/java/com/gitblit/tests/RpcTests.java index 943153d..51b4671 100644 --- a/src/test/java/com/gitblit/tests/RpcTests.java +++ b/src/test/java/com/gitblit/tests/RpcTests.java @@ -191,12 +191,6 @@ assertEquals(AccessRestrictionType.VIEW, retrievedRepository.accessRestriction); assertEquals(AuthorizationControl.AUTHENTICATED, retrievedRepository.authorizationControl); - //fork repo - UserModel userModel = new UserModel("garbageUser"); - assertTrue("Failed to create Fork Repository!", - RpcUtils.forkRpository(model, userModel, url, account, password.toCharArray())); - - // rename and change access restriciton String originalName = model.name; model.name = "garbagerepo2.git"; @@ -403,4 +397,67 @@ assertNotNull(branches); assertTrue(branches.size() > 0); } + + @Test + public void testFork() throws Exception { + // test forking by an administrator + // admins are all-powerful and can fork the unforakable :) + testFork(account, password, true, true); + testFork(account, password, false, true); + + // test forking by a permitted normal user + UserModel forkUser = new UserModel("forkuser"); + forkUser.password = forkUser.username; + forkUser.canFork = true; + RpcUtils.deleteUser(forkUser, url, account, password.toCharArray()); + RpcUtils.createUser(forkUser, url, account, password.toCharArray()); + testFork(forkUser.username, forkUser.password, true, true); + testFork(forkUser.username, forkUser.password, false, false); + RpcUtils.deleteUser(forkUser, url, account, password.toCharArray()); + + // test forking by a non-permitted normal user + UserModel noForkUser = new UserModel("noforkuser"); + noForkUser.password = noForkUser.username; + noForkUser.canFork = false; + RpcUtils.deleteUser(noForkUser, url, account, password.toCharArray()); + RpcUtils.createUser(noForkUser, url, account, password.toCharArray()); + testFork(forkUser.username, forkUser.password, true, false); + testFork(forkUser.username, forkUser.password, false, false); + RpcUtils.deleteUser(noForkUser, url, account, password.toCharArray()); + } + + private void testFork(String forkAcct, String forkAcctPassword, boolean allowForks, boolean expectSuccess) throws Exception { + // test does not exist + RepositoryModel dne = new RepositoryModel(); + dne.name = "doesNotExist.git"; + assertFalse(String.format("Successfully forked %s!", dne.name), + RpcUtils.forkRepository(dne, url, forkAcct, forkAcctPassword.toCharArray())); + + // delete any previous fork + RepositoryModel fork = findRepository(String.format("~%s/helloworld.git", forkAcct)); + if (fork != null) { + RpcUtils.deleteRepository(fork, url, account, password.toCharArray()); + } + + // update the origin to allow forks or not + RepositoryModel origin = findRepository("helloworld.git"); + origin.allowForks = allowForks; + RpcUtils.updateRepository(origin.name, origin, url, account, password.toCharArray()); + + // fork the repository + if (expectSuccess) { + assertTrue(String.format("Failed to fork %s!", origin.name), + RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray())); + } else { + assertFalse(String.format("Successfully forked %s!", origin.name), + RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray())); + } + + // attempt another fork + assertFalse(String.format("Successfully forked %s!", origin.name), + RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray())); + + // delete the fork repository + RpcUtils.deleteRepository(fork, url, account, password.toCharArray()); + } } diff --git a/src/test/java/com/gitblit/tests/Test.java b/src/test/java/com/gitblit/tests/Test.java deleted file mode 100644 index 275c6b4..0000000 --- a/src/test/java/com/gitblit/tests/Test.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gitblit.tests; - -/** - * Created with IntelliJ IDEA. - * User: manisha - * Date: 3/21/14 - * Time: 12:03 PM - * To change this template use File | Settings | File Templates. - */ -public @interface Test { -} -- Gitblit v1.9.1