Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWinston Prakash2013-05-28 21:39:03 -0400
committerWinston Prakash2013-05-28 21:39:03 -0400
commit60c7b097492a5048ded6ff09f6cfcf3f3785cc61 (patch)
tree8196e7c47390939afaa882c99244d6726a3237ee
parent66a9e3af5c78a0d05060e7961a475c4e8619cc27 (diff)
downloadorg.eclipse.hudson.core-team-impl.tar.gz
org.eclipse.hudson.core-team-impl.tar.xz
org.eclipse.hudson.core-team-impl.zip
Implement the feature that helps to move jobs between teams by the Sys Adminteam-impl
-rw-r--r--hudson-core/src/main/java/hudson/Functions.java35
-rw-r--r--hudson-core/src/main/java/hudson/model/AbstractItem.java6
-rw-r--r--hudson-core/src/main/java/hudson/model/Hudson.java46
-rw-r--r--hudson-core/src/main/java/org/eclipse/hudson/security/team/PublicTeam.java (renamed from hudson-core/src/main/java/org/eclipse/hudson/security/team/DefaultTeam.java)10
-rw-r--r--hudson-core/src/main/java/org/eclipse/hudson/security/team/Team.java14
-rw-r--r--hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamBasedACL.java8
-rw-r--r--hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamManager.java262
-rw-r--r--hudson-core/src/main/resources/hudson/model/View/newJob.jelly2
-rw-r--r--hudson-core/src/main/resources/hudson/model/View/sidepanel.jelly2
-rw-r--r--hudson-core/src/main/resources/hudson/security/SecurityRealm/loginLink.jelly6
-rw-r--r--hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/index.jelly2
-rw-r--r--hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/sidepanel.jelly58
-rw-r--r--hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/teamManager.jelly222
-rw-r--r--hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamAwareSecurityRealmTest.java4
-rw-r--r--hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamJobACLTest.java32
-rw-r--r--hudson-war/src/main/webapp/css/team-manager.css26
-rw-r--r--hudson-war/src/main/webapp/scripts/team-manager.js104
17 files changed, 608 insertions, 231 deletions
diff --git a/hudson-core/src/main/java/hudson/Functions.java b/hudson-core/src/main/java/hudson/Functions.java
index 06263a7f..daa2c7b5 100644
--- a/hudson-core/src/main/java/hudson/Functions.java
+++ b/hudson-core/src/main/java/hudson/Functions.java
@@ -1,19 +1,21 @@
-/*******************************************************************************
+/**
+ * *****************************************************************************
*
* Copyright (c) 2004-2012 Oracle Corporation.
*
- * 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
+ * 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:
*
- * Kohsuke Kawaguchi, Winston Prakash, Stephen Connolly, Tom Huybrechts, Alan Harder, Romain Seguy
+ * Kohsuke Kawaguchi, Winston Prakash, Stephen Connolly, Tom Huybrechts, Alan
+ * Harder, Romain Seguy
*
*
- *******************************************************************************/
-
+ ******************************************************************************
+ */
package hudson;
import com.google.common.base.Predicate;
@@ -508,7 +510,7 @@ public class Functions {
}
return null;
}
-
+
public static String getAncestorUrl(StaplerRequest req, Ancestor anc) {
if (anc != null) {
String ancUrl = anc.getUrl();
@@ -785,7 +787,7 @@ public class Functions {
}
return buf.append(c.getName());
}
-
+
public static String getRequestRootPath() {
return getRequestRootPath(null);
}
@@ -796,15 +798,14 @@ public class Functions {
}
return getHttpRequestRootPath(req);
}
-
private static RequestRootPathProvider requestRootPathProvider = new DefaultRequestRootPathProvider();
-
+
public static void setRequestRootPathProvider(RequestRootPathProvider requestRootPathProvider) {
- Functions.requestRootPathProvider = requestRootPathProvider;
+ Functions.requestRootPathProvider = requestRootPathProvider;
}
public static String getHttpRequestRootPath(HttpServletRequest req) {
- return requestRootPathProvider.getRootPath(req);
+ return requestRootPathProvider.getRootPath(req);
}
/**
@@ -1521,14 +1522,14 @@ public class Functions {
public static Object rawHtml(Object o) {
return InternationalizedStringExpression.rawHtml(o);
}
-
+
public static String getJobsFolderName(String jobId) {
String jobsFolderName = "jobs";
if (jobId != null) {
- TeamManager teamManager = Hudson.getInstance().getTeamManager();
- if (teamManager != null) {
+ TeamManager teamManager = Hudson.getInstance().getTeamManager();
+ if (teamManager != null) {
jobsFolderName = teamManager.getJobsFolderName(jobId);
- }
+ }
}
return jobsFolderName;
}
diff --git a/hudson-core/src/main/java/hudson/model/AbstractItem.java b/hudson-core/src/main/java/hudson/model/AbstractItem.java
index 447c920e..db16c1b9 100644
--- a/hudson-core/src/main/java/hudson/model/AbstractItem.java
+++ b/hudson-core/src/main/java/hudson/model/AbstractItem.java
@@ -342,7 +342,11 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
}
public String getShortUrl() {
- return getParent().getUrlChildPrefix() + '/' + Util.rawEncode(getName()) + '/';
+ if (Hudson.getInstance().getTeamManager() != null) {
+ return getParent().getUrlChildPrefix() + '/' + Util.rawEncode(getId()) + '/';
+ } else {
+ return getParent().getUrlChildPrefix() + '/' + Util.rawEncode(getName()) + '/';
+ }
}
public String getSearchUrl() {
diff --git a/hudson-core/src/main/java/hudson/model/Hudson.java b/hudson-core/src/main/java/hudson/model/Hudson.java
index 5238a679..8df84c6b 100644
--- a/hudson-core/src/main/java/hudson/model/Hudson.java
+++ b/hudson-core/src/main/java/hudson/model/Hudson.java
@@ -816,6 +816,18 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
public TeamManager getTeamManager(TeamBasedAuthorizationStrategyDescriptor authorizationStrategy) {
return teamManager;
}
+
+ /**
+ * Do not use this API, for internal purpose only
+ * @since 3.1.0
+ */
+ public void replaceItemId(String oldTemId, String newItemId){
+ if (items.containsKey(oldTemId)){
+ TopLevelItem item = items.get(oldTemId);
+ items.remove(oldTemId);
+ items.put(newItemId, item);
+ }
+ }
public HudsonSecurityManager getSecurityManager() {
return HudsonSecurityEntitiesHolder.getHudsonSecurityManager();
@@ -1854,7 +1866,11 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
}
public String getUrlChildPrefix() {
- return "job";
+ if (getTeamManager() == null) {
+ return "job";
+ } else {
+ return "jobById";
+ }
}
/**
@@ -2110,6 +2126,10 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
public TopLevelItem getJob(String name) {
return getItem(name);
}
+
+ public TopLevelItem getJobById(String id) {
+ return getItemById(id);
+ }
/**
* @deprecated Used only for mapping jobs to URL in a case-insensitive
@@ -2142,6 +2162,21 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
}
return item;
}
+
+ /**
+ * Get the item based on id
+ * @param item id
+ * @return item, null if does not exist or no read permission
+ * @since 3.1.0
+ */
+ public TopLevelItem getItemById(String id) {
+ for (TopLevelItem item: getItems()){
+ if (item.getId().equals(id)){
+ return item;
+ }
+ }
+ return null;
+ }
@Override
public File getRootDirFor(TopLevelItem child) {
@@ -2766,14 +2801,11 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*/
public TopLevelItem reloadProjectFromDisk(File jobDir) throws IOException {
TopLevelItem item = (TopLevelItem) Items.load(this, jobDir);
- String itemName = item.getName();
if (getTeamManager() != null){
- Team team = getTeamManager().findJobOwnerTeam(item.getName());
- if ((team != null) && team.getName().equals(Team.DEFAULT_TEAM_NAME)){
- itemName = getTeamManager().getTeamQualifiedJobId(itemName);
- }
+ items.put(item.getId(), item);
+ }else{
+ items.put(item.getName(), item);
}
- items.put(itemName, item);
rebuildDependencyGraph();
return item;
}
diff --git a/hudson-core/src/main/java/org/eclipse/hudson/security/team/DefaultTeam.java b/hudson-core/src/main/java/org/eclipse/hudson/security/team/PublicTeam.java
index cc4865bc..06119693 100644
--- a/hudson-core/src/main/java/org/eclipse/hudson/security/team/DefaultTeam.java
+++ b/hudson-core/src/main/java/org/eclipse/hudson/security/team/PublicTeam.java
@@ -15,20 +15,20 @@ import java.io.IOException;
import java.util.List;
/**
- * The default team contains the jobs not specific to any team.
+ * The public team contains the jobs not specific to any team.
* Every one has read access to these jobs except sysadmin
* @since 3.1.0
* @author Winston Prakash
*/
-public final class DefaultTeam extends Team{
+public final class PublicTeam extends Team{
- DefaultTeam(TeamManager teamManager) {
- super(DEFAULT_TEAM_NAME, teamManager);
+ PublicTeam(TeamManager teamManager) {
+ super(PUBLIC_TEAM_NAME, teamManager);
}
/**
* Scan and find the jobs in the existing Hudson home and add them to the
- * default team.
+ * public team.
* @param hudsonHome
*/
void loadExistingJobs(File rootFolder) throws IOException{
diff --git a/hudson-core/src/main/java/org/eclipse/hudson/security/team/Team.java b/hudson-core/src/main/java/org/eclipse/hudson/security/team/Team.java
index 62e15035..7de709d6 100644
--- a/hudson-core/src/main/java/org/eclipse/hudson/security/team/Team.java
+++ b/hudson-core/src/main/java/org/eclipse/hudson/security/team/Team.java
@@ -37,7 +37,7 @@ import org.springframework.security.Authentication;
*/
public class Team implements AccessControlled {
- public static final String DEFAULT_TEAM_NAME = "default";
+ public static final String PUBLIC_TEAM_NAME = "public";
private List<String> admins = new CopyOnWriteArrayList<String>();
private List<String> members = new CopyOnWriteArrayList<String>();
private List<String> jobs = new CopyOnWriteArrayList<String>();
@@ -144,16 +144,16 @@ public class Team implements AccessControlled {
}
}
- public void addJob(String jobname) throws IOException {
- if (!jobs.contains(jobname)) {
- jobs.add(jobname);
+ public void addJob(String jobId) throws IOException {
+ if (!jobs.contains(jobId)) {
+ jobs.add(jobId);
getTeamManager().save();
}
}
- public void removeJob(String jobname) throws IOException {
- if (jobs.contains(jobname)) {
- jobs.remove(jobname);
+ public void removeJob(String jobId) throws IOException {
+ if (jobs.contains(jobId)) {
+ jobs.remove(jobId);
getTeamManager().save();
}
}
diff --git a/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamBasedACL.java b/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamBasedACL.java
index f180470c..b6d2ed70 100644
--- a/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamBasedACL.java
+++ b/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamBasedACL.java
@@ -110,17 +110,17 @@ public class TeamBasedACL extends SidACL {
}
}
// Grant Read permission to
- Team defaultTeam;
+ Team publicTeam;
try {
- defaultTeam = teamManager.findTeam("default");
+ publicTeam = teamManager.findTeam(PublicTeam.PUBLIC_TEAM_NAME);
- if (defaultTeam.isJobOwner(job.getId())) {
+ if (publicTeam.isJobOwner(job.getId())) {
if (permission.getImpliedBy() == Permission.READ) {
return true;
}
}
} catch (TeamNotFoundException ex) {
- logger.error("The deafult team must exists.", ex);
+ logger.error("The public team must exists.", ex);
}
// TODO: Grant read permission to jobs marked as public scoped in all teams
}
diff --git a/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamManager.java b/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamManager.java
index 3b4e7535..42877fec 100644
--- a/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamManager.java
+++ b/hudson-core/src/main/java/org/eclipse/hudson/security/team/TeamManager.java
@@ -14,24 +14,29 @@ import com.thoughtworks.xstream.XStream;
import hudson.BulkChange;
import hudson.XmlFile;
import hudson.model.Hudson;
+import hudson.model.Item;
import hudson.model.Job;
import hudson.model.Saveable;
import hudson.model.listeners.SaveableListener;
import hudson.security.ACL;
-import hudson.security.Permission;
import hudson.security.SecurityRealm;
import hudson.util.FormValidation;
import hudson.util.XStream2;
import java.io.File;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
import org.eclipse.hudson.security.HudsonSecurityEntitiesHolder;
import org.eclipse.hudson.security.HudsonSecurityManager;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.QueryParameter;
+import org.kohsuke.stapler.StaplerRequest;
+import org.kohsuke.stapler.StaplerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,7 +55,7 @@ public final class TeamManager implements Saveable {
private transient File hudsonHomeDir;
private transient File teamsFolder;
private transient final String teamsConfigFileName = "teams.xml";
- private transient DefaultTeam defaultTeam;
+ private transient PublicTeam publicTeam;
private transient final String TEAMS_FOLDER_NAME = "teams";
public TeamManager(File homeDir) {
@@ -61,7 +66,7 @@ public final class TeamManager implements Saveable {
}
initializeXstream();
load();
- ensureDefaultTeam();
+ ensurePublicTeam();
}
public void addSysAdmin(String adminName) throws IOException {
@@ -86,11 +91,14 @@ public final class TeamManager implements Saveable {
String currentUser = HudsonSecurityManager.getAuthentication().getName();
return isSysAdmin(currentUser);
}
-
+
public boolean isCurrentUserTeamAdmin() {
String currentUser = HudsonSecurityManager.getAuthentication().getName();
+ if (isCurrentUserSysAdmin()) {
+ return true;
+ }
Team team = findCurrentUserTeam();
- if (team != null){
+ if (team != null) {
return team.isAdmin(currentUser);
}
return false;
@@ -141,10 +149,10 @@ public final class TeamManager implements Saveable {
public HttpResponse doCreateTeam(@QueryParameter String teamName, @QueryParameter String description) throws IOException {
if (!isCurrentUserSysAdmin()) {
- return new TeamUtils.ErrorHttpResponse("No permission to create team");
+ return new TeamUtils.ErrorHttpResponse("No permission to create team.");
}
if ((teamName == null) || "".equals(teamName.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team name required");
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
}
try {
Team team = createTeam(teamName, description);
@@ -156,10 +164,10 @@ public final class TeamManager implements Saveable {
public HttpResponse doDeleteTeam(@QueryParameter String teamName) throws IOException {
if (!isCurrentUserSysAdmin()) {
- return new TeamUtils.ErrorHttpResponse("No permission to delete team");
+ return new TeamUtils.ErrorHttpResponse("No permission to delete team.");
}
if ((teamName == null) || "".equals(teamName.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team name required");
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
}
try {
deleteTeam(teamName);
@@ -170,14 +178,14 @@ public final class TeamManager implements Saveable {
}
public HttpResponse doAddTeamAdmin(@QueryParameter String teamName, @QueryParameter String teamAdminSid) throws IOException {
- if (!this.isCurrentUserTeamAdmin()) {
- return new TeamUtils.ErrorHttpResponse("No permission to add team admin");
+ if (!isCurrentUserTeamAdmin()) {
+ return new TeamUtils.ErrorHttpResponse("No permission to add team admin.");
}
if ((teamName == null) || "".equals(teamName.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team name required");
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
}
if ((teamAdminSid == null) || "".equals(teamAdminSid.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team admin name required");
+ return new TeamUtils.ErrorHttpResponse("Team admin name required.");
}
Team team;
try {
@@ -196,13 +204,13 @@ public final class TeamManager implements Saveable {
public HttpResponse doRemoveTeamAdmin(@QueryParameter String teamName, @QueryParameter String teamAdminSid) throws IOException {
if (!isCurrentUserTeamAdmin()) {
- return new TeamUtils.ErrorHttpResponse("No permission to remove team admin");
+ return new TeamUtils.ErrorHttpResponse("No permission to remove team admin.");
}
if ((teamName == null) || "".equals(teamName.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team name required");
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
}
if ((teamAdminSid == null) || "".equals(teamAdminSid.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team admin name required");
+ return new TeamUtils.ErrorHttpResponse("Team admin name required.");
}
Team team;
try {
@@ -221,13 +229,13 @@ public final class TeamManager implements Saveable {
public HttpResponse doAddTeamMember(@QueryParameter String teamName, @QueryParameter String teamMemberSid) throws IOException {
if (!isCurrentUserTeamAdmin()) {
- return new TeamUtils.ErrorHttpResponse("No permission to add team member");
+ return new TeamUtils.ErrorHttpResponse("No permission to add team member.");
}
if ((teamName == null) || "".equals(teamName.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team name required");
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
}
if ((teamMemberSid == null) || "".equals(teamMemberSid.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team member name required");
+ return new TeamUtils.ErrorHttpResponse("Team member name required.");
}
Team team;
try {
@@ -249,10 +257,10 @@ public final class TeamManager implements Saveable {
return new TeamUtils.ErrorHttpResponse("No permission to remove team member");
}
if ((teamName == null) || "".equals(teamName.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team name required");
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
}
if ((teamMemberSid == null) || "".equals(teamMemberSid.trim())) {
- return new TeamUtils.ErrorHttpResponse("Team member name required");
+ return new TeamUtils.ErrorHttpResponse("Team member name required.");
}
Team team;
try {
@@ -269,10 +277,100 @@ public final class TeamManager implements Saveable {
}
}
+ public HttpResponse doMoveJob(@QueryParameter String jobId, @QueryParameter String teamName) throws IOException {
+ if (!isCurrentUserTeamAdmin()) {
+ return new TeamUtils.ErrorHttpResponse("No permission to remove team member");
+ }
+ if ((teamName == null) || "".equals(teamName.trim())) {
+ return new TeamUtils.ErrorHttpResponse("Team name required.");
+ }
+ if ((jobId == null) || "".equals(jobId.trim())) {
+ return new TeamUtils.ErrorHttpResponse("Job name required.");
+ }
+ Team newTeam;
+ try {
+ newTeam = findTeam(teamName);
+ } catch (TeamNotFoundException ex) {
+ return new TeamUtils.ErrorHttpResponse(teamName + " is not a valid team.");
+ }
+
+ Team oldTeam = findJobOwnerTeam(jobId);
+ if (oldTeam == null) {
+ return new TeamUtils.ErrorHttpResponse(jobId + " does not belong to any team.");
+ }
+
+ Item item = Hudson.getInstance().getItemById(jobId);
+ Job job;
+ if (item instanceof Job<?, ?>) {
+ job = (Job) item;
+ if (job.isBuilding()) {
+ return new TeamUtils.ErrorHttpResponse(job.getName() + " is building.");
+ }
+ try {
+ if (moveJob(job, oldTeam, newTeam)) {
+ return HttpResponses.ok();
+ } else {
+ return new TeamUtils.ErrorHttpResponse("Faile to move the jon " + jobId
+ + " to the team " + teamName);
+ }
+ } catch (IOException ex) {
+ return new TeamUtils.ErrorHttpResponse(teamName + " is not a valid team.");
+ }
+ } else {
+ return new TeamUtils.ErrorHttpResponse(jobId + " not a valid job Id.");
+ }
+ }
+
public HttpResponse doCheckSid(@QueryParameter String sid) throws IOException {
return FormValidation.respond(FormValidation.Kind.OK, TeamUtils.getIcon(sid));
}
+ private boolean moveJob(Job job, Team oldTeam, Team newTeam) throws IOException {
+ try {
+ File jobRootDir = job.getRootDir();
+ File newJobRootDir = new File(getJobsFolder(newTeam), job.getName());
+ newJobRootDir.mkdirs();
+ if (jobRootDir.renameTo(newJobRootDir)) {
+ String oldJobId = job.getId();
+ oldTeam.removeJob(job.getId());
+ String newJobId = getTeamQualifiedJobId(newTeam, job.getName());
+ job.setId(newJobId);
+ job.save();
+ newTeam.addJob(newJobId);
+ Hudson.getInstance().replaceItemId(oldJobId, newJobId);
+ return true;
+ }
+ return false;
+ } catch (Exception exc) {
+ throw new IOException(exc);
+ }
+ }
+
+ /**
+ * Get the name of the teams as JSON
+ * @return HttpResponse with JSON as content type
+ */
+ public HttpResponse doGetTeamsJson() {
+ return new HttpResponse() {
+ @Override
+ public void generateResponse(StaplerRequest sr, StaplerResponse rsp, Object o) throws IOException, ServletException {
+ rsp.setStatus(HttpServletResponse.SC_OK);
+ rsp.setContentType("application/json");
+ PrintWriter w = new PrintWriter(rsp.getWriter());
+ w.println("{");
+ for (int i = 0; i < teams.size(); i++) {
+ w.print("\"" + teams.get(i).getName() + "\":\"" + teams.get(i).getName() + "\"");
+ if (i < teams.size() - 1){
+ w.println(",");
+ }
+ }
+ w.println("}");
+ w.close();
+ }
+ };
+
+ }
+
public void addUser(String teamName, String userName) throws TeamNotFoundException, IOException {
Team team = findTeam(teamName);
team.addMember(userName);
@@ -311,26 +409,26 @@ public final class TeamManager implements Saveable {
return team;
}
- public boolean isCurrentUserHasAccess(String jobName) {
+ public boolean isCurrentUserHasAccess(String jobId) {
Team userTeam = findCurrentUserTeam();
if (userTeam != null) {
- if (userTeam.isJobOwner(jobName)) {
+ if (userTeam.isJobOwner(jobId)) {
return true;
} else {
- return isAnonymousJob(jobName);
+ return isAnonymousJob(jobId);
}
} else {
- return isAnonymousJob(jobName);
+ return isAnonymousJob(jobId);
}
}
- public boolean isUserHasAccess(String userName, String jobName) {
+ public boolean isUserHasAccess(String userName, String jobId) {
Team userTeam = findUserTeam(userName);
if (userTeam != null) {
- return userTeam.isJobOwner(jobName);
+ return userTeam.isJobOwner(jobId);
} else {
for (Team team : teams) {
- if (team.isJobOwner(jobName)) {
+ if (team.isJobOwner(jobId)) {
// Job belongs to a team so has no access
return false;
}
@@ -359,42 +457,42 @@ public final class TeamManager implements Saveable {
return null;
}
- public Team findJobOwnerTeam(String jobName) {
+ public Team findJobOwnerTeam(String jobId) {
for (Team team : teams) {
- if (team.isJobOwner(jobName)) {
+ if (team.isJobOwner(jobId)) {
return team;
}
}
return null;
}
- public void addJobToCurrentUserTeam(String jobName) throws IOException {
- addJob(findCurrentUserTeam(), jobName);
+ public void addJobToCurrentUserTeam(String jobId) throws IOException {
+ addJob(findCurrentUserTeam(), jobId);
}
- public void addJobToUserTeam(String userName, String jobName) throws IOException {
- addJob(findUserTeam(userName), jobName);
+ public void addJobToUserTeam(String userName, String jobId) throws IOException {
+ addJob(findUserTeam(userName), jobId);
}
- public void addJob(Team team, String jobName) throws IOException {
+ public void addJob(Team team, String jobId) throws IOException {
if (team != null) {
- team.addJob(jobName);
+ team.addJob(jobId);
save();
}
}
- public void removeJobFromCurrentUserTeam(String jobName) throws IOException {
- removeJob(findCurrentUserTeam(), jobName);
+ public void removeJobFromCurrentUserTeam(String jobId) throws IOException {
+ removeJob(findCurrentUserTeam(), jobId);
}
- public void removeJobFromUserTeam(String userName, String jobName) throws IOException {
- removeJob(findUserTeam(userName), jobName);
+ public void removeJobFromUserTeam(String userName, String jobId) throws IOException {
+ removeJob(findUserTeam(userName), jobId);
}
- public void removeJob(Team team, String jobName) throws IOException {
+ public void removeJob(Team team, String jobId) throws IOException {
if (team != null) {
- team.removeJob(jobName);
+ team.removeJob(jobId);
save();
}
}
@@ -428,34 +526,79 @@ public final class TeamManager implements Saveable {
}
}
- public String getTeamQualifiedJobId(String jobId) {
- if (defaultTeam.isJobOwner(jobId)) {
- return jobId;
+ /**
+ * Get the current user team qualified Id for the job name
+ *
+ * @param jobName
+ * @return String, Qualified Job ID
+ */
+ public String getTeamQualifiedJobId(String jobName) {
+ if (publicTeam.isJobOwner(jobName)) {
+ return jobName;
}
Team team = findCurrentUserTeam();
- if ((team != null) && !Team.DEFAULT_TEAM_NAME.equals(team.getName())) {
- jobId = team.getName() + "_" + jobId;
+ if ((team != null) && !Team.PUBLIC_TEAM_NAME.equals(team.getName())) {
+ jobName = team.getName() + "." + jobName;
+ }
+ return jobName;
+ }
+
+ /**
+ * Get the current user team qualified Id for the job name
+ * @param team
+ * @param jobName
+ * @return String, Team qualified Job ID
+ */
+ public String getTeamQualifiedJobId(Team team, String jobName) {
+ if (team == publicTeam) {
+ return jobName;
}
- return jobId;
+ return team.getName() + "." + jobName;
}
+ /**
+ * The Folder where all the jobs of the team to which this jobId belongs to
+ * are stored
+ *
+ * @param jobId
+ * @return String, path to the team jobs folder
+ */
public String getJobsFolderName(String jobId) {
Team team = findJobOwnerTeam(jobId);
// May be just created job
if (team == null) {
team = findCurrentUserTeam();
}
- if ((team != null) && !Team.DEFAULT_TEAM_NAME.equals(team.getName())) {
+ if ((team != null) && !Team.PUBLIC_TEAM_NAME.equals(team.getName())) {
return TEAMS_FOLDER_NAME + "/" + team.getName() + "/" + Team.JOBS_FOLDER_NAME;
}
return "jobs";
}
+ /**
+ * Get the folder where the jobs of this team are stored
+ *
+ * @param team
+ * @return
+ */
+ public File getJobsFolder(Team team) {
+ if ((team != null) && !Team.PUBLIC_TEAM_NAME.equals(team.getName())) {
+ return new File(teamsFolder, "/" + team.getName() + "/" + Team.JOBS_FOLDER_NAME);
+ } else {
+ return new File(hudsonHomeDir, "jobs");
+ }
+ }
+
+ /**
+ * Get the root folders of all the jobs known to this Team manager
+ *
+ * @return
+ */
public File[] getJobsRootFolders() {
List<File> jobsRootFolders = new ArrayList<File>();
for (Team team : teams) {
- if (Team.DEFAULT_TEAM_NAME.equals(team.getName())) {
+ if (Team.PUBLIC_TEAM_NAME.equals(team.getName())) {
jobsRootFolders.addAll(team.getJobsRootFolders(hudsonHomeDir));
} else {
jobsRootFolders.addAll(team.getJobsRootFolders(teamsFolder));
@@ -509,13 +652,13 @@ public final class TeamManager implements Saveable {
return new TeamBasedACL(this, TeamBasedACL.SCOPE.JOB, team);
}
- Team getDefaultTeam() throws TeamNotFoundException {
- return findTeam(DefaultTeam.DEFAULT_TEAM_NAME);
+ Team getPublicTeam() throws TeamNotFoundException {
+ return findTeam(PublicTeam.PUBLIC_TEAM_NAME);
}
- private boolean isAnonymousJob(String jobName) {
+ private boolean isAnonymousJob(String jobId) {
for (Team team : teams) {
- if (team.isJobOwner(jobName)) {
+ if (team.isJobOwner(jobId)) {
// job belongs to another team so has no access
return false;
}
@@ -548,24 +691,25 @@ public final class TeamManager implements Saveable {
}
}
- private void ensureDefaultTeam() {
- defaultTeam = new DefaultTeam(this);
+ private void ensurePublicTeam() {
+ publicTeam = new PublicTeam(this);
try {
- Team team = findTeam(DefaultTeam.DEFAULT_TEAM_NAME);
+ Team team = findTeam(PublicTeam.PUBLIC_TEAM_NAME);
teams.remove(team);
} catch (TeamNotFoundException ex) {
// It's ok, we are going to remove it any way
}
try {
- defaultTeam.loadExistingJobs(hudsonHomeDir);
+ publicTeam.loadExistingJobs(hudsonHomeDir);
} catch (IOException ex) {
logger.error("Failed to load existing jobs", ex);
}
- teams.add(defaultTeam);
+ teams.add(publicTeam);
}
private void initializeXstream() {
xstream.alias("teamManager", TeamManager.class);
xstream.alias("team", Team.class);
+ xstream.alias("publicTeam", PublicTeam.class);
}
}
diff --git a/hudson-core/src/main/resources/hudson/model/View/newJob.jelly b/hudson-core/src/main/resources/hudson/model/View/newJob.jelly
index c3ed4aec..77b269a1 100644
--- a/hudson-core/src/main/resources/hudson/model/View/newJob.jelly
+++ b/hudson-core/src/main/resources/hudson/model/View/newJob.jelly
@@ -31,7 +31,7 @@
</h1>
<j:invokeStatic var="jobs" className="hudson.model.Items" method="all" />
- <n:form nameTitle="${%Job name}" copyTitle="${%Copy existing job}" copyNames="${app.topLevelItemNames}"
+ <n:form nameTitle="${%Job name}" copyTitle="${%Copy existing job}" copyNames="${app.jobNames}"
descriptors="${jobs}" checkUrl="checkJobName" xmlns:n="/lib/hudson/newFromList" />
</l:main-panel>
</l:layout>
diff --git a/hudson-core/src/main/resources/hudson/model/View/sidepanel.jelly b/hudson-core/src/main/resources/hudson/model/View/sidepanel.jelly
index f4f77270..7499d72d 100644
--- a/hudson-core/src/main/resources/hudson/model/View/sidepanel.jelly
+++ b/hudson-core/src/main/resources/hudson/model/View/sidepanel.jelly
@@ -35,7 +35,7 @@
<j:if test="${app.teamManager.isCurrentUserSysAdmin()}">
<l:task icon="images/24x24/user.png" href="${rootURL}/teamManager" title="${%Manage Teams}"/>
</j:if>
- <j:if test="${app.teamManager.isCurrentUserTeamAdmin()}">
+ <j:if test="${app.teamManager.isCurrentUserTeamAdmin() &amp;&amp; !app.teamManager.isCurrentUserSysAdmin()}">
<l:task icon="images/24x24/user.png" href="${rootURL}/teamManager" title="${%Manage Team}"/>
</j:if>
</j:if>
diff --git a/hudson-core/src/main/resources/hudson/security/SecurityRealm/loginLink.jelly b/hudson-core/src/main/resources/hudson/security/SecurityRealm/loginLink.jelly
index 0c149357..13d28110 100644
--- a/hudson-core/src/main/resources/hudson/security/SecurityRealm/loginLink.jelly
+++ b/hudson-core/src/main/resources/hudson/security/SecurityRealm/loginLink.jelly
@@ -57,7 +57,7 @@
}
function submitLoginForm(){
- showMessage(jQuery('#loginMsg'), "Logging in ..", "blue");
+ showLoginMessage(jQuery('#loginMsg'), "Logging in ..", "blue");
var dataString = jQuery("#loginForm").serialize();
jQuery.ajax({
type: 'POST',
@@ -69,13 +69,13 @@
},
error: function(){
var msg = 'Failed to login. Check your credentials and try again.';
- showMessage(jQuery('#loginMsg'), msg, "red");
+ showLoginMessage(jQuery('#loginMsg'), msg, "red");
},
dataType: "html"
});
}
- function showMessage(widget, msg, color){
+ function showLoginMessage(widget, msg, color){
widget.text(msg);
widget.css("color",color);
widget.show();
diff --git a/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/index.jelly b/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/index.jelly
index a12a6f90..63d4629c 100644
--- a/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/index.jelly
+++ b/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/index.jelly
@@ -30,7 +30,7 @@
<j:if test='${it.isCurrentUserSysAdmin()}'>
<st:include page="teamManager.jelly" />
</j:if>
- <j:if test='${it.isCurrentUserTeamAdmin()}'>
+ <j:if test='${it.isCurrentUserTeamAdmin() &amp;&amp; !it.isCurrentUserSysAdmin()}'>
<st:include page="teamAdmin.jelly"/>
</j:if>
diff --git a/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/sidepanel.jelly b/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/sidepanel.jelly
index d60a6677..07c069f1 100644
--- a/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/sidepanel.jelly
+++ b/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/sidepanel.jelly
@@ -19,36 +19,36 @@
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
- <l:header />
- <l:side-panel>
- <l:tasks>
- <l:task icon="images/24x24/up.png" href="${rootURL}/" title="${%Back to Main Dashboard}" />
+ <l:header />
+ <l:side-panel>
+ <l:tasks>
+ <l:task icon="images/24x24/up.png" href="${rootURL}/" title="${%Back to Main Dashboard}" />
- <l:task icon="images/24x24/new-package.png" href="${rootURL}/${it.viewUrl}newJob" title="${%New Job}" permission="${it.itemCreatePermission}" it="${app}" />
- <l:task icon="images/24x24/setting.png" href="${rootURL}/manage" title="${%Manage Hudson}" permission="${app.ADMINISTER}" it="${app}" />
- <j:choose>
- <j:when test="${it.class.name=='hudson.model.AllView'}">
- <l:task icon="images/24x24/user.png" href="${rootURL}/people/" title="${%People}" />
- </j:when>
- <j:when test="${it.isDefault() or it.hasPeople()}">
- <l:task icon="images/24x24/user.png" href="${rootURL}/${it.viewUrl}people/" title="${%People}" />
- </j:when>
- </j:choose>
- <l:task icon="images/24x24/graph.png" href="${rootURL}/${it.url}builds" title="${%Build History}"/>
- <j:if test="${it.isEditable()}">
- <!-- /configure URL on Hudson object is overloaded with Hudson's system config, so always use the explicit name. -->
- <l:task icon="images/24x24/gear.png" href="${rootURL}/${it.viewUrl}configure" title="${%Configure View}" permission="${it.CONFIGURE}" />
- </j:if>
- <j:if test="${it.owner.canDelete(it)}">
- <l:taskWithDialog icon="images/24x24/edit-delete.png" dialogPanel="deleteConfirmationPanel.jelly" href="delete" title="${%Delete View}" permission="${it.DELETE}" />
- </j:if>
- <j:if test="${app.fingerprintMap.ready}">
- <l:task icon="images/24x24/search.png" href="${rootURL}/projectRelationship" title="${%Job Relationship}" />
- <l:task icon="images/24x24/fingerprint.png" href="${rootURL}/fingerprintCheck" title="${%Check File Fingerprint}" />
- </j:if>
+ <l:task icon="images/24x24/new-package.png" href="${rootURL}/${it.viewUrl}newJob" title="${%New Job}" permission="${it.itemCreatePermission}" it="${app}" />
+ <l:task icon="images/24x24/setting.png" href="${rootURL}/manage" title="${%Manage Hudson}" permission="${app.ADMINISTER}" it="${app}" />
+ <j:choose>
+ <j:when test="${it.class.name=='hudson.model.AllView'}">
+ <l:task icon="images/24x24/user.png" href="${rootURL}/people/" title="${%People}" />
+ </j:when>
+ <j:when test="${it.isDefault() or it.hasPeople()}">
+ <l:task icon="images/24x24/user.png" href="${rootURL}/${it.viewUrl}people/" title="${%People}" />
+ </j:when>
+ </j:choose>
+ <l:task icon="images/24x24/graph.png" href="${rootURL}/${it.url}builds" title="${%Build History}"/>
+ <j:if test="${it.isEditable()}">
+ <!-- /configure URL on Hudson object is overloaded with Hudson's system config, so always use the explicit name. -->
+ <l:task icon="images/24x24/gear.png" href="${rootURL}/${it.viewUrl}configure" title="${%Configure View}" permission="${it.CONFIGURE}" />
+ </j:if>
+ <j:if test="${it.owner.canDelete(it)}">
+ <l:taskWithDialog icon="images/24x24/edit-delete.png" dialogPanel="deleteConfirmationPanel.jelly" href="delete" title="${%Delete View}" permission="${it.DELETE}" />
+ </j:if>
+ <j:if test="${app.fingerprintMap.ready}">
+ <l:task icon="images/24x24/search.png" href="${rootURL}/projectRelationship" title="${%Job Relationship}" />
+ <l:task icon="images/24x24/fingerprint.png" href="${rootURL}/fingerprintCheck" title="${%Check File Fingerprint}" />
+ </j:if>
- <t:actions />
+ <t:actions />
- </l:tasks>
- </l:side-panel>
+ </l:tasks>
+ </l:side-panel>
</j:jelly>
diff --git a/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/teamManager.jelly b/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/teamManager.jelly
index 4709cd95..925543da 100644
--- a/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/teamManager.jelly
+++ b/hudson-core/src/main/resources/org/eclipse/hudson/security/team/TeamManager/teamManager.jelly
@@ -16,102 +16,170 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout">
- <div id="container">
-
- <j:if test="${it.teams.size() == 1}">
- <h2>
- <img src="${imagesURL}/48x48/warning.png"/>
- This Hudson does not have any teams!!
- </h2>
- </j:if>
-
- <div id="teamContainer">
- <ul class="team">
- <j:forEach var="team" items="${it.teams}">
- <j:if test='${!team.name.equals("default")}'>
- <st:include it="${team}" page="team.jelly"/>
+ <div id="container">
+ <div id="outerTabs">
+ <ul>
+ <li>
+ <a href="#teamTab">Manage Teams</a>
+ </li>
+ <li>
+ <a href="#jobsTab">Manage Team Jobs</a>
+ </li>
+
+ </ul>
+ <div id="teamTab">
+ <div id="teamContainer">
+ <div id="noTeamsMsg">
+ <j:if test="${it.teams.size() == 1}">
+ <h2>
+ <img src="${imagesURL}/48x48/warning.png"/>
+ This Hudson does not have any teams!!
+ </h2>
</j:if>
- </j:forEach>
- </ul>
- <br style="clear:both"/>
- </div>
- <div>
- <input type="button" id="createTeamButton" value="Create New Team" />
- <span id="createTeamMsg">
- <!-- message goes here -->
- </span>
+ </div>
+ <ul class="team">
+ <j:forEach var="team" items="${it.teams}">
+ <j:if test='${!team.name.equals("public")}'>
+ <st:include it="${team}" page="team.jelly"/>
+ </j:if>
+ </j:forEach>
+ </ul>
+ <br style="clear:both"/>
+ </div>
+ <div>
+ <input type="button" id="createTeamButton" value="Create New Team" />
+ <span id="createTeamMsg">
+ <!-- message goes here -->
+ </span>
+ </div>
+ </div>
+ <div id="jobsTab">
+ <j:if test="${app.items.size() == 0}">
+ <h2>
+ <img src="${imagesURL}/48x48/warning.png"/>
+ This Hudson does not have any jobs!!
+ </h2>
+ </j:if>
+
+ <div id="teamJobsContainer">
+ <table width="100%" border="0" id="teamJobsList" cellpadding="5">
+ <j:forEach var="job" items="${app.items}">
+ <tr>
+ <td class="column1">
+ <input class="move_cb_${job.name}" type="checkbox" value="${job.id}"/>
+ </td>
+ <td class="column2">
+ ${job.name}
+ </td>
+ <td class="column3">
+ <span id="job_colum3_span_${job.id}">
+ ${it.findJobOwnerTeam(job.id).name}
+ </span>
+ </td>
+ </tr>
+ </j:forEach>
+ </table>
+ <br style="clear:both"/>
+ </div>
+ <div>
+ <input type="button" id="moveJobsButton" value="Move Jobs" />
+ <span id="createTeamMsg">
+ <!-- message goes here -->
+ </span>
+ </div>
</div>
-
</div>
+ </div>
- <!-- Template for Admin or member add -->
- <div style="margin-top: 10px; display: none" id="userTemplate">
- <li>
- <input type="hidden" name="hiddenUserName"/>
- <input type="hidden" name="hiddenTeamName"/>
- <img name="typeIcon"/>
- <span style="margin-left:10px; font-size:13px;">
- </span>
- <img name="deleteIcon" style="margin-left:25px" src="${imagesURL}/16x16/delete.png"/>
- </li>
- </div>
+ <!-- Template for Admin or member add -->
+ <div style="margin-top: 10px; display: none" id="userTemplate">
+ <li>
+ <input type="hidden" name="hiddenUserName"/>
+ <input type="hidden" name="hiddenTeamName"/>
+ <img name="typeIcon"/>
+ <span style="margin-left:10px; font-size:13px;">
+ </span>
+ <img name="deleteIcon" style="margin-left:25px" src="${imagesURL}/16x16/delete.png"/>
+ </li>
+ </div>
- <!-- Dialog template for creating team -->
- <div style="margin-top: 10px; display: none" id="dialog-create-team" title="Create New Team">
- <div>
- <label for="teamName">Name:</label>
- <input type="text" name="teamName" id="teamName" size="25"/>
- <br/>
- <label for="teamDesc">Description:</label>
- <input type="text" name="teamDesc" id="teamDesc" size="50"/>
- </div>
+ <!-- Dialog template for creating team -->
+ <div style="margin-top: 10px; display: none" id="dialog-create-team" title="Create New Team">
+ <div>
+ <label for="teamName">Name:</label>
+ <input type="text" name="teamName" id="teamName" size="25"/>
+ <br/>
+ <label for="teamDesc">Description:</label>
+ <input type="text" name="teamDesc" id="teamDesc" size="50"/>
+ </div>
+ <div style="margin-top:10px">
+ <span id="teamAddMsg">
+ <!-- message goes here -->
+ </span>
+ </div>
+ </div>
+
+ <!-- Dialog template for deleting team -->
+ <div style="margin-top: 10px; display: none" id="dialog-delete-team">
+ <div>
+ <span>
+ The team will be permanently deleted. Do you really want to delete the team?
+ </span>
<div style="margin-top:10px">
- <span id="teamAddMsg">
+ <span id="teamDeleteMsg">
<!-- message goes here -->
</span>
</div>
</div>
-
- <!-- Dialog template for deleting team -->
- <div style="margin-top: 10px; display: none" id="dialog-delete-team">
- <div>
- <span>
- The team will be permanently deleted. Do you really want to delete the team?
+ </div>
+
+ <!-- Dialog template for adding member -->
+ <div style="margin-top: 10px; display: none" id="dialog-add-user">
+ <div>
+ <label>${%User or Group Name}:</label>
+ <input style="margin-left:5px" size="35" type="text" id="sidName" />
+ <div style="margin-top:10px">
+ <span id="userAddMsg">
+ <!-- message goes here -->
</span>
- <div style="margin-top:10px">
- <span id="teamDeleteMsg">
- <!-- message goes here -->
- </span>
- </div>
</div>
</div>
+ </div>
- <!-- Dialog template for adding member -->
- <div style="margin-top: 10px; display: none" id="dialog-add-user">
- <div>
- <label>${%User or Group Name}:</label>
- <input style="margin-left:5px" size="35" type="text" id="sidName" />
- <div style="margin-top:10px">
- <span id="userAddMsg">
- <!-- message goes here -->
- </span>
- </div>
+ <!-- Dialog template for removing user -->
+ <div style="margin-top: 10px; display: none" id="dialog-remove-user">
+ <div>
+ <span>
+ Do you really want to delete the member from the team?
+ </span>
+ <div style="margin-top:10px">
+ <span id="userRemoveMsg">
+ <!-- message goes here -->
+ </span>
</div>
</div>
-
- <!-- Dialog template for removing user -->
- <div style="margin-top: 10px; display: none" id="dialog-remove-user">
- <div>
- <span>
- Do you really want to delete the member from the team?
+ </div>
+
+ <!-- Dialog template for moving jobs -->
+ <div style="margin-top: 10px; display: none" id="dialog-move-jobs">
+ <div>
+ <span>
+ Following jobs will be moved to the selected Team. <br/>
+ Before moving the jobs make sure they are not building and not used.
+ </span>
+ <ul id="selectedJobs">
+ <!-- dynamically filled -->
+ </ul>
+ <select id="teamChoice">
+ <option value="loading">Loading ..</option>
+ </select>
+ <div style="margin-top:10px">
+ <span id="moveJobMsg">
+ <!-- dynamically inserted -->
</span>
- <div style="margin-top:10px">
- <span id="userRemoveMsg">
- <!-- message goes here -->
- </span>
- </div>
</div>
</div>
+ </div>
</j:jelly>
\ No newline at end of file
diff --git a/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamAwareSecurityRealmTest.java b/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamAwareSecurityRealmTest.java
index 6b4fe739..0e9a5ee5 100644
--- a/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamAwareSecurityRealmTest.java
+++ b/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamAwareSecurityRealmTest.java
@@ -99,13 +99,13 @@ public class TeamAwareSecurityRealmTest {
}
@Test
- public void testDefaultJobPermission() throws IOException, TeamManager.TeamNotFoundException, TeamManager.TeamAlreadyExistsException {
+ public void testPublicJobPermission() throws IOException, TeamManager.TeamNotFoundException, TeamManager.TeamAlreadyExistsException {
String teamName = "team1";
Team newTeam = teamManager.createTeam(teamName);
hudsonSecurityManager.setSecurityRealm(new TeamAwareSecurityRealmImpl(newTeam, false, false));
FreeStyleProject freeStyleJob = new FreeStyleProjectMock("testJob");
- teamManager.getDefaultTeam().addJob(freeStyleJob.getName());
+ teamManager.getPublicTeam().addJob(freeStyleJob.getName());
//Dummy Sid
Sid sid = new PrincipalSid("Paul");
diff --git a/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamJobACLTest.java b/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamJobACLTest.java
index c22b2301..dddfd902 100644
--- a/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamJobACLTest.java
+++ b/hudson-core/src/test/java/org/eclipse/hudson/security/team/TeamJobACLTest.java
@@ -82,51 +82,51 @@ public class TeamJobACLTest {
}
@Test
- public void testDefaultJobPermission() throws IOException {
+ public void testPublicJobPermission() throws IOException {
FreeStyleProject freeStyleJob = new FreeStyleProjectMock("testJob");
try {
- teamManager.getDefaultTeam().addJob(freeStyleJob.getName());
+ teamManager.getPublicTeam().addJob(freeStyleJob.getName());
} catch (TeamNotFoundException ex) {
- fail("Default Team must exist");
+ fail("Public Team must exist");
}
Sid sid = new PrincipalSid("Paul");
TeamBasedACL teamBasedACL = new TeamBasedACL(teamManager, TeamBasedACL.SCOPE.JOB, freeStyleJob);
- Assert.assertFalse("Paul is not a SysAdmin and should not have default Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
- Assert.assertTrue("Paul should have default Job READ permission", teamBasedACL.hasPermission(sid, readPermission).booleanValue());
+ Assert.assertFalse("Paul is not a SysAdmin and should not have public Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
+ Assert.assertTrue("Paul should have pubic Job READ permission", teamBasedACL.hasPermission(sid, readPermission).booleanValue());
teamManager.addSysAdmin("Paul");
- Assert.assertTrue("Paul is a SysAdmin and should have default Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
+ Assert.assertTrue("Paul is a SysAdmin and should have public Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
}
@Test
- public void testAnonymousDefaultJobPermission() throws IOException {
+ public void testAnonymousPublicJobPermission() throws IOException {
FreeStyleProject freeStyleJob = new FreeStyleProjectMock("testJob");
try {
- teamManager.getDefaultTeam().addJob(freeStyleJob.getName());
+ teamManager.getPublicTeam().addJob(freeStyleJob.getName());
} catch (TeamNotFoundException ex) {
- fail("Default Team must exist");
+ fail("Public Team must exist");
}
Sid sid = ACL.ANONYMOUS;
TeamBasedACL teamBasedACL = new TeamBasedACL(teamManager, TeamBasedACL.SCOPE.JOB, freeStyleJob);
- Assert.assertFalse("Anonymous should not have default Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
- Assert.assertTrue("Anonymous should have default Job READ permission", teamBasedACL.hasPermission(sid, readPermission).booleanValue());
+ Assert.assertFalse("Anonymous should not have public Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
+ Assert.assertTrue("Anonymous should have public Job READ permission", teamBasedACL.hasPermission(sid, readPermission).booleanValue());
}
@Test
- public void testEveryoneDefaultJobPermission() throws IOException {
+ public void testEveryonePublicJobPermission() throws IOException {
FreeStyleProject freeStyleJob = new FreeStyleProjectMock("testJob");
try {
- teamManager.getDefaultTeam().addJob(freeStyleJob.getName());
+ teamManager.getPublicTeam().addJob(freeStyleJob.getName());
} catch (TeamNotFoundException ex) {
- fail("Default Team must exist");
+ fail("Public Team must exist");
}
Sid sid = ACL.EVERYONE;
TeamBasedACL teamBasedACL = new TeamBasedACL(teamManager, TeamBasedACL.SCOPE.JOB, freeStyleJob);
- Assert.assertFalse("Every one should not have default Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
- Assert.assertTrue("Every one should have default Job READ permission", teamBasedACL.hasPermission(sid, readPermission).booleanValue());
+ Assert.assertFalse("Every one should not have public Job CONFIGURE permission", teamBasedACL.hasPermission(sid, configurePermission).booleanValue());
+ Assert.assertTrue("Every one should have piublic Job READ permission", teamBasedACL.hasPermission(sid, readPermission).booleanValue());
}
} \ No newline at end of file
diff --git a/hudson-war/src/main/webapp/css/team-manager.css b/hudson-war/src/main/webapp/css/team-manager.css
index 77b879db..6716bf38 100644
--- a/hudson-war/src/main/webapp/css/team-manager.css
+++ b/hudson-war/src/main/webapp/css/team-manager.css
@@ -60,6 +60,32 @@ p {
border-bottom-color: #dfcdeb;
}
+#outerTabs {
+ padding: 0px;
+ background: none;
+ border-width: 0px;
+}
+
+#outerTabs .ui-tabs-nav {
+ padding-left: 0px;
+ background: transparent;
+ border-width: 0px 0px 1px 0px;
+ border-color:#d4bde6;
+ -moz-border-radius: 0px;
+ -webkit-border-radius: 0px;
+ border-radius: 0px;
+}
+
+#outerTabs .ui-tabs-nav li {
+ border-color:#d4bde6;
+}
+
+#outerTabs .ui-tabs-panel {
+ /*background: url(images/ui-bg_highlight-hard_100_f5f3e5_1x100.png) repeat-x scroll 50% top #f5f3e5;*/
+ border-width: 0px 1px 1px 1px;
+ border-color:#d4bde6;
+}
+
ul.team label{
font-weight: bold;
}
diff --git a/hudson-war/src/main/webapp/scripts/team-manager.js b/hudson-war/src/main/webapp/scripts/team-manager.js
index ee18dc1c..de5454d5 100644
--- a/hudson-war/src/main/webapp/scripts/team-manager.js
+++ b/hudson-war/src/main/webapp/scripts/team-manager.js
@@ -16,16 +16,34 @@
jQuery.noConflict();
+var images = [
+ imageRoot + '/green-check.jpg',
+ imageRoot + '/progressbar.gif',
+ imageRoot + '/error.png',
+ imageRoot + '/16x16/warning.png'
+];
+
var pageInitialized = false;
jQuery(document).ready(function() {
//To avoid multiple fire of document.ready
- if (pageInitialized){
+ if (pageInitialized) {
return;
}
pageInitialized = true;
+ jQuery("#outerTabs").tabs();
+
+ jQuery("#outerTabs tr").hover(
+ function() {
+ jQuery(this).css("background", "#EEEDED");
+ },
+ function() {
+ jQuery(this).css("background", "");
+ }
+ );
+
var createTeamButton = jQuery('#createTeamButton');
createTeamButton.button();
createTeamButton.unbind("click").click(function() {
@@ -66,6 +84,11 @@ jQuery(document).ready(function() {
});
});
+ var moveJobsButton = jQuery('#moveJobsButton');
+ moveJobsButton.button();
+ moveJobsButton.unbind("click").click(function() {
+ moveJobsButtonAction();
+ });
jQuery('.teamList li').each(function() {
verifySid(this);
@@ -101,6 +124,7 @@ function createTeam(teamName, teamDesc) {
description: teamDesc
},
success: function(result) {
+ jQuery("#noTeamsMsg").remove();
var resultItem = jQuery(result);
jQuery(resultItem).appendTo(jQuery('ul.team'));
var teamAdminAddButton = jQuery('.teamAdminAddButton', jQuery(resultItem));
@@ -348,6 +372,84 @@ function removeTeamMember(teamName, memberName, parent) {
});
}
+var moveCount;
+var jobsToMove;
+function moveJobsButtonAction() {
+ jQuery("#selectedJobs").empty();
+ jobsToMove = getJobsToMove();
+ moveCount = jobsToMove.length;
+ for (var i = 0; i < jobsToMove.length; i++) {
+ var item = '<li value="' + jobsToMove[i] + '">' + jobsToMove[i] + ' <img style="display: none"/></li>';
+ jQuery(item).attr("value", jobsToMove[i])
+ jQuery(item).appendTo(jQuery("#selectedJobs"));
+ }
+
+ jQuery('#dialog-move-jobs').dialog({
+ resizable: false,
+ height: 200 + moveCount * 20,
+ width: 400,
+ modal: true,
+ title: "Move Jobs to another Team",
+ buttons: {
+ 'Move': function() {
+ if (moveCount > 0) {
+ var teamName = jQuery("#teamChoice option:selected").val();
+ for (var i = 0; i < jobsToMove.length; i++) {
+ var img = jQuery("#selectedJobs li[value='" + jobsToMove[i] + "']").children('img');
+ jQuery(img).attr('src', imageRoot + '/progressbar.gif');
+ jQuery(img).show();
+ moveJobs(jobsToMove[i], teamName);
+ }
+ }
+ },
+ Cancel: function() {
+ jQuery(this).dialog("close");
+ }
+ }
+ });
+
+ jQuery.getJSON('getTeamsJson', function(json) {
+ jQuery('#teamChoice').empty();
+ jQuery.each(json, function(key, val) {
+ var item = '<option value="' + key + '">' + val + '</option>';
+ jQuery(item).appendTo(jQuery('#teamChoice'));
+ });
+ });
+
+}
+
+function getJobsToMove() {
+ var jobs = [];
+ jQuery('#teamJobsContainer input[@type=checkbox]:checked').each(function() {
+ jobs.push(jQuery(this).val());
+ });
+ return jobs;
+}
+
+function moveJobs(jobId, teamName) {
+ jQuery.ajax({
+ type: 'POST',
+ url: "moveJob",
+ data: {
+ jobId: jobId,
+ teamName: teamName
+ },
+ success: function() {
+ var img = jQuery("#selectedJobs li[value='" + jobId + "']").children('img');
+ jQuery(img).attr('src', imageRoot + '/green-check.jpg');
+ jQuery("#job_colum3_span_" + jobId).text(teamName);
+ moveCount--;
+ if (moveCount === 0) {
+ jQuery('#dialog-move-jobs').dialog("close");
+ }
+ },
+ error: function(msg) {
+ showMessage(msg.responseText, true, jQuery('#moveJobMsg'));
+ },
+ dataType: "html"
+ });
+}
+
function verifySid(sidElement) {
var sid = jQuery(sidElement).children('span').text();
jQuery.ajax({

Back to the top