src/main/java/com/gitblit/transport/ssh/WelcomeShell.java
@@ -113,36 +113,71 @@ String getMessage() { SshDaemonClient client = session.getAttribute(SshDaemonClient.KEY); UserModel user = client.getUser(); String hostname = getHostname(); int port = settings.getInteger(Keys.git.sshPort, 0); final String b1 = StringUtils.rightPad("", 72, '═'); final String b2 = StringUtils.rightPad("", 72, '─'); final String nl = "\r\n"; StringBuilder msg = new StringBuilder(); msg.append("\r\n"); msg.append("Hi "); msg.append(nl); msg.append(b1); msg.append(nl); msg.append(" "); msg.append(com.gitblit.Constants.getGitBlitVersion()); msg.append(nl); msg.append(b1); msg.append(nl); msg.append(nl); msg.append(" Hi "); msg.append(user.getDisplayName()); msg.append(", you have successfully connected to Gitblit over SSH"); msg.append("\r\n"); msg.append("with client: "); msg.append(", you have successfully connected over SSH."); msg.append(nl); msg.append(nl); msg.append(" client: "); msg.append(session.getClientVersion()); msg.append("\r\n"); msg.append("\r\n"); msg.append(nl); msg.append(nl); msg.append("You may clone a repository with the following Git syntax:\r\n"); msg.append("\r\n"); msg.append(b2); msg.append(nl); msg.append(nl); msg.append(" You may clone a repository with the following Git syntax:"); msg.append(nl); msg.append(nl); msg.append(" git clone "); msg.append(formatUrl(user.username)); msg.append("\r\n"); msg.append("\r\n"); msg.append(formatUrl(hostname, port, user.username)); msg.append(nl); msg.append(nl); msg.append(b2); msg.append(nl); msg.append(nl); msg.append(" You may upload an SSH public key with the following syntax:"); msg.append(nl); msg.append(nl); msg.append(String.format(" cat ~/.ssh/id_rsa.pub | ssh -l %s -p %d %s gitblit keys add -", user.username, port, hostname)); msg.append(nl); msg.append(nl); msg.append(b2); msg.append(nl); msg.append(nl); // display the core commands SshCommandFactory cmdFactory = (SshCommandFactory) session.getFactoryManager().getCommandFactory(); DispatchCommand root = cmdFactory.createRootDispatcher(client, ""); String usage = root.usage().replace("\n", "\r\n"); String usage = root.usage().replace("\n", nl); msg.append(usage); return msg.toString(); } private String formatUrl(String username) { private String getHostname() { String host = null; String url = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443"); if (url != null) { @@ -154,15 +189,17 @@ if (StringUtils.isEmpty(host)) { host = SystemReader.getInstance().getHostname(); } return host; } int port = settings.getInteger(Keys.git.sshPort, 0); private String formatUrl(String hostname, int port, String username) { if (port == 22) { // standard port return MessageFormat.format("{0}@{1}/REPOSITORY.git", username, host); return MessageFormat.format("{0}@{1}/REPOSITORY.git", username, hostname); } else { // non-standard port return MessageFormat.format("ssh://{0}@{1}:{2,number,0}/REPOSITORY.git", username, host, port); username, hostname, port); } } } src/main/java/com/gitblit/transport/ssh/commands/BaseCommand.java
@@ -37,7 +37,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gitblit.Keys; import com.gitblit.utils.IdGenerator; import com.gitblit.utils.StringUtils; import com.gitblit.utils.WorkQueue; import com.gitblit.utils.WorkQueue.CancelableRunnable; import com.gitblit.utils.cli.CmdLineParser; @@ -200,9 +202,39 @@ } if (clp.wasHelpRequestedByOption()) { CommandMetaData meta = getClass().getAnnotation(CommandMetaData.class); String title = meta.name().toUpperCase() + ": " + meta.description(); String b = com.gitblit.utils.StringUtils.leftPad("", title.length() + 2, '═'); StringWriter msg = new StringWriter(); clp.printDetailedUsage(commandName, msg); msg.write(usage()); msg.write('\n'); msg.write(b); msg.write('\n'); msg.write(' '); msg.write(title); msg.write('\n'); msg.write(b); msg.write("\n\n"); msg.write("USAGE\n"); msg.write("─────\n"); msg.write(' '); msg.write(commandName); msg.write('\n'); msg.write(' '); clp.printSingleLineUsage(msg, null); msg.write("\n\n"); msg.write("ARGUMENTS & OPTIONS\n"); msg.write("───────────────────\n"); clp.printUsage(msg, null); msg.write('\n'); String examples = usage().trim(); if (!StringUtils.isEmpty(examples)) { msg.write('\n'); msg.write("EXAMPLES\n"); msg.write("────────\n"); msg.write(examples); msg.write('\n'); } throw new UnloggedFailure(1, msg.toString()); } } @@ -213,9 +245,33 @@ } public String usage() { Class<? extends BaseCommand> clazz = getClass(); if (clazz.isAnnotationPresent(UsageExamples.class)) { return examples(clazz.getAnnotation(UsageExamples.class).examples()); } else if (clazz.isAnnotationPresent(UsageExample.class)) { return examples(clazz.getAnnotation(UsageExample.class)); } return ""; } protected String examples(UsageExample... examples) { int sshPort = getContext().getGitblit().getSettings().getInteger(Keys.git.sshPort, 29418); String username = getContext().getClient().getUsername(); String hostname = "localhost"; String ssh = String.format("ssh -l %s -p %d %s", username, sshPort, hostname); StringBuilder sb = new StringBuilder(); for (UsageExample example : examples) { sb.append(example.description()).append("\n\n"); String syntax = example.syntax(); syntax = syntax.replace("${ssh}", ssh); syntax = syntax.replace("${username}", username); syntax = syntax.replace("${cmd}", commandName); sb.append(" ").append(syntax).append("\n\n"); } return sb.toString(); } protected void showHelp() throws UnloggedFailure { argv = new String [] { "--help" }; parseCommandLine(); src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
@@ -332,9 +332,9 @@ continue; } String displayName = name; String displayName = name + (meta.admin() ? "*" : ""); if (commandToAliases.containsKey(meta.name())) { displayName = name + " (" + Joiner.on(',').join(commandToAliases.get(meta.name())) + ")"; displayName = name + (meta.admin() ? "*" : "")+ " (" + Joiner.on(',').join(commandToAliases.get(meta.name())) + ")"; } displayNames.put(name, displayName); src/main/java/com/gitblit/transport/ssh/commands/SshCommand.java
@@ -18,8 +18,12 @@ import java.io.PrintWriter; import org.apache.sshd.server.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class SshCommand extends BaseCommand { protected Logger log = LoggerFactory.getLogger(getClass()); protected PrintWriter stdout; protected PrintWriter stderr; src/main/java/com/gitblit/transport/ssh/commands/UsageExample.java
New file @@ -0,0 +1,32 @@ /* * Copyright 2014 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.transport.ssh.commands; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Annotation tagged on a concrete Command to describe how to use it. */ @Target({ElementType.TYPE}) @Retention(RUNTIME) public @interface UsageExample { String syntax(); String description() default ""; } src/main/java/com/gitblit/transport/ssh/commands/UsageExamples.java
New file @@ -0,0 +1,31 @@ /* * Copyright 2014 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.transport.ssh.commands; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Annotation tagged on a concrete Command to describe how to use it. */ @Target({ElementType.TYPE}) @Retention(RUNTIME) public @interface UsageExamples { UsageExample [] examples() default {}; } src/main/java/com/gitblit/transport/ssh/git/GarbageCollectionCommand.java
@@ -25,8 +25,10 @@ import org.slf4j.LoggerFactory; import com.gitblit.transport.ssh.commands.CommandMetaData; import com.gitblit.transport.ssh.commands.UsageExample; @CommandMetaData(name = "gc", description = "Cleanup unnecessary files and optimize the local repository", admin = true) @UsageExample(syntax = "${cmd} test/myrepository.git", description = "Garbage collect \"test/myrepository.git\"") public class GarbageCollectionCommand extends BaseGitCommand { private static final Logger log = LoggerFactory.getLogger(GarbageCollectionCommand.class); src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java
@@ -36,7 +36,7 @@ protected List<String> readKeys(List<String> sshKeys) throws UnsupportedEncodingException, IOException { int idx = -1; if (sshKeys.isEmpty() || ((idx = sshKeys.indexOf("-")) >= 0)) { if ((idx = sshKeys.indexOf("-")) >= 0) { String sshKey = ""; BufferedReader br = new BufferedReader(new InputStreamReader( in, Charsets.UTF_8)); src/main/java/com/gitblit/transport/ssh/gitblit/ConfigCommand.java
@@ -14,9 +14,17 @@ import com.gitblit.models.SettingModel; import com.gitblit.transport.ssh.commands.CommandMetaData; import com.gitblit.transport.ssh.commands.SshCommand; import com.gitblit.transport.ssh.commands.UsageExample; import com.gitblit.transport.ssh.commands.UsageExamples; import com.google.common.collect.Maps; @CommandMetaData(name = "config", description = "Administer Gitblit settings", admin = true) @UsageExamples(examples = { @UsageExample(syntax = "${cmd} --list", description = "List all settings"), @UsageExample(syntax = "${cmd} git.sshPort", description = "Describe the git.sshPort setting"), @UsageExample(syntax = "${cmd} git.sshPort 29418", description = "Set git.sshPort to 29418"), @UsageExample(syntax = "${cmd} git.sshPort --reset", description = "Reset git.sshPort to it's default value"), }) public class ConfigCommand extends SshCommand { @Argument(index = 0, metaVar = "KEY", usage = "The setting to describe or update") src/main/java/com/gitblit/transport/ssh/gitblit/CreateRepository.java
File was deleted src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatcher.java
@@ -26,8 +26,6 @@ protected void setup(UserModel user) { // commands in this dispatcher register(user, VersionCommand.class); register(user, CreateRepository.class); register(user, SetAccountCommand.class); register(user, ConfigCommand.class); // nested dispatchers src/main/java/com/gitblit/transport/ssh/gitblit/KeysDispatcher.java
@@ -30,6 +30,7 @@ import com.gitblit.transport.ssh.commands.CommandMetaData; import com.gitblit.transport.ssh.commands.DispatchCommand; import com.gitblit.transport.ssh.commands.SshCommand; import com.gitblit.transport.ssh.commands.UsageExample; import com.gitblit.utils.FlipTable; import com.gitblit.utils.FlipTable.Borders; @@ -50,11 +51,12 @@ } @CommandMetaData(name = "add", description = "Add an SSH public key to your account") @UsageExample(syntax = "cat ~/.ssh/id_rsa.pub | ${ssh} ${cmd} -", description = "Upload your SSH public key and add it to your account") public static class AddKey extends BaseKeyCommand { protected final Logger log = LoggerFactory.getLogger(getClass()); @Argument(metaVar = "<stdin>|KEY", usage = "the key to add") @Argument(metaVar = "-|<KEY>", usage = "the key(s) to add", required = true) private List<String> addKeys = new ArrayList<String>(); @Override @@ -70,6 +72,7 @@ } @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove an SSH public key from your account") @UsageExample(syntax = "${cmd} 2", description = "Remove the SSH key identified as #2 in `keys list`") public static class RemoveKey extends BaseKeyCommand { protected final Logger log = LoggerFactory.getLogger(getClass()); @@ -131,7 +134,7 @@ } } @CommandMetaData(name = "list", aliases = { "ls" }, description = "List your registered public keys") @CommandMetaData(name = "list", aliases = { "ls" }, description = "List your registered SSH public keys") public static class ListKeys extends SshCommand { @Option(name = "-L", usage = "list complete public key parameters") src/main/java/com/gitblit/transport/ssh/gitblit/RepositoriesDispatcher.java
@@ -23,6 +23,7 @@ import com.gitblit.transport.ssh.commands.CommandMetaData; import com.gitblit.transport.ssh.commands.DispatchCommand; import com.gitblit.transport.ssh.commands.ListFilterCommand; import com.gitblit.transport.ssh.commands.UsageExample; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.FlipTable; import com.gitblit.utils.FlipTable.Borders; @@ -38,6 +39,7 @@ /* List repositories */ @CommandMetaData(name = "list", aliases = { "ls" }, description = "List repositories") @UsageExample(syntax = "${cmd} mirror/.* -v", description = "Verbose list of all repositories in the 'mirror' directory") public static class ListRepositories extends ListFilterCommand<RepositoryModel> { @Override @@ -72,7 +74,7 @@ String size = r.size; if (!r.hasCommits) { lm = ""; size = "(empty)"; size = FlipTable.EMPTY; } if (verbose) { String owners = ""; src/main/java/com/gitblit/transport/ssh/gitblit/SetAccountCommand.java
File was deleted src/main/java/com/gitblit/transport/ssh/gitblit/UsersDispatcher.java
@@ -15,75 +15,308 @@ */ package com.gitblit.transport.ssh.gitblit; import java.util.ArrayList; import java.util.List; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; import com.gitblit.Constants.AccessPermission; import com.gitblit.manager.IGitblit; import com.gitblit.models.RegistrantAccessPermission; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; import com.gitblit.transport.ssh.commands.CommandMetaData; import com.gitblit.transport.ssh.commands.DispatchCommand; import com.gitblit.transport.ssh.commands.ListFilterCommand; import com.gitblit.transport.ssh.commands.SshCommand; import com.gitblit.transport.ssh.commands.UsageExample; import com.gitblit.transport.ssh.commands.UsageExamples; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.FlipTable; import com.gitblit.utils.FlipTable.Borders; import com.gitblit.utils.StringUtils; import com.google.common.base.Joiner; @CommandMetaData(name = "users", description = "User management commands", admin = true) public class UsersDispatcher extends DispatchCommand { @Override protected void setup(UserModel user) { // primary user commands register(user, NewUser.class); register(user, RemoveUser.class); register(user, ShowUser.class); register(user, ListUsers.class); // user-specific commands register(user, SetName.class); register(user, Permissions.class); register(user, DisableUser.class); register(user, EnableUser.class); } @CommandMetaData(name = "show", description = "Show a user") public static class ShowUser extends SshCommand { public static abstract class UserCommand extends SshCommand { @Argument(index = 0, required = true, metaVar = "USERNAME", usage = "username") protected String username; protected UserModel getUser(boolean requireUser) throws UnloggedFailure { IGitblit gitblit = getContext().getGitblit(); UserModel user = gitblit.getUserModel(username); if (requireUser && user == null) { throw new UnloggedFailure(1, String.format("User %s does not exist!", username)); } return user; } } @CommandMetaData(name = "new", description = "Create a new user account") @UsageExample(syntax = "${cmd} john 12345 --email john@smith.com --canFork --canCreate") public static class NewUser extends UserCommand { @Argument(index = 1, required = true, metaVar = "PASSWORD", usage = "password") protected String password; @Option(name = "--email", metaVar = "ADDRESS", usage = "email address") protected String email; @Option(name = "--canAdmin", usage = "can administer the server") protected boolean canAdmin; @Option(name = "--canFork", usage = "can fork repositories") protected boolean canFork; @Option(name = "--canCreate", usage = "can create personal repositories") protected boolean canCreate; @Option(name = "--disabled", usage = "create a disabled user account") protected boolean disabled; @Override public void run() throws UnloggedFailure { if (getUser(false) != null) { throw new UnloggedFailure(1, String.format("User %s already exists!", username)); } UserModel user = new UserModel(username); user.password = password; if (email != null) { user.emailAddress = email; } user.canAdmin = canAdmin; user.canFork = canFork; user.canCreate = canCreate; user.disabled = disabled; IGitblit gitblit = getContext().getGitblit(); if (gitblit.updateUserModel(username, user)) { stdout.println(String.format("%s created.", username)); } else { throw new UnloggedFailure(1, String.format("Failed to create %s!", username)); } } } @CommandMetaData(name = "set-name", description = "Set the display name of an account") @UsageExample(syntax = "${cmd} john John Smith", description = "The display name to \"John Smith\" for john's account") public static class SetName extends UserCommand { @Argument(index = 1, multiValued = true, required = true, metaVar = "NAME", usage = "display name") protected List<String> displayName = new ArrayList<String>(); @Override public void run() throws UnloggedFailure { UserModel user = getUser(true); IGitblit gitblit = getContext().getGitblit(); user.displayName = Joiner.on(" ").join(displayName); if (gitblit.updateUserModel(username, user)) { stdout.println(String.format("Set the display name of %s to \"%s\".", username, user.displayName)); } else { throw new UnloggedFailure(1, String.format("Failed to set the display name of %s!", username)); } } } @CommandMetaData(name = "disable", description = "Prohibit an account from authenticating") @UsageExample(syntax = "${cmd} john", description = "Prevent John from authenticating") public static class DisableUser extends UserCommand { @Override public void run() throws UnloggedFailure { UserModel user = getUser(true); user.disabled = true; IGitblit gitblit = getContext().getGitblit(); if (gitblit.updateUserModel(username, user)) { stdout.println(String.format("%s is not allowed to authenticate.", username)); } else { throw new UnloggedFailure(1, String.format("Failed to disable %s!", username)); } } } @CommandMetaData(name = "enable", description = "Allow an account to authenticate") @UsageExample(syntax = "${cmd} john", description = "Allow John to authenticate") public static class EnableUser extends UserCommand { @Override public void run() throws UnloggedFailure { UserModel user = getUser(true); user.disabled = false; IGitblit gitblit = getContext().getGitblit(); if (gitblit.updateUserModel(username, user)) { stdout.println(String.format("%s may now authenticate.", username)); } else { throw new UnloggedFailure(1, String.format("Failed to enable %s!", username)); } } } @CommandMetaData(name = "permissions", aliases = { "perms" }, description = "Add or remove permissions from an account") @UsageExample(syntax = "${cmd} john RW:alpha/repo.git RWC:alpha/repo2.git", description = "Add or set permissions for John") public static class Permissions extends UserCommand { @Argument(index = 1, multiValued = true, metaVar = "[PERMISSION:]REPOSITORY", usage = "a repository expression") protected List<String> permissions; @Option(name = "--remove", aliases = { "-r" }, metaVar = "REPOSITORY|ALL", usage = "remove a repository permission") protected List<String> removals; @Override public void run() throws UnloggedFailure { IGitblit gitblit = getContext().getGitblit(); UserModel u = gitblit.getUserModel(username); if (u == null) { throw new UnloggedFailure(1, String.format("Unknown user \"%s\"", username)); UserModel user = getUser(true); boolean modified = false; if (!ArrayUtils.isEmpty(removals)) { if (removals.contains("ALL")) { user.permissions.clear(); } else { for (String repo : removals) { user.removeRepositoryPermission(repo); log.info(String.format("Removing permission for %s from %s", repo, username)); } } modified = true; } if (!ArrayUtils.isEmpty(permissions)) { for (String perm : permissions) { String repo = AccessPermission.repositoryFromRole(perm); if (StringUtils.findInvalidCharacter(repo) == null) { // explicit permision, confirm repository RepositoryModel r = gitblit.getRepositoryModel(repo); if (r == null) { throw new UnloggedFailure(1, String.format("Repository %s does not exist!", repo)); } } AccessPermission ap = AccessPermission.permissionFromRole(perm); user.setRepositoryPermission(repo, ap); log.info(String.format("Setting %s:%s for %s", ap.name(), repo, username)); } modified = true; } if (modified && gitblit.updateUserModel(username, user)) { // reload & display new permissions user = gitblit.getUserModel(username); } showPermissions(user); } protected void showPermissions(UserModel user) { List<RegistrantAccessPermission> perms = user.getRepositoryPermissions(); String[] pheaders = { "Repository", "Permission", "Type", "Source", "Mutable" }; Object [][] pdata = new Object[perms.size()][]; for (int i = 0; i < perms.size(); i++) { RegistrantAccessPermission ap = perms.get(i); pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType, ap.source, ap.mutable ? "Y":"" }; } stdout.println(FlipTable.of(pheaders, pdata, Borders.BODY_HCOLS)); } } @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove a user account") @UsageExample(syntax = "${cmd} john", description = "Delete john's account") public static class RemoveUser extends UserCommand { @Override public void run() throws UnloggedFailure { UserModel user = getUser(true); IGitblit gitblit = getContext().getGitblit(); if (gitblit.deleteUserModel(user)) { stdout.println(String.format("%s has been deleted.", username)); } else { throw new UnloggedFailure(1, String.format("Failed to delete %s!", username)); } } } @CommandMetaData(name = "show", description = "Show the details of an account") @UsageExample(syntax = "${cmd} john", description = "Display john's account") public static class ShowUser extends UserCommand { @Override public void run() throws UnloggedFailure { UserModel u = getUser(true); // fields String [] fheaders = new String [] { "Field", "Value" }; Object [][] fdata = new Object[5][]; fdata[0] = new Object [] { "Email", u.emailAddress }; fdata[1] = new Object [] { "Type", u.accountType }; fdata[2] = new Object [] { "Can Admin", u.canAdmin() ? "Y":"N" }; fdata[3] = new Object [] { "Can Fork", u.canFork() ? "Y":"N" }; fdata[4] = new Object [] { "Can Create", u.canCreate() ? "Y":"N" }; fdata[2] = new Object [] { "Can Admin", u.canAdmin() ? "Y":"" }; fdata[3] = new Object [] { "Can Fork", u.canFork() ? "Y":"" }; fdata[4] = new Object [] { "Can Create", u.canCreate() ? "Y":"" }; String fields = FlipTable.of(fheaders, fdata, Borders.COLS); // teams String [] theaders = new String [] { "Team", "Type" }; Object [][] tdata = new Object[u.teams.size()][]; int i = 0; for (TeamModel t : u.teams) { tdata[i] = new Object [] { t.name, t.accountType }; i++; String teams; if (u.teams.size() == 0) { teams = FlipTable.EMPTY; } else { String [] theaders = new String [] { "Team", "Type" }; Object [][] tdata = new Object[u.teams.size()][]; int i = 0; for (TeamModel t : u.teams) { tdata[i] = new Object [] { t.name, t.accountType }; i++; } teams = FlipTable.of(theaders, tdata, Borders.COLS); } String teams = FlipTable.of(theaders, tdata, Borders.COLS); // permissions List<RegistrantAccessPermission> perms = u.getRepositoryPermissions(); String[] pheaders = { "Repository", "Permission", "Type", "Source", "Mutable" }; Object [][] pdata = new Object[perms.size()][]; for (i = 0; i < perms.size(); i++) { RegistrantAccessPermission ap = perms.get(i); pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType, ap.source, ap.mutable ? "Y":"N" }; String permissions; if (perms.isEmpty()) { permissions = FlipTable.EMPTY; } else { String[] pheaders = { "Repository", "Permission", "Type", "Source", "Mutable" }; Object [][] pdata = new Object[perms.size()][]; for (int i = 0; i < perms.size(); i++) { RegistrantAccessPermission ap = perms.get(i); pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType, ap.source, ap.mutable ? "Y":"" }; } permissions = FlipTable.of(pheaders, pdata, Borders.COLS); } String permissions = FlipTable.of(pheaders, pdata, Borders.COLS); // assemble user table String [] headers = new String[] { u.getDisplayName() + (u.username.equals(u.getDisplayName()) ? "" : (" (" + u.username + ")")) }; String userTitle = u.getDisplayName() + (u.username.equals(u.getDisplayName()) ? "" : (" (" + u.username + ")")); if (u.disabled) { userTitle += " [DISABLED]"; } String [] headers = new String[] { userTitle }; String[][] data = new String[6][]; data[0] = new String [] { "FIELDS" }; data[1] = new String [] { fields }; @@ -95,7 +328,11 @@ } } @CommandMetaData(name = "list", aliases= { "ls" }, description = "List users") @CommandMetaData(name = "list", aliases= { "ls" }, description = "List accounts") @UsageExamples( examples = { @UsageExample(syntax = "${cmd}", description = "List accounts as a table"), @UsageExample(syntax = "${cmd} j.*", description = "List all accounts that start with 'j'"), }) public static class ListUsers extends ListFilterCommand<UserModel> { @Override @@ -125,10 +362,12 @@ for (int i = 0; i < list.size(); i++) { UserModel u = list.get(i); String name = u.disabled ? "-" : ((u.canAdmin() ? "*" : " ")) + u.username; String name = (u.disabled ? "-" : ((u.canAdmin() ? "*" : " "))) + u.username; if (verbose) { data[i] = new Object[] { name, u.displayName, u.accountType, u.emailAddress, u.canCreate() ? "Y":"", u.canFork() ? "Y" : ""}; u.emailAddress, (u.canAdmin() || u.canCreate()) ? "Y":"", (u.canAdmin() || u.canFork()) ? "Y" : ""}; } else { data[i] = new Object[] { name, u.displayName, u.accountType, u.emailAddress }; @@ -147,8 +386,8 @@ u.getDisplayName(), u.accountType, u.emailAddress == null ? "" : u.emailAddress, u.canCreate() ? "Y":"", u.canFork() ? "Y" : ""); (u.canAdmin() || u.canCreate()) ? "Y":"", (u.canAdmin() || u.canFork()) ? "Y" : ""); } } else { for (UserModel u : users) { src/main/java/com/gitblit/utils/FlipTable.java
@@ -36,7 +36,7 @@ * </pre> */ public final class FlipTable { private static final String EMPTY = "(empty)"; public static final String EMPTY = "(empty)"; public static enum Borders { FULL(15), BODY_HCOLS(13), HCOLS(12), BODY(9), HEADER(8), COLS(4); src/site/setup_transport_ssh.mkd
@@ -23,14 +23,14 @@ Then you can upload your *public* key right from the command-line. cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add cat c:\<userfolder>\.ssh\id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add - cat c:\<userfolder>\.ssh\id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add - **NOTE:** It is important to note that *ssh-keygen* generates a public/private keypair (e.g. id_rsa and id_rsa.pub). You want to upload the *public* key, which is denoted by the *.pub* file extension. Once you've done both of those steps you should be able to execute the following command without a password prompt. ssh -l <username> -p 29418 <hostname> gitblit version ssh -l <username> -p 29418 <hostname> ### Setting up an SSH alias @@ -40,7 +40,7 @@ You can define an alias for your server which will reduce your command syntax to something like this. ssh <alias> gitblit version ssh <alias> Create or modify your `~/.ssh/config` file and add a host entry. If you are on Windows, you'll want to create or modify `<userfolder>\.ssh\config`, where *userfolder* is dependent on your version of Windows. Most recently this is `c:\users\<userfolder>`. @@ -62,22 +62,21 @@ Add an SSH public key to your account. This command accepts a public key piped to stdin. cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add - ##### keys list Show the SSH public keys you have added to your account. ssh -l <username> -p 29418 <hostname> gitblit keys list ##### keys remove Remove an SSH public key from your account. This command accepts a public key piped to stdin. Remove an SSH public key from your account. This command accepts several input values, the most useful one is an index number which matches the index number displayed in the `list` command. cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys remove ssh -l <username> -p 29418 <hostname> gitblit keys remove 2 You can also remove all your public keys from your account. ssh -l <username> -p 29418 <hostname> gitblit keys remove ALL ##### keys list Show the SSH keys you have added to your account. ssh -l <username> -p 29418 <hostname> gitblit keys list