/*
* Copyright (c) 2013 Hudson.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Hudson - initial API and implementation and/or initial documentation
*/
package hudson.cli;
import hudson.Extension;
import hudson.model.Hudson;
import hudson.util.QuotedStringTokenizer;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.hudson.security.HudsonSecurityManager;
import org.eclipse.hudson.security.team.TeamManager;
import org.kohsuke.args4j.Option;
import org.springframework.security.core.Authentication;
/**
* Lists the teams and READ or CREATE job permissions of the current user.
* @author Bob Foster
* @since 3.1.0
*/
@Extension
public class ListTeamsCommand extends CLICommand {
@Override
public String getShortDescription() {
return "Lists the teams and READ or CREATE job permissions of the current user";
}
private String getCurrentUser() {
Authentication authentication = HudsonSecurityManager.getAuthentication();
return authentication.getName();
}
enum Format {
XML, CSV, PLAIN
}
@Option(name = "-format", usage = "Controls how the output from this command is printed.")
public Format format = Format.PLAIN;
@Option(name = "-u", aliases = {"--users"}, usage = "Users to report. \"a,b\" for users a and b. \"*\" for all. Available only to admins.")
public String users = null;
TeamManager teamManager;
@Override
protected int run() throws TeamManager.TeamNotFoundException {
teamManager = Hudson.getInstance().getTeamManager();
String[] teams = new String[0];
String[] userArray = null;
String[] adminTeams = null;
if (teamManager.isTeamManagementEnabled()) {
Collection<String> currentUserTeams = teamManager.getCurrentUserVisibleTeams();
Arrays.sort(teams = currentUserTeams.toArray(new String[currentUserTeams.size()]));
if (users != null) {
userArray = QuotedStringTokenizer.tokenize(users, ",");
for (String user : userArray) {
if ("*".equals(user)) {
userArray = new String[] {"*"};
break;
}
}
// NB: Users administered by current user must be in teams visible to current user
// but not necessarily all those teams are administered by the current user.
Collection<String> usersAdministered = teamManager.getCurrentUserAdminUsers();
if (userArray.length == 1 && "*".equals(userArray[0])) {
// all users administered by current user
userArray = usersAdministered.toArray(new String[usersAdministered.size()]);
} else {
for (String user : userArray) {
if (!usersAdministered.contains(user)) {
throw new IllegalArgumentException("User "+user+" is not in a team administered by current user");
}
}
}
Arrays.sort(userArray);
Collection<String> cuAdminTeams = teamManager.getCurrentUserAdminTeams();
adminTeams = cuAdminTeams.toArray(new String[cuAdminTeams.size()]);
Arrays.sort(adminTeams);
}
}
switch (format) {
case XML:
PrintWriter w = new PrintWriter(stdout);
if (userArray != null) {
w.println("<users>");
for (String user : userArray) {
w.println(" <user>");
w.print(" <name>");
w.print(user);
w.println("</name>");
w.println(" <teams>");
for (String team : adminTeams) {
if (teamManager.isUserHasAccessToTeam(user, team)) {
printTeamXml(w, user, team, " ");
}
}
w.println(" </teams>");
w.println(" </user>");
}
w.println("</users>");
} else {
Authentication authentication = HudsonSecurityManager.getAuthentication();
w.println("<teams>");
for (String team : teams) {
printTeamXml(w, authentication.getName(), team, " ");
}
w.println("</teams>");
}
w.flush();
break;
case CSV:
if (userArray != null) {
stdout.printf("User,Team,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", TeamManager.ALL_TEAM_PERMISSIONS);
for (String user : userArray) {
for (String team : adminTeams) {
if (teamManager.isUserHasAccessToTeam(user, team)) {
stdout.printf(user+","+team+",%s,%s,%s,%s,%s,%s,%s,%s\n",
convertToXArray(teamManager.getUserTeamPermissions(user, team)));
}
}
}
} else {
stdout.printf("Team,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", TeamManager.ALL_TEAM_PERMISSIONS);
for (String team : teams) {
stdout.printf(team+",%s,%s,%s,%s,%s,%s,%s,%s\n",
convertToXArray(teamManager.getCurrentUserTeamPermissions(team)));
}
}
stdout.flush();
break;
case PLAIN:
if (userArray != null) {
int bigTeam = findBig(adminTeams);
int bigUser = findBig(userArray);
for (String user : userArray) {
for (String team : adminTeams) {
if (teamManager.isUserHasAccessToTeam(user, team)) {
printPlain(user, team, bigUser, bigTeam);
}
}
}
} else {
int bigTeam = findBig(teams);
for (String team : teams) {
printPlain(getCurrentUser(), team, 0, bigTeam);
}
}
stdout.flush();
break;
}
return 0;
}
private int findBig(String[] sa) {
int big = 0;
for (String s : sa) {
if (big < s.length()) {
big = s.length();
}
}
return big;
}
private void printPlain(String user, String team, int bigUser, int bigTeam) throws TeamManager.TeamNotFoundException {
if (bigUser > 0) {
stdout.print(user);
pad(stdout, bigUser-user.length()+1);
}
stdout.print(team);
pad(stdout, bigTeam-team.length()+2);
String[] permissions = teamManager.getUserTeamPermissions(user, team);
for (int i = 0; i < permissions.length; i++) {
if (i == permissions.length - 1) {
stdout.println(permissions[i]);
} else {
stdout.print(permissions[i]);
stdout.print(" ");
}
}
}
private void printTeamXml(PrintWriter w, String user, String team, String indent) throws TeamManager.TeamNotFoundException {
w.print(indent);
w.println("<team>");
w.print(indent);
w.print(" <name>");
w.print(team);
w.println("</name>");
String[] permissions = teamManager.getUserTeamPermissions(user, team);
if (permissions.length > 0) {
w.print(indent);
w.println(" <permissions>");
for (String permission : permissions) {
w.print(indent);
w.print(" <permission>");
w.print(permission);
w.println("</permission>");
}
w.print(indent);
w.println(" </permissions>");
}
w.print(indent);
w.println("</team>");
}
private String[] convertToXArray(String[] currentUserTeamPermissions) {
String[] allPermissions = TeamManager.ALL_TEAM_PERMISSIONS;
// Both arrays are sorted, so it's just a merge
String[] xarray = new String[allPermissions.length];
int currentIndex = 0;
for (int i = 0; i < allPermissions.length; i++) {
if (currentIndex < currentUserTeamPermissions.length
&& allPermissions[i].equals(currentUserTeamPermissions[currentIndex])) {
xarray[i] = "X";
currentIndex++;
} else {
xarray[i] = "-";
}
}
return xarray;
}
private void pad(PrintStream out, int n) {
while (n-- > 0) {
out.print(" ");
}
}
}