@@ -194,7 +194,7 @@ public class LuceneService implements Runnable { | |||
* Synchronously indexes a repository. This may build a complete index of a | |||
* repository or it may update an existing index. | |||
* | |||
* @param name | |||
* @param displayName | |||
* the name of the repository | |||
* @param repository | |||
* the repository object |
@@ -222,6 +222,11 @@ public abstract class BaseCommand implements Command, SessionAware { | |||
msg.write(" "); | |||
clp.printSingleLineUsage(msg, null); | |||
msg.write("\n\n"); | |||
String txt = getUsageText(); | |||
if (!StringUtils.isEmpty(txt)) { | |||
msg.write(txt); | |||
msg.write("\n\n"); | |||
} | |||
msg.write("ARGUMENTS & OPTIONS\n"); | |||
msg.write("───────────────────\n"); | |||
clp.printUsage(msg, null); | |||
@@ -254,6 +259,10 @@ public abstract class BaseCommand implements Command, SessionAware { | |||
return ""; | |||
} | |||
protected String getUsageText() { | |||
return ""; | |||
} | |||
protected String examples(UsageExample... examples) { | |||
int sshPort = getContext().getGitblit().getSettings().getInteger(Keys.git.sshPort, 29418); | |||
String username = getContext().getClient().getUsername(); |
@@ -15,12 +15,14 @@ | |||
*/ | |||
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.GitBlitException; | |||
import com.gitblit.manager.IGitblit; | |||
import com.gitblit.models.RegistrantAccessPermission; | |||
import com.gitblit.models.RepositoryModel; | |||
@@ -45,11 +47,13 @@ public class TeamsDispatcher extends DispatchCommand { | |||
protected void setup(UserModel user) { | |||
// primary team commands | |||
register(user, NewTeam.class); | |||
register(user, RenameTeam.class); | |||
register(user, RemoveTeam.class); | |||
register(user, ShowTeam.class); | |||
register(user, ListTeams.class); | |||
// team-specific commands | |||
register(user, SetField.class); | |||
register(user, Permissions.class); | |||
register(user, Members.class); | |||
} | |||
@@ -94,12 +98,135 @@ public class TeamsDispatcher extends DispatchCommand { | |||
team.canCreate = canCreate; | |||
IGitblit gitblit = getContext().getGitblit(); | |||
if (gitblit.updateTeamModel(teamname, team)) { | |||
try { | |||
gitblit.addTeam(team); | |||
stdout.println(String.format("%s created.", teamname)); | |||
} else { | |||
throw new UnloggedFailure(1, String.format("Failed to create %s!", teamname)); | |||
} catch (GitBlitException e) { | |||
String msg = String.format("Failed to create %s!", teamname); | |||
log.error(msg, e); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
} | |||
} | |||
@CommandMetaData(name = "rename", aliases = { "mv" }, description = "Rename a team") | |||
@UsageExample(syntax = "${cmd} contributors friends", description = "Rename the contributors team to the friends team") | |||
public static class RenameTeam extends TeamCommand { | |||
@Argument(index = 1, required = true, metaVar = "NEWNAME", usage = "the new team name") | |||
protected String newTeamName; | |||
@Override | |||
public void run() throws UnloggedFailure { | |||
TeamModel team = getTeam(true); | |||
IGitblit gitblit = getContext().getGitblit(); | |||
if (null != gitblit.getTeamModel(newTeamName)) { | |||
throw new UnloggedFailure(1, String.format("Team %s already exists!", newTeamName)); | |||
} | |||
// set the new team name | |||
team.name = newTeamName; | |||
try { | |||
gitblit.reviseTeam(teamname, team); | |||
stdout.println(String.format("Renamed team %s to %s.", teamname, newTeamName)); | |||
} catch (GitBlitException e) { | |||
String msg = String.format("Failed to rename team from %s to %s", teamname, newTeamName); | |||
log.error(msg, e); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
} | |||
} | |||
@CommandMetaData(name = "set", description = "Set the specified field of a team") | |||
@UsageExample(syntax = "${cmd} contributors canFork true", description = "Allow the contributors team to fork repositories") | |||
public static class SetField extends TeamCommand { | |||
@Argument(index = 1, required = true, metaVar = "FIELD", usage = "the field to update") | |||
protected String fieldName; | |||
@Argument(index = 2, required = true, metaVar = "VALUE", usage = "the new value") | |||
protected List<String> fieldValues = new ArrayList<String>(); | |||
protected enum Field { | |||
mailingList, canAdmin, canFork, canCreate; | |||
static Field fromString(String name) { | |||
for (Field field : values()) { | |||
if (field.name().equalsIgnoreCase(name)) { | |||
return field; | |||
} | |||
} | |||
return null; | |||
} | |||
} | |||
@Override | |||
protected String getUsageText() { | |||
String fields = Joiner.on(", ").join(Field.values()); | |||
StringBuilder sb = new StringBuilder(); | |||
sb.append("Valid fields are:\n ").append(fields); | |||
return sb.toString(); | |||
} | |||
@Override | |||
public void run() throws UnloggedFailure { | |||
TeamModel team = getTeam(true); | |||
Field field = Field.fromString(fieldName); | |||
if (field == null) { | |||
throw new UnloggedFailure(1, String.format("Unknown field %s", fieldName)); | |||
} | |||
String value = Joiner.on(" ").join(fieldValues); | |||
IGitblit gitblit = getContext().getGitblit(); | |||
switch(field) { | |||
case mailingList: | |||
team.mailingLists.clear(); | |||
team.mailingLists.addAll(fieldValues); | |||
break; | |||
case canAdmin: | |||
team.canAdmin = toBool(value); | |||
break; | |||
case canFork: | |||
team.canFork = toBool(value); | |||
break; | |||
case canCreate: | |||
team.canCreate = toBool(value); | |||
break; | |||
default: | |||
throw new UnloggedFailure(1, String.format("Field %s was not properly handled by the set command.", fieldName)); | |||
} | |||
try { | |||
gitblit.reviseTeam(teamname, team); | |||
stdout.println(String.format("Set %s.%s = %s", teamname, fieldName, value)); | |||
} catch (GitBlitException e) { | |||
String msg = String.format("Failed to set %s.%s = %s", teamname, fieldName, value); | |||
log.error(msg, e); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
} | |||
protected boolean toBool(String value) throws UnloggedFailure { | |||
String v = value.toLowerCase(); | |||
if (v.equals("t") | |||
|| v.equals("true") | |||
|| v.equals("yes") | |||
|| v.equals("on") | |||
|| v.equals("y") | |||
|| v.equals("1")) { | |||
return true; | |||
} else if (v.equals("f") | |||
|| v.equals("false") | |||
|| v.equals("no") | |||
|| v.equals("off") | |||
|| v.equals("n") | |||
|| v.equals("0")) { | |||
return false; | |||
} | |||
throw new UnloggedFailure(1, String.format("Invalid boolean value %s", value)); | |||
} | |||
} | |||
@CommandMetaData(name = "permissions", aliases = { "perms" }, description = "Add or remove permissions from a team") | |||
@@ -182,6 +309,12 @@ public class TeamsDispatcher extends DispatchCommand { | |||
IGitblit gitblit = getContext().getGitblit(); | |||
TeamModel team = getTeam(true); | |||
boolean canEditMemberships = gitblit.supportsTeamMembershipChanges(team); | |||
if (!canEditMemberships) { | |||
String msg = String.format("Team %s (%s) does not permit membership changes!", team.name, team.accountType); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
boolean modified = false; | |||
if (!ArrayUtils.isEmpty(removals)) { | |||
if (removals.contains("ALL")) { | |||
@@ -201,6 +334,11 @@ public class TeamsDispatcher extends DispatchCommand { | |||
if (u == null) { | |||
throw new UnloggedFailure(1, String.format("Unknown user %s", username)); | |||
} | |||
boolean canEditTeams = gitblit.supportsTeamMembershipChanges(u); | |||
if (!canEditTeams) { | |||
String msg = String.format("User %s (%s) does not allow team membership changes ", u.username, u.accountType); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
team.addUser(username); | |||
} | |||
modified = true; |
@@ -22,6 +22,8 @@ import org.kohsuke.args4j.Argument; | |||
import org.kohsuke.args4j.Option; | |||
import com.gitblit.Constants.AccessPermission; | |||
import com.gitblit.GitBlitException; | |||
import com.gitblit.Keys; | |||
import com.gitblit.manager.IGitblit; | |||
import com.gitblit.models.RegistrantAccessPermission; | |||
import com.gitblit.models.RepositoryModel; | |||
@@ -46,12 +48,13 @@ public class UsersDispatcher extends DispatchCommand { | |||
protected void setup(UserModel user) { | |||
// primary user commands | |||
register(user, NewUser.class); | |||
register(user, RenameUser.class); | |||
register(user, RemoveUser.class); | |||
register(user, ShowUser.class); | |||
register(user, ListUsers.class); | |||
// user-specific commands | |||
register(user, SetName.class); | |||
register(user, SetField.class); | |||
register(user, Permissions.class); | |||
register(user, DisableUser.class); | |||
register(user, EnableUser.class); | |||
@@ -113,32 +116,175 @@ public class UsersDispatcher extends DispatchCommand { | |||
user.disabled = disabled; | |||
IGitblit gitblit = getContext().getGitblit(); | |||
if (gitblit.updateUserModel(username, user)) { | |||
try { | |||
gitblit.addUser(user); | |||
stdout.println(String.format("%s created.", username)); | |||
} else { | |||
throw new UnloggedFailure(1, String.format("Failed to create %s!", username)); | |||
} catch (GitBlitException e) { | |||
log.error("Failed to add " + username, e); | |||
throw new UnloggedFailure(1, e.getMessage()); | |||
} | |||
} | |||
} | |||
@CommandMetaData(name = "rename", aliases = { "mv" }, description = "Rename an account") | |||
@UsageExample(syntax = "${cmd} john frank", description = "Rename the account from john to frank") | |||
public static class RenameUser extends UserCommand { | |||
@Argument(index = 1, required = true, metaVar = "NEWNAME", usage = "the new account name") | |||
protected String newUserName; | |||
@Override | |||
public void run() throws UnloggedFailure { | |||
UserModel user = getUser(true); | |||
IGitblit gitblit = getContext().getGitblit(); | |||
if (null != gitblit.getTeamModel(newUserName)) { | |||
throw new UnloggedFailure(1, String.format("Team %s already exists!", newUserName)); | |||
} | |||
// set the new name | |||
user.username = newUserName; | |||
try { | |||
gitblit.reviseUser(username, user); | |||
stdout.println(String.format("Renamed user %s to %s.", username, newUserName)); | |||
} catch (GitBlitException e) { | |||
String msg = String.format("Failed to rename user from %s to %s", username, newUserName); | |||
log.error(msg, e); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
} | |||
} | |||
@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 { | |||
@CommandMetaData(name = "set", description = "Set the specified field of an account") | |||
@UsageExample(syntax = "${cmd} john name John Smith", description = "Set the display name to \"John Smith\" for john's account") | |||
public static class SetField extends UserCommand { | |||
@Argument(index = 1, required = true, metaVar = "FIELD", usage = "the field to update") | |||
protected String fieldName; | |||
@Argument(index = 1, multiValued = true, required = true, metaVar = "NAME", usage = "display name") | |||
protected List<String> displayName = new ArrayList<String>(); | |||
@Argument(index = 2, required = true, metaVar = "VALUE", usage = "the new value") | |||
protected List<String> fieldValues = new ArrayList<String>(); | |||
protected enum Field { | |||
name, displayName, email, password, canAdmin, canFork, canCreate; | |||
static Field fromString(String name) { | |||
for (Field field : values()) { | |||
if (field.name().equalsIgnoreCase(name)) { | |||
return field; | |||
} | |||
} | |||
return null; | |||
} | |||
} | |||
@Override | |||
protected String getUsageText() { | |||
String fields = Joiner.on(", ").join(Field.values()); | |||
StringBuilder sb = new StringBuilder(); | |||
sb.append("Valid fields are:\n ").append(fields); | |||
return sb.toString(); | |||
} | |||
@Override | |||
public void run() throws UnloggedFailure { | |||
UserModel user = getUser(true); | |||
Field field = Field.fromString(fieldName); | |||
if (field == null) { | |||
throw new UnloggedFailure(1, String.format("Unknown field %s", fieldName)); | |||
} | |||
String value = Joiner.on(" ").join(fieldValues).trim(); | |||
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)); | |||
boolean editCredentials = gitblit.supportsCredentialChanges(user); | |||
boolean editDisplayName = gitblit.supportsDisplayNameChanges(user); | |||
boolean editEmailAddress = gitblit.supportsEmailAddressChanges(user); | |||
String m = String.format("Can not edit %s for %s (%s)", field, user.username, user.accountType); | |||
switch(field) { | |||
case name: | |||
case displayName: | |||
if (!editDisplayName) { | |||
throw new UnloggedFailure(1, m); | |||
} | |||
user.displayName = value; | |||
break; | |||
case email: | |||
if (!editEmailAddress) { | |||
throw new UnloggedFailure(1, m); | |||
} | |||
user.emailAddress = value; | |||
break; | |||
case password: | |||
if (!editCredentials) { | |||
throw new UnloggedFailure(1, m); | |||
} | |||
int minLength = gitblit.getSettings().getInteger(Keys.realm.minPasswordLength, 5); | |||
if (minLength < 4) { | |||
minLength = 4; | |||
} | |||
if (value.trim().length() < minLength) { | |||
throw new UnloggedFailure(1, "Password is too short."); | |||
} | |||
// Optionally store the password MD5 digest. | |||
String type = gitblit.getSettings().getString(Keys.realm.passwordStorage, "md5"); | |||
if (type.equalsIgnoreCase("md5")) { | |||
// store MD5 digest of password | |||
user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(value); | |||
} else if (type.equalsIgnoreCase("combined-md5")) { | |||
// store MD5 digest of username+password | |||
user.password = StringUtils.COMBINED_MD5_TYPE + StringUtils.getMD5(username + value); | |||
} else { | |||
user.password = value; | |||
} | |||
// reset the cookie | |||
user.cookie = StringUtils.getSHA1(user.username + value); | |||
break; | |||
case canAdmin: | |||
user.canAdmin = toBool(value); | |||
break; | |||
case canFork: | |||
user.canFork = toBool(value); | |||
break; | |||
case canCreate: | |||
user.canCreate = toBool(value); | |||
break; | |||
default: | |||
throw new UnloggedFailure(1, String.format("Field %s was not properly handled by the set command.", fieldName)); | |||
} | |||
try { | |||
gitblit.reviseUser(username, user); | |||
stdout.println(String.format("Set %s.%s = %s", username, fieldName, value)); | |||
} catch (GitBlitException e) { | |||
String msg = String.format("Failed to set %s.%s = %s", username, fieldName, value); | |||
log.error(msg, e); | |||
throw new UnloggedFailure(1, msg); | |||
} | |||
} | |||
protected boolean toBool(String value) throws UnloggedFailure { | |||
String v = value.toLowerCase(); | |||
if (v.equals("t") | |||
|| v.equals("true") | |||
|| v.equals("yes") | |||
|| v.equals("on") | |||
|| v.equals("y") | |||
|| v.equals("1")) { | |||
return true; | |||
} else if (v.equals("f") | |||
|| v.equals("false") | |||
|| v.equals("no") | |||
|| v.equals("off") | |||
|| v.equals("n") | |||
|| v.equals("0")) { | |||
return false; | |||
} | |||
throw new UnloggedFailure(1, String.format("Invalid boolean value %s", value)); | |||
} | |||
} | |||