This is an automated email from the git hooks/post-receive script. New commit to branch feature/GIT in repository scmwebeditor. See http://git.nuiton.org/scmwebeditor.git commit 2533ad9fa6b84349686ae2208d9bc9794c0593a8 Author: Hugo PIGEON <hpigeon@codelutin.com> Date: Tue Apr 28 15:09:02 2015 +0200 It is now possible to use Git repositories which need authentication --- .../org/nuiton/scmwebeditor/GitConnection.java | 305 +++++++++++++++------ .../org/nuiton/scmwebeditor/SvnConnection.java | 9 +- .../actions/ScmWebEditorMainAction.java | 2 +- .../nuiton/scmwebeditor/actions/SearchAction.java | 16 +- src/main/webapp/WEB-INF/content/loginSearch.jsp | 4 +- src/main/webapp/js/branches.js | 5 +- 6 files changed, 248 insertions(+), 93 deletions(-) diff --git a/src/main/java/org/nuiton/scmwebeditor/GitConnection.java b/src/main/java/org/nuiton/scmwebeditor/GitConnection.java index 304b988..3731baf 100644 --- a/src/main/java/org/nuiton/scmwebeditor/GitConnection.java +++ b/src/main/java/org/nuiton/scmwebeditor/GitConnection.java @@ -43,6 +43,7 @@ import org.nuiton.scmwebeditor.actions.ScmWebEditorCommitAction; import org.nuiton.scmwebeditor.actions.SearchAction; import org.nuiton.scmwebeditor.actions.UploadAction; +import javax.naming.AuthenticationException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -66,6 +67,9 @@ public class GitConnection implements ScmConnection { /** the name of the file to edit */ protected String fileName; + /** the id of the HTTP session */ + protected String sessionId; + protected static final String MASTER_BRANCH = "master"; @@ -83,96 +87,38 @@ public class GitConnection implements ScmConnection { fileName = address.substring(address.lastIndexOf("/") + 1); } - // Cloning the remote repository to a local directory - String localReposPath = ScmWebEditorConfig.getLocalRepositoriesPath(); - String hashedAddress = addressGit; - - try { - MessageDigest md = MessageDigest.getInstance("SHA-512"); - md.update(addressGit.getBytes()); - byte byteData[] = md.digest(); - - StringBuffer sb = new StringBuffer(); - for (int i = 0 ; i < byteData.length ; i++) { - String hexByte = Integer.toString((byteData[i] & 0xff) + 0x100, 16); - hexByte = hexByte.substring(1); - sb.append(hexByte); - } - - hashedAddress = sb.toString(); - if (log.isDebugEnabled()) { - log.debug("hashed address " + addressGit + " : " + hashedAddress); - } - } catch (NoSuchAlgorithmException e) { - log.error("Can not hash the repository address : the algorithm does not exist", e); - } + this.sessionId = sessionId; + } - localDirectory = new File(localReposPath + "/" + sessionId + "/" + hashedAddress); - // We don't need to clone the repository if we already have the last version - boolean cloneNeeded = false; - - if (!localDirectory.exists()) { - cloneNeeded = true; - } else { - Git git = Git.open(localDirectory); - DiffCommand diff = git.diff(); - try { - - List<DiffEntry> diffs = diff.call(); + @Override + public String search(SearchAction action) { - // If there are differences, we delete the current version and clone the last one - if(diffs.size() > 0) { - FileUtils.deleteDirectory(localDirectory); - cloneNeeded = true; - if (log.isDebugEnabled()) { - log.debug("The current version is not the last one, cloning is required"); - } - } else { + try { + cloneRepository(action.getUsername(), action.getPw()); + } catch (ScmNotFoundException e) { - if (log.isDebugEnabled()) { - log.debug("The current version is the last one, cloning is not required"); - } - } - } catch (GitAPIException e) { - if (log.isErrorEnabled()) { - log.error("The repository at address " + addressGit + " doesn't exist", e); - } + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); } - } + action.setError(true); + return action.SUCCESS; - if (cloneNeeded) { - CloneCommand clone = Git.cloneRepository(); - clone.setURI(addressGit); - clone.setDirectory(localDirectory); - try { - clone.call(); - } catch (GitAPIException e) { - if (log.isErrorEnabled()) { - log.error("Can't clone the remote repository"); - } - throw new ScmNotFoundException("Can not find a Git repository at address " + addressGit); - } - } + } catch (IOException e) { - // Connection to the local repository - File gitFile = new File(localDirectory.getAbsolutePath() + "/.git"); - FileRepositoryBuilder gitRepoBuilder = new FileRepositoryBuilder(); - gitRepoBuilder.setGitDir(gitFile); - gitRepo = gitRepoBuilder.build(); + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + action.setError(true); + return action.SUCCESS; - if (!gitRepo.getObjectDatabase().exists()) { + } catch (AuthenticationException e) { if (log.isErrorEnabled()) { - log.error("The repository at address " + addressGit + " doesn't exist"); - throw new ScmNotFoundException("The repository at address " + addressGit + " doesn't exist"); + log.error("Error while cloning the repository", e); } + return action.AUTH_ERROR; } - } - - - @Override - public String search(SearchAction action) { String url; @@ -314,6 +260,30 @@ public class GitConnection implements ScmConnection { @Override public String commit(ScmWebEditorCommitAction action) { + try { + cloneRepository(action.getUsername(), action.getPw()); + } catch (ScmNotFoundException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + return action.SUCCESS; + + } catch (IOException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + return action.SUCCESS; + + } catch (AuthenticationException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + return action.LOGIN; + } + if (log.isDebugEnabled()) { log.debug("Entering Git commit"); } @@ -440,6 +410,30 @@ public class GitConnection implements ScmConnection { @Override public String uploadFile(UploadAction action) { + try { + cloneRepository(action.getUsername(), action.getPw()); + } catch (ScmNotFoundException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + return action.SUCCESS; + + } catch (IOException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + return action.SUCCESS; + + } catch (AuthenticationException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + return action.SUCCESS; + } + action.setFileRoot(addressGit); action.setScmRoot(addressGit); @@ -570,7 +564,22 @@ public class GitConnection implements ScmConnection { @Override - public String getFileContent(String path, String username, String password) { + public String getFileContent(String path, String username, String password) throws AuthenticationException { + + try { + cloneRepository(username, password); + } catch (ScmNotFoundException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + + } catch (IOException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + } File fileToEdit = new File(localDirectory.getAbsolutePath() + "/" + fileName); @@ -587,7 +596,22 @@ public class GitConnection implements ScmConnection { } @Override - public String getHeadRevisionNumber(String path, String username, String password) { + public String getHeadRevisionNumber(String path, String username, String password) throws AuthenticationException { + + try { + cloneRepository(username, password); + } catch (ScmNotFoundException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + + } catch (IOException e) { + + if (log.isErrorEnabled()) { + log.error("Error while cloning the repository", e); + } + } Git git = null; @@ -629,14 +653,17 @@ public class GitConnection implements ScmConnection { * @param address the URL to the remote repository * @return a list of the repository's branches */ - public static List<String> getBranches(String address) { + public static List<String> getBranches(String address, String username, String password) { List<String> branches = new ArrayList<String>(); + CredentialsProvider credentials = new UsernamePasswordCredentialsProvider(username, password); + LsRemoteCommand lsRemote = new LsRemoteCommand(null); lsRemote.setRemote(address); lsRemote.setTags(false); lsRemote.setHeads(true); + lsRemote.setCredentialsProvider(credentials); try { Collection<Ref> lsRemoteResult = lsRemote.call(); @@ -691,4 +718,120 @@ public class GitConnection implements ScmConnection { } } } + + + public void cloneRepository(String username, String password) + throws ScmNotFoundException, IOException, AuthenticationException { + + // Cloning the remote repository to a local directory + String localReposPath = ScmWebEditorConfig.getLocalRepositoriesPath(); + String hashedAddress = addressGit; + + try { + MessageDigest md = MessageDigest.getInstance("SHA-512"); + md.update(addressGit.getBytes()); + byte byteData[] = md.digest(); + + StringBuffer sb = new StringBuffer(); + for (int i = 0 ; i < byteData.length ; i++) { + String hexByte = Integer.toString((byteData[i] & 0xff) + 0x100, 16); + hexByte = hexByte.substring(1); + sb.append(hexByte); + } + + hashedAddress = sb.toString(); + if (log.isDebugEnabled()) { + log.debug("hashed address " + addressGit + " : " + hashedAddress); + } + } catch (NoSuchAlgorithmException e) { + log.error("Can not hash the repository address : the algorithm does not exist", e); + } + + localDirectory = new File(localReposPath + "/" + sessionId + "/" + hashedAddress); + + // We don't need to clone the repository if we already have the last version + boolean cloneNeeded = false; + + if (!localDirectory.exists()) { + cloneNeeded = true; + } else { + Git git = Git.open(localDirectory); + DiffCommand diff = git.diff(); + try { + + List<DiffEntry> diffs = diff.call(); + + // If there are differences, we delete the current version and clone the last one + if(diffs.size() > 0) { + FileUtils.deleteDirectory(localDirectory); + cloneNeeded = true; + if (log.isDebugEnabled()) { + log.debug("The current version is not the last one, cloning is required"); + } + } else { + + if (log.isDebugEnabled()) { + log.debug("The current version is the last one, cloning is not required"); + } + } + } catch (GitAPIException e) { + if (log.isErrorEnabled()) { + log.error("The repository at address " + addressGit + " doesn't exist", e); + } + } + } + + if (cloneNeeded) { + + if (log.isDebugEnabled()) { + log.debug("Cloning : username == " + username + " ; password == " + password); + } + + CredentialsProvider credentials = new UsernamePasswordCredentialsProvider(username, password); + + CloneCommand clone = Git.cloneRepository(); + clone.setURI(addressGit); + clone.setDirectory(localDirectory); + clone.setCredentialsProvider(credentials); + try { + clone.call(); + } catch (InvalidRemoteException e) { + FileUtils.deleteDirectory(localDirectory); + if (log.isErrorEnabled()) { + log.error("Can't clone the remote repository", e); + } + } catch (TransportException e) { + FileUtils.deleteDirectory(localDirectory); + if (log.isErrorEnabled()) { + log.error("Can't clone the remote repository", e); + } + throw new AuthenticationException("Can not clone the Git repository : auth failed"); + } catch (GitAPIException e) { + FileUtils.deleteDirectory(localDirectory); + if (log.isErrorEnabled()) { + log.error("Can't clone the remote repository", e); + } + throw new ScmNotFoundException("Can not find a Git repository at address " + addressGit); + } + } + + + if (log.isDebugEnabled()) { + log.debug("Connection to local repostitory"); + } + + // Connection to the local repository + File gitFile = new File(localDirectory.getAbsolutePath() + "/.git"); + FileRepositoryBuilder gitRepoBuilder = new FileRepositoryBuilder(); + gitRepoBuilder.setGitDir(gitFile); + gitRepo = gitRepoBuilder.build(); + + if (!gitRepo.getObjectDatabase().exists()) { + + if (log.isErrorEnabled()) { + log.error("The repository at address " + addressGit + " doesn't exist"); + throw new ScmNotFoundException("The repository at address " + addressGit + " doesn't exist"); + } + } + } } diff --git a/src/main/java/org/nuiton/scmwebeditor/SvnConnection.java b/src/main/java/org/nuiton/scmwebeditor/SvnConnection.java index 2d5f7e1..25040bd 100644 --- a/src/main/java/org/nuiton/scmwebeditor/SvnConnection.java +++ b/src/main/java/org/nuiton/scmwebeditor/SvnConnection.java @@ -108,13 +108,8 @@ public class SvnConnection implements ScmConnection { SVNRepository repository; ISVNAuthenticationManager authManager; - String name = "anonymous"; - String password = "anonymous"; - - if (action.getUsername() != null && action.getPw() != null) { - name = action.getUsername(); - password = action.getPw(); - } + String name = action.getUsername(); + String password = action.getPw(); if (action.getId().equals("")) { diff --git a/src/main/java/org/nuiton/scmwebeditor/actions/ScmWebEditorMainAction.java b/src/main/java/org/nuiton/scmwebeditor/actions/ScmWebEditorMainAction.java index 07ee875..2bd1635 100644 --- a/src/main/java/org/nuiton/scmwebeditor/actions/ScmWebEditorMainAction.java +++ b/src/main/java/org/nuiton/scmwebeditor/actions/ScmWebEditorMainAction.java @@ -335,7 +335,7 @@ public class ScmWebEditorMainAction extends ScmWebEditorBaseAction implements Se } catch (AuthenticationException e) { request.setAttribute(PARAMETER_ADDRESS, address); - // if svn authentication failed user is redirected on login page + // if scm authentication failed user is redirected on login page if (log.isDebugEnabled()) { log.debug("Auth Fail ", e); } diff --git a/src/main/java/org/nuiton/scmwebeditor/actions/SearchAction.java b/src/main/java/org/nuiton/scmwebeditor/actions/SearchAction.java index fdd4d52..7ac6bca 100644 --- a/src/main/java/org/nuiton/scmwebeditor/actions/SearchAction.java +++ b/src/main/java/org/nuiton/scmwebeditor/actions/SearchAction.java @@ -127,6 +127,13 @@ public class SearchAction extends ScmWebEditorBaseAction { address = address.substring(0, address.length() - 1); } + if (username == null) { + username = "anonymous"; + } + if (pw == null) { + pw = "anonymous"; + } + // connection to the repository HttpSession session = request.getSession(); String sessionId = session.getId(); @@ -222,7 +229,14 @@ public class SearchAction extends ScmWebEditorBaseAction { public String getBranchesJSON() { - branches = GitConnection.getBranches(address); + if (username == null) { + username = "anonymous"; + } + if (pw == null) { + pw = "anonymous"; + } + + branches = GitConnection.getBranches(address, username, pw); String json = ""; if (branches.size() > 0) { diff --git a/src/main/webapp/WEB-INF/content/loginSearch.jsp b/src/main/webapp/WEB-INF/content/loginSearch.jsp index 0d1602c..c2874d6 100644 --- a/src/main/webapp/WEB-INF/content/loginSearch.jsp +++ b/src/main/webapp/WEB-INF/content/loginSearch.jsp @@ -31,9 +31,9 @@ <p> <label><s:text name="scm.username"/> : <input type="text" - name="username"></input></label><br/> + name="username" id="username"></input></label><br/> <label><s:text name="scm.password"/> : <input type="password" - name="pw"></input></label><br/> + name="pw" id="pw"></input></label><br/> <s:url id="ajaxSearchLogin" value="search.action"/> diff --git a/src/main/webapp/js/branches.js b/src/main/webapp/js/branches.js index 689311d..03f1b4e 100644 --- a/src/main/webapp/js/branches.js +++ b/src/main/webapp/js/branches.js @@ -5,12 +5,15 @@ $(document).ready(function() { var listSelect = $("#branchesList"); var address = $("#addressInput").val(); var scmType = $("#scmType").val(); + var username = $("#username").val(); + var pw = $("#pw").val(); if (scmType == "Git") { listSelect.find("option:gt(0)").remove(); - $.getJSON("getBranches.action?address=" + address + "&scmType=" + scmType, function(result) { + $.getJSON("getBranches.action?address=" + address + "&scmType=" + scmType + + "&username=" + username + "&pw=" + pw, function(result) { $.each(result.branches, function(i, field) { listSelect.append("<option>" + field + "</option>"); }); -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.