Add user. Implemented repository view and git access restrictions.
1 files deleted
7 files added
19 files modified
| | |
| | | #
|
| | |
|
| | | # Allow push/pull over http/https with JGit servlet
|
| | | git.allowPushPull = true
|
| | | git.enableGitServlet = true
|
| | |
|
| | | # Base folder for repositories
|
| | | # Use forward slashes even on Windows!!
|
| | |
| | | #
|
| | | # Authentication Settings
|
| | | #
|
| | |
|
| | | # Require authentication for http/https push/pull access of git repositories
|
| | | git.authenticate = true
|
| | |
|
| | | # Require authentication to see everything but the admin pages
|
| | | web.authenticateViewPages = false
|
| | |
| | | # Jetty Settings
|
| | | #
|
| | |
|
| | | # use NIO connectors. If false, socket connectors will be used.
|
| | | # Use Jetty NIO connectors. If false, Jetty Socket connectors will be used.
|
| | | server.useNio = true
|
| | |
|
| | | # Standard http port to serve. <= 0 disables this connector.
|
| | | server.httpPort = 80
|
| | | server.httpPort = 0
|
| | |
|
| | | # Secure/SSL https port to serve. <= 0 disables this connector.
|
| | | server.httpsPort = 443
|
| | |
| | | # You may specify an ip or an empty value to bind to all interfaces.
|
| | | server.httpsBindInterface = localhost
|
| | |
|
| | | # Password for SSL keystore (keystore password and certificate password must match)
|
| | | # Password for SSL keystore.
|
| | | # Keystore password and certificate password must match.
|
| | | # This is provided for convenience, its probably more secure to set this value
|
| | | # using the --storePassword command line parameter.
|
| | | server.storePassword = dosomegit
|
| | |
|
| | | # Port for shutdown monitor to listen on.
|
| | |
| | |
|
| | | public final static String VERSION = "0.1.0-SNAPSHOT";
|
| | |
|
| | | public final static String ADMIN_ROLE = "admin";
|
| | |
|
| | | public final static String PULL_ROLE = "pull";
|
| | |
|
| | | public final static String PUSH_ROLE = "push";
|
| | | public final static String ADMIN_ROLE = "#admin";
|
| | |
|
| | | public final static String PROPERTIES_FILE = "gitblit.properties";
|
| | |
|
| | | public static enum AccessRestrictionType {
|
| | | NONE, PUSH, CLONE, VIEW;
|
| | |
|
| | | public static AccessRestrictionType fromString(String name) {
|
| | | for (AccessRestrictionType type : values()) {
|
| | | if (type.toString().equalsIgnoreCase(name)) {
|
| | | return type;
|
| | | }
|
| | | }
|
| | | return NONE;
|
| | | }
|
| | | |
| | | public boolean atLeast(AccessRestrictionType type) {
|
| | | return this.ordinal() >= type.ordinal();
|
| | | }
|
| | |
|
| | | public String toString() {
|
| | | switch (this) {
|
| | | case NONE:
|
| | | return "none";
|
| | | case PUSH:
|
| | | return "push";
|
| | | case CLONE:
|
| | | return "clone";
|
| | | case VIEW:
|
| | | return "view";
|
| | | }
|
| | | return "none";
|
| | | }
|
| | | }
|
| | |
|
| | | public static String getGitBlitVersion() {
|
| | | return NAME + " v" + VERSION;
|
| | | }
|
| | |
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.wicket.User;
|
| | | import com.gitblit.wicket.models.RepositoryModel;
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | public class GitBlit implements ServletContextListener {
|
| | |
|
| | |
| | | userCookie.setPath("/");
|
| | | response.addCookie(userCookie);
|
| | | }
|
| | | |
| | |
|
| | | public User getUser(String username) {
|
| | | User user = loginService.getUserModel(username);
|
| | | return user;
|
| | | }
|
| | |
|
| | | public void editUserModel(User user, boolean isCreate) throws GitBlitException {
|
| | | if (!loginService.updateUserModel(user)) {
|
| | | throw new GitBlitException(isCreate ? "Failed to add user!" : "Failed to update user!");
|
| | | }
|
| | | }
|
| | |
|
| | | public List<String> getRepositoryList() {
|
| | | return JGitUtils.getRepositoryList(repositoriesFolder, exportAll, storedSettings.getBoolean(Keys.git.nestedRepositories, true));
|
| | | }
|
| | |
| | | }
|
| | | return r;
|
| | | }
|
| | | |
| | | public List<RepositoryModel> getRepositoryModels() {
|
| | |
|
| | | public List<RepositoryModel> getRepositoryModels(User user) {
|
| | | List<String> list = getRepositoryList();
|
| | | List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();
|
| | | for (String repo : list) {
|
| | | RepositoryModel model = getRepositoryModel(repo);
|
| | | repositories.add(model);
|
| | | RepositoryModel model = getRepositoryModel(user, repo);
|
| | | if (model != null) {
|
| | | repositories.add(model);
|
| | | }
|
| | | }
|
| | | return repositories;
|
| | | }
|
| | |
|
| | | public RepositoryModel getRepositoryModel(User user, String repositoryName) {
|
| | | RepositoryModel model = getRepositoryModel(repositoryName);
|
| | | if (model.accessRestriction.atLeast(AccessRestrictionType.VIEW)) {
|
| | | if (user != null && user.canView(model)) {
|
| | | return model;
|
| | | }
|
| | | return null;
|
| | | } else {
|
| | | return model;
|
| | | }
|
| | | }
|
| | |
|
| | | public RepositoryModel getRepositoryModel(String repositoryName) {
|
| | | Repository r = getRepository(repositoryName);
|
| | | RepositoryModel model = new RepositoryModel();
|
| | |
| | | if (config != null) {
|
| | | model.description = config.getString("gitblit", null, "description");
|
| | | model.owner = config.getString("gitblit", null, "owner");
|
| | | model.group = config.getString("gitblit", null, "group");
|
| | | model.useTickets = config.getBoolean("gitblit", "useTickets", false);
|
| | | model.useDocs = config.getBoolean("gitblit", "useDocs", false);
|
| | | model.useRestrictedAccess = config.getBoolean("gitblit", "restrictedAccess", false);
|
| | | model.accessRestriction = AccessRestrictionType.fromString(config.getString("gitblit", null, "accessRestriction"));
|
| | | model.showRemoteBranches = config.getBoolean("gitblit", "showRemoteBranches", false);
|
| | | }
|
| | | r.close();
|
| | |
| | | if (new File(repositoriesFolder, repository.name).exists()) {
|
| | | throw new GitBlitException(MessageFormat.format("Can not create repository {0} because it already exists.", repository.name));
|
| | | }
|
| | | // create repository |
| | | // create repository
|
| | | logger.info("create repository " + repository.name);
|
| | | r = JGitUtils.createRepository(repositoriesFolder, repository.name, true);
|
| | | } else {
|
| | |
| | | config.setString("gitblit", null, "owner", repository.owner);
|
| | | config.setBoolean("gitblit", null, "useTickets", repository.useTickets);
|
| | | config.setBoolean("gitblit", null, "useDocs", repository.useDocs);
|
| | | config.setBoolean("gitblit", null, "restrictedAccess", repository.useRestrictedAccess);
|
| | | config.setString("gitblit", null, "accessRestriction", repository.accessRestriction.toString());
|
| | | config.setBoolean("gitblit", null, "showRemoteBranches", repository.showRemoteBranches);
|
| | | try {
|
| | | config.save();
|
| | |
| | | import org.eclipse.jetty.util.log.Logger;
|
| | | import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
| | | import org.eclipse.jetty.webapp.WebAppContext;
|
| | | import org.eclipse.jgit.http.server.GitServlet;
|
| | |
|
| | | import com.beust.jcommander.JCommander;
|
| | | import com.beust.jcommander.Parameter;
|
| | |
| | | // Git Servlet
|
| | | ServletHolder gitServlet = null;
|
| | | String gitServletPathSpec = "/git/*";
|
| | | if (fileSettings.getBoolean(Keys.git.allowPushPull, true)) {
|
| | | gitServlet = rootContext.addServlet(GitServlet.class, gitServletPathSpec);
|
| | | if (fileSettings.getBoolean(Keys.git.enableGitServlet, true)) {
|
| | | gitServlet = rootContext.addServlet(GitBlitServlet.class, gitServletPathSpec);
|
| | | gitServlet.setInitParameter("base-path", params.repositoriesFolder);
|
| | | gitServlet.setInitParameter("export-all", params.exportAll ? "1" : "0");
|
| | | gitServlet.setInitParameter("export-all", fileSettings.getBoolean(Keys.git.exportAll, true) ? "1" : "0");
|
| | | }
|
| | |
|
| | | // Login Service
|
| | | LoginService loginService = null;
|
| | | String realmUsers = params.realmFile;
|
| | | if (realmUsers != null && new File(realmUsers).exists()) {
|
| | | logger.info("Setting up login service from " + realmUsers);
|
| | | JettyLoginService jettyLoginService = new JettyLoginService(realmUsers);
|
| | | GitBlit.self().setLoginService(jettyLoginService);
|
| | | loginService = jettyLoginService;
|
| | | String realmUsers = params.realmFile; |
| | | if (!StringUtils.isEmpty(realmUsers)) { |
| | | File realmFile = new File(realmUsers);
|
| | | if (realmFile.exists()) { |
| | | logger.info("Setting up login service from " + realmUsers);
|
| | | JettyLoginService jettyLoginService = new JettyLoginService(realmFile);
|
| | | GitBlit.self().setLoginService(jettyLoginService);
|
| | | loginService = jettyLoginService;
|
| | | }
|
| | | }
|
| | |
|
| | | // Determine what handler to use
|
| | | Handler handler;
|
| | | if (gitServlet != null) {
|
| | | if (loginService != null && params.authenticatePushPull) {
|
| | | // Authenticate Pull/Push
|
| | | String[] roles = new String[] { Constants.PULL_ROLE, Constants.PUSH_ROLE };
|
| | | logger.info("Authentication required for git servlet pull/push access");
|
| | | if (loginService != null) {
|
| | | // Authenticate Clone/Push
|
| | | logger.info("Setting up authenticated git servlet clone/push access");
|
| | |
|
| | | Constraint constraint = new Constraint();
|
| | | constraint.setName("auth");
|
| | | constraint.setAuthenticate(true);
|
| | | constraint.setRoles(roles);
|
| | | constraint.setRoles(new String [] { "*" });
|
| | |
|
| | | ConstraintMapping mapping = new ConstraintMapping();
|
| | | mapping.setPathSpec(gitServletPathSpec);
|
| | | mapping.setConstraint(constraint);
|
| | |
|
| | | ConstraintSecurityHandler security = new ConstraintSecurityHandler();
|
| | | ConstraintSecurityHandler security = new ConstraintSecurityHandler(); |
| | | security.addConstraintMapping(mapping);
|
| | | for (String role : roles) {
|
| | | security.addRole(role);
|
| | | }
|
| | | security.setAuthenticator(new BasicAuthenticator());
|
| | | security.setLoginService(loginService);
|
| | | security.setStrict(false);
|
| | |
| | | handler = rootContext;
|
| | | }
|
| | | } else {
|
| | | logger.info("Git servlet pull/push disabled");
|
| | | logger.info("Git servlet clone/push disabled");
|
| | | handler = rootContext;
|
| | | }
|
| | |
|
| | |
| | | @Parameter(names = { "--stop" }, description = "Stop Server")
|
| | | public Boolean stop = false;
|
| | |
|
| | | @Parameter(names = { "--temp" }, description = "Server temp folder")
|
| | | @Parameter(names = { "--tempFolder" }, description = "Server temp folder")
|
| | | public String temp = fileSettings.getString(Keys.server.tempFolder, "temp");
|
| | |
|
| | | /*
|
| | | * GIT Servlet Parameters
|
| | | */
|
| | | @Parameter(names = { "--repos" }, description = "Git Repositories Folder")
|
| | | @Parameter(names = { "--repositoriesFolder" }, description = "Git Repositories Folder")
|
| | | public String repositoriesFolder = fileSettings.getString(Keys.git.repositoriesFolder, "repos");
|
| | |
|
| | | @Parameter(names = { "--exportAll" }, description = "Export All Found Repositories")
|
| | | public Boolean exportAll = fileSettings.getBoolean(Keys.git.exportAll, true);
|
| | |
|
| | | /*
|
| | | * Authentication Parameters
|
| | | */
|
| | | @Parameter(names = { "--authenticatePushPull" }, description = "Authenticate Git Push/Pull access")
|
| | | public Boolean authenticatePushPull = fileSettings.getBoolean(Keys.git.authenticate, true);
|
| | |
|
| | | @Parameter(names = { "--realm" }, description = "Users Realm Hash File")
|
| | | @Parameter(names = { "--realmFile" }, description = "Users Realm Hash File")
|
| | | public String realmFile = fileSettings.getString(Keys.server.realmFile, "users.properties");
|
| | |
|
| | | /*
|
| | | * JETTY Parameters
|
| | | */
|
| | | @Parameter(names = { "--nio" }, description = "Use NIO Connector else use Socket Connector.")
|
| | | @Parameter(names = { "--useNio" }, description = "Use NIO Connector else use Socket Connector.")
|
| | | public Boolean useNIO = fileSettings.getBoolean(Keys.server.useNio, true);
|
| | |
|
| | | @Parameter(names = "--port", description = "HTTP port for to serve. (port <= 0 will disable this connector)")
|
| | | @Parameter(names = "--httpPort", description = "HTTP port for to serve. (port <= 0 will disable this connector)")
|
| | | public Integer port = fileSettings.getInteger(Keys.server.httpPort, 80);
|
| | |
|
| | | @Parameter(names = "--securePort", description = "HTTPS port to serve. (port <= 0 will disable this connector)")
|
| | | @Parameter(names = "--httpsPort", description = "HTTPS port to serve. (port <= 0 will disable this connector)")
|
| | | public Integer securePort = fileSettings.getInteger(Keys.server.httpsPort, 443);
|
| | |
|
| | | @Parameter(names = "--storePassword", description = "Password for SSL (https) keystore.")
|
New file |
| | |
| | | package com.gitblit;
|
| | |
|
| | | import java.io.IOException;
|
| | | import java.text.MessageFormat;
|
| | |
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | | import javax.servlet.http.HttpServletResponse;
|
| | |
|
| | | import org.eclipse.jgit.http.server.GitServlet;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.wicket.models.RepositoryModel;
|
| | |
|
| | | public class GitBlitServlet extends GitServlet {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private final Logger logger = LoggerFactory.getLogger(GitBlitServlet.class);
|
| | |
|
| | | public GitBlitServlet() {
|
| | | super();
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void service(final HttpServletRequest req, final HttpServletResponse rsp) throws ServletException, IOException {
|
| | | // admins have full git access to all repositories
|
| | | if (req.isUserInRole(Constants.ADMIN_ROLE)) {
|
| | | // admins can do whatever
|
| | | super.service(req, rsp);
|
| | | return;
|
| | | }
|
| | |
|
| | | // try to intercept repository names for authenticated access
|
| | | String url = req.getRequestURI().substring(req.getServletPath().length());
|
| | | if (url.charAt(0) == '/' && url.length() > 1) {
|
| | | url = url.substring(1);
|
| | | }
|
| | | int forwardSlash = url.indexOf('/');
|
| | | if (forwardSlash > -1) {
|
| | | String repository = url.substring(0, forwardSlash);
|
| | | String function = url.substring(forwardSlash + 1);
|
| | | String query = req.getQueryString();
|
| | | RepositoryModel model = GitBlit.self().getRepositoryModel(repository);
|
| | | if (model != null) {
|
| | | if (model.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {
|
| | | boolean authorizedUser = req.isUserInRole(repository);
|
| | | if (function.startsWith("git-receive-pack") || (query.indexOf("service=git-receive-pack") > -1)) {
|
| | | // Push request
|
| | | boolean pushRestricted = model.accessRestriction.atLeast(AccessRestrictionType.PUSH);
|
| | | if (!pushRestricted || (pushRestricted && authorizedUser)) {
|
| | | // push-unrestricted or push-authorized
|
| | | super.service(req, rsp);
|
| | | return;
|
| | | } else {
|
| | | // user is unauthorized to push to this repository
|
| | | logger.warn(MessageFormat.format("user {0} is not authorized to push to {1} ", req.getUserPrincipal().getName(), repository));
|
| | | rsp.sendError(HttpServletResponse.SC_FORBIDDEN, MessageFormat.format("you are not authorized to push to {0} ", repository));
|
| | | return;
|
| | | }
|
| | | } else if (function.startsWith("git-upload-pack") || (query.indexOf("service=git-upload-pack") > -1)) {
|
| | | // Clone request
|
| | | boolean cloneRestricted = model.accessRestriction.atLeast(AccessRestrictionType.CLONE);
|
| | | if (!cloneRestricted || (cloneRestricted && authorizedUser)) {
|
| | | // clone-unrestricted or clone-authorized
|
| | | super.service(req, rsp);
|
| | | return;
|
| | | } else {
|
| | | // user is unauthorized to clone this repository
|
| | | logger.warn(MessageFormat.format("user {0} is not authorized to clone {1} ", req.getUserPrincipal().getName(), repository));
|
| | | rsp.sendError(HttpServletResponse.SC_FORBIDDEN, MessageFormat.format("you are not authorized to clone {0} ", repository));
|
| | | return;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // pass-through to git servlet
|
| | | super.service(req, rsp);
|
| | | }
|
| | | }
|
| | |
| | | package com.gitblit;
|
| | |
|
| | | import com.gitblit.wicket.User;
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | public interface ILoginService {
|
| | |
|
| | | User authenticate(String username, char[] password);
|
| | |
|
| | | User authenticate(char[] cookie);
|
| | | |
| | | User getUserModel(String username);
|
| | | |
| | | boolean updateUserModel(User model);
|
| | | |
| | | boolean deleteUserModel(User model);
|
| | | |
| | | }
|
| | |
| | | package com.gitblit;
|
| | |
|
| | | import org.eclipse.jetty.security.HashLoginService;
|
| | | import java.io.File;
|
| | | import java.io.FileReader;
|
| | | import java.io.FileWriter;
|
| | | import java.io.IOException;
|
| | | import java.security.Principal;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Map;
|
| | | import java.util.Properties;
|
| | |
|
| | | import javax.security.auth.Subject;
|
| | |
|
| | | import org.eclipse.jetty.http.security.Credential;
|
| | | import org.eclipse.jetty.security.IdentityService;
|
| | | import org.eclipse.jetty.security.MappedLoginService;
|
| | | import org.eclipse.jetty.server.UserIdentity;
|
| | | import org.eclipse.jetty.util.log.Log;
|
| | |
|
| | | import com.gitblit.wicket.User;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | public class JettyLoginService extends HashLoginService implements ILoginService {
|
| | | public class JettyLoginService extends MappedLoginService implements ILoginService {
|
| | |
|
| | | public JettyLoginService(String realmFile) {
|
| | | super(Constants.NAME, realmFile);
|
| | | private final File realmFile;
|
| | |
|
| | | public JettyLoginService(File realmFile) {
|
| | | super();
|
| | | setName(Constants.NAME);
|
| | | this.realmFile = realmFile;
|
| | | }
|
| | |
|
| | | @Override
|
| | |
| | | if (identity == null || identity.equals(UserIdentity.UNAUTHENTICATED_IDENTITY)) {
|
| | | return null;
|
| | | }
|
| | | User user = new User(username, password);
|
| | | User user = new User(username);
|
| | | user.setCookie(StringUtils.getSHA1((Constants.NAME + username + new String(password))));
|
| | | user.canAdmin(identity.isUserInRole(Constants.ADMIN_ROLE, null));
|
| | | user.canClone(identity.isUserInRole(Constants.PULL_ROLE, null));
|
| | | user.canPush(identity.isUserInRole(Constants.PUSH_ROLE, null));
|
| | |
|
| | | // Add repositories
|
| | | for (Principal principal : identity.getSubject().getPrincipals()) {
|
| | | if (principal instanceof RolePrincipal) {
|
| | | RolePrincipal role = (RolePrincipal) principal;
|
| | | if (role.getName().charAt(0) != '#') {
|
| | | user.addRepository(role.getName().substring(1));
|
| | | }
|
| | | }
|
| | | }
|
| | | return user;
|
| | | }
|
| | |
|
| | |
| | | // TODO cookie login
|
| | | return null;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public User getUserModel(String username) {
|
| | | User model = new User(username);
|
| | | UserIdentity identity = _users.get(username);
|
| | | Subject subject = identity.getSubject();
|
| | | for (Principal principal : subject.getPrincipals()) {
|
| | | if (principal instanceof RolePrincipal) {
|
| | | RolePrincipal role = (RolePrincipal) principal;
|
| | | String name = role.getName();
|
| | | switch (name.charAt(0)) {
|
| | | case '#':
|
| | | // Permissions
|
| | | if (name.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
|
| | | model.canAdmin(true);
|
| | | }
|
| | | break;
|
| | | default:
|
| | | model.addRepository(name.substring(1));
|
| | | }
|
| | | }
|
| | | }
|
| | | return model;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean updateUserModel(User model) {
|
| | | try {
|
| | | Properties properties = new Properties();
|
| | | FileReader reader = new FileReader(realmFile);
|
| | | properties.load(reader);
|
| | | reader.close();
|
| | |
|
| | | ArrayList<String> roles = new ArrayList<String>();
|
| | |
|
| | | // Repositories
|
| | | roles.addAll(model.getRepositories());
|
| | |
|
| | | // Permissions
|
| | | if (model.canAdmin()) {
|
| | | roles.add(Constants.ADMIN_ROLE);
|
| | | }
|
| | |
|
| | | StringBuilder sb = new StringBuilder();
|
| | | sb.append(model.getPassword());
|
| | | sb.append(',');
|
| | | for (String role : roles) {
|
| | | sb.append(role);
|
| | | sb.append(',');
|
| | | }
|
| | | // trim trailing comma
|
| | | sb.setLength(sb.length() - 1);
|
| | |
|
| | | // Update realm file
|
| | | File realmFileCopy = new File(realmFile.getAbsolutePath() + ".tmp");
|
| | | FileWriter writer = new FileWriter(realmFileCopy);
|
| | | properties.put(model.getUsername(), sb.toString());
|
| | | properties.store(writer, null);
|
| | | writer.close();
|
| | | realmFile.delete();
|
| | | realmFileCopy.renameTo(realmFile);
|
| | |
|
| | | // Update login service
|
| | | putUser(model.getUsername(), Credential.getCredential(model.getPassword()), roles.toArray(new String[0]));
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | t.printStackTrace();
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean deleteUserModel(User model) {
|
| | | try {
|
| | | // Read realm file
|
| | | Properties properties = new Properties();
|
| | | FileReader reader = new FileReader(realmFile);
|
| | | properties.load(reader);
|
| | | reader.close();
|
| | | properties.remove(model.getUsername());
|
| | |
|
| | | // Update realm file
|
| | | File realmFileCopy = new File(realmFile.getAbsolutePath() + ".tmp");
|
| | | FileWriter writer = new FileWriter(realmFileCopy);
|
| | | properties.store(writer, null);
|
| | | writer.close();
|
| | | realmFile.delete();
|
| | | realmFileCopy.renameTo(realmFile);
|
| | |
|
| | | // Drop user from map
|
| | | _users.remove(model.getUsername());
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | t.printStackTrace();
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | | /* ------------------------------------------------------------ */
|
| | | @Override
|
| | | public void loadUsers() throws IOException {
|
| | | if (realmFile == null)
|
| | | return;
|
| | |
|
| | | if (Log.isDebugEnabled())
|
| | | Log.debug("Load " + this + " from " + realmFile);
|
| | | Properties properties = new Properties();
|
| | | FileReader reader = new FileReader(realmFile);
|
| | | properties.load(reader);
|
| | | reader.close();
|
| | |
|
| | | // Map Users
|
| | | for (Map.Entry<Object, Object> entry : properties.entrySet()) {
|
| | | String username = ((String) entry.getKey()).trim();
|
| | | String credentials = ((String) entry.getValue()).trim();
|
| | | String roles = null;
|
| | | int c = credentials.indexOf(',');
|
| | | if (c > 0) {
|
| | | roles = credentials.substring(c + 1).trim();
|
| | | credentials = credentials.substring(0, c).trim();
|
| | | }
|
| | |
|
| | | if (username != null && username.length() > 0 && credentials != null && credentials.length() > 0) {
|
| | | String[] roleArray = IdentityService.NO_ROLES;
|
| | | if (roles != null && roles.length() > 0) {
|
| | | roleArray = roles.split(",");
|
| | | }
|
| | | putUser(username, Credential.getCredential(credentials), roleArray);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected UserIdentity loadUser(String username) {
|
| | | return null;
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.wicket.models.User;
|
| | | import com.gitblit.wicket.pages.RepositoriesPage;
|
| | |
|
| | | public class AuthorizationStrategy extends AbstractPageAuthorizationStrategy implements IUnauthorizedComponentInstantiationListener {
|
| | |
| | | gb.rename = rename
|
| | | gb.delete = delete
|
| | | gb.docs = docs
|
| | | gb.restrictedAccess = restricted access
|
| | | gb.accessRestriction = access restriction
|
| | | gb.name = name
|
| | | gb.group = group
|
| | | gb.description = description
|
| | | gb.enableTickets = enable tickets
|
| | | gb.enableDocs = enable docs
|
| | | gb.save = save
|
| | | gb.showRemoteBranches = show remote branches |
| | | gb.showRemoteBranches = show remote branches
|
| | | gb.editUsers = edit users
|
| | | gb.password = password
|
| | | gb.confirmPassword = confirm password
|
| | | gb.repositories = repositories
|
| | | gb.canAdmin can admin
|
| | | gb.notRestricted = open repository
|
| | | gb.cloneRestricted = clone-restricted repository
|
| | | gb.pushRestricted = push-restricted repository
|
| | | gb.viewRestricted = view-restricted repository |
| | |
| | | import org.apache.wicket.protocol.http.WebSession;
|
| | | import org.apache.wicket.protocol.http.request.WebClientInfo;
|
| | |
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | public final class GitBlitWebSession extends WebSession {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | public class LoginPage extends WebPage {
|
| | |
|
| | |
| | |
|
| | | protected RepositoryModel getRepositoryModel() {
|
| | | if (m == null) {
|
| | | m = GitBlit.self().getRepositoryModel(repositoryName);
|
| | | RepositoryModel model = GitBlit.self().getRepositoryModel(GitBlitWebSession.get().getUser(), repositoryName);
|
| | | if (model == null) {
|
| | | error("Unauthorized access for repository " + repositoryName);
|
| | | redirectToInterceptPage(new RepositoriesPage());
|
| | | return null; |
| | | }
|
| | | m = model;
|
| | | }
|
| | | return m;
|
| | | }
|
| | | |
| | |
|
| | | protected RevCommit getCommit() {
|
| | | RevCommit commit = JGitUtils.getCommit(r, objectId);
|
| | | if (commit == null) {
|
| | |
| | | public static int getPage(PageParameters params) {
|
| | | return params.getInt("page", 1); // index from 1
|
| | | }
|
| | | |
| | | public static String getUsername(PageParameters params) {
|
| | | return params.getString("user", "");
|
| | | }
|
| | |
|
| | | public static Label createDateLabel(String wicketId, Date date, TimeZone timeZone) {
|
| | | DateFormat df = new SimpleDateFormat(GitBlit.self().settings().getString(Keys.web.datestampShortFormat, "MM/dd/yy"));
|
| | |
| | | import java.io.Serializable;
|
| | | import java.util.Date;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | |
|
| | | public class RepositoryModel implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | | public String name;
|
| | | public String description;
|
| | | public String owner;
|
| | | public String group;
|
| | | public Date lastChange;
|
| | | public boolean hasCommits;
|
| | | public boolean showRemoteBranches;
|
| | | public boolean useTickets;
|
| | | public boolean useDocs;
|
| | | public boolean useRestrictedAccess;
|
| | | public AccessRestrictionType accessRestriction;
|
| | |
|
| | | public RepositoryModel() {
|
| | | |
| | |
|
| | | }
|
| | | |
| | |
|
| | | public RepositoryModel(String name, String description, String owner, Date lastchange) {
|
| | | this.name = name;
|
| | | this.description = description;
|
| | | this.owner = owner;
|
| | | this.lastChange = lastchange;
|
| | | }
|
| | | } |
| | | } |
New file |
| | |
| | | package com.gitblit.wicket.models;
|
| | |
|
| | | import java.io.Serializable;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | |
|
| | | public class User implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private String username;
|
| | | private String password;
|
| | | private String cookie;
|
| | | private boolean canAdmin = false;
|
| | | private List<String> repositories = new ArrayList<String>();
|
| | |
|
| | | public User(String username) {
|
| | | this.username = username;
|
| | | }
|
| | |
|
| | | public String getUsername() {
|
| | | return username;
|
| | | }
|
| | |
|
| | | public String getPassword() {
|
| | | return password;
|
| | | }
|
| | |
|
| | | public void setPassword(String password) {
|
| | | this.password = password;
|
| | | }
|
| | |
|
| | | public void canAdmin(boolean value) {
|
| | | canAdmin = value;
|
| | | }
|
| | |
|
| | | public boolean canAdmin() {
|
| | | return canAdmin;
|
| | | }
|
| | | |
| | | public boolean canClone(RepositoryModel repository) {
|
| | | return canAccess(repository, AccessRestrictionType.CLONE);
|
| | | }
|
| | |
|
| | | public boolean canPush(RepositoryModel repository) {
|
| | | return canAccess(repository, AccessRestrictionType.PUSH);
|
| | | }
|
| | | |
| | | public boolean canView(RepositoryModel repository) {
|
| | | return canAccess(repository, AccessRestrictionType.VIEW);
|
| | | }
|
| | | |
| | | private boolean canAccess(RepositoryModel repository, AccessRestrictionType minimum) {
|
| | | if (repository.accessRestriction.atLeast(minimum)) {
|
| | | // repository is restricted, must check roles
|
| | | return canAdmin || repositories.contains(repository.name);
|
| | | } else {
|
| | | // repository is not restricted
|
| | | return true;
|
| | | }
|
| | | }
|
| | |
|
| | | public void setCookie(String cookie) {
|
| | | this.cookie = cookie;
|
| | | }
|
| | |
|
| | | public String getCookie() {
|
| | | return cookie;
|
| | | }
|
| | |
|
| | | public void setRepositories(List<String> repositories) {
|
| | | this.repositories.clear();
|
| | | this.repositories.addAll(repositories);
|
| | | }
|
| | |
|
| | | public void addRepository(String name) {
|
| | | repositories.add(name.toLowerCase());
|
| | | }
|
| | |
|
| | | public List<String> getRepositories() {
|
| | | return repositories;
|
| | | }
|
| | |
|
| | | public String toString() {
|
| | | return username;
|
| | | }
|
| | | }
|
| | |
| | | xml:lang="en"
|
| | | lang="en">
|
| | |
|
| | | <body>
|
| | | <wicket:extend>
|
| | | <body onload="document.getElementById('name').focus();">
|
| | | <!-- Push content down to preserve header image -->
|
| | | <div style="padding-top:20px"></div>
|
| | |
|
| | |
| | | <form wicket:id="editForm">
|
| | | <table class="plain">
|
| | | <tbody>
|
| | | <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input type="text" wicket:id="name" size="30" tabindex="1" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.description"></wicket:message></th><td class="edit"><input type="text" wicket:id="description" size="80" tabindex="2" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.owner"></wicket:message></th><td class="edit"><input type="text" wicket:id="owner" size="30" tabindex="3" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.group"></wicket:message></th><td class="edit"><input type="text" wicket:id="group" size="30" tabindex="4" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input type="text" wicket:id="name" id="name" size="40" tabindex="1" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.description"></wicket:message></th><td class="edit"><input type="text" wicket:id="description" size="40" tabindex="2" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.owner"></wicket:message></th><td class="edit"><input type="text" wicket:id="owner" size="40" tabindex="3" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select wicket:id="accessRestriction" tabindex="4" /></td></tr> |
| | | <tr><th><wicket:message key="gb.enableTickets"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useTickets" tabindex="5" /> <i>distributed Ticgit issues</i></td></tr>
|
| | | <tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useDocs" tabindex="6" /> <i>enumerates repository Markdown documentation</i></td></tr>
|
| | | <tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useDocs" tabindex="6" /> <i>enumerates Markdown documentation in repository</i></td></tr>
|
| | | <tr><th><wicket:message key="gb.showRemoteBranches"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="showRemoteBranches" tabindex="7" /> <i>show remote branches</i></td></tr>
|
| | | <tr><td class="edit" colspan="2"><input type="submit" value="Save" wicket:message="value:gb.save" tabindex="8" /></td></tr>
|
| | | <tr><th></th><td class="editButton"><input type="submit" value="Save" wicket:message="value:gb.save" tabindex="8" /></td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </form>
|
| | |
|
| | | </wicket:extend>
|
| | | </body>
|
| | | </wicket:extend>
|
| | | </html> |
| | |
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import java.util.Arrays;
|
| | | import java.util.Date;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.form.CheckBox;
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.model.CompoundPropertyModel;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.wicket.AdminPage;
|
| | |
| | | if (isCreate) {
|
| | | super.setupPage("", getString("gb.newRepository"));
|
| | | } else {
|
| | | super.setupPage("", getString("gb.edit"));
|
| | | super.setupPage("", getString("gb.edit") + " " + repositoryModel.name);
|
| | | }
|
| | | CompoundPropertyModel<RepositoryModel> model = new CompoundPropertyModel<RepositoryModel>(repositoryModel);
|
| | | Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", model) {
|
| | |
| | | setResponsePage(RepositoriesPage.class);
|
| | | }
|
| | | };
|
| | | |
| | |
|
| | | // field names reflective match RepositoryModel fields
|
| | | form.add(new TextField<String>("name").setEnabled(isCreate));
|
| | | form.add(new TextField<String>("description"));
|
| | | form.add(new TextField<String>("owner"));
|
| | | form.add(new TextField<String>("group"));
|
| | | form.add(new DropDownChoice<AccessRestrictionType>("accessRestriction", Arrays.asList(AccessRestrictionType.values())));
|
| | | form.add(new CheckBox("useTickets"));
|
| | | form.add(new CheckBox("useDocs"));
|
| | | form.add(new CheckBox("showRemoteBranches"));
|
New file |
| | |
| | | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
| | | <html xmlns="http://www.w3.org/1999/xhtml" |
| | | xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" |
| | | xml:lang="en" |
| | | lang="en"> |
| | |
|
| | | <wicket:extend>
|
| | | <body onload="document.getElementById('username').focus();">
|
| | | <!-- Push content down to preserve header image -->
|
| | | <div style="padding-top:20px"></div>
|
| | |
|
| | | <div style="text-align:center;" wicket:id="feedback">[Feedback Panel]</div> |
| | |
|
| | | <!-- Repository Table -->
|
| | | <form wicket:id="editForm">
|
| | | <table class="plain">
|
| | | <tbody>
|
| | | <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input type="text" wicket:id="username" id="username" size="30" tabindex="1" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.password"></wicket:message></th><td class="edit"><input type="password" wicket:id="password" size="30" tabindex="2" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.confirmPassword"></wicket:message></th><td class="edit"><input type="password" wicket:id="confirmPassword" size="30" tabindex="3" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.canAdmin"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="canAdmin" tabindex="6" /> <i>can administer Git:Blit server</i></td></tr> |
| | | <tr><th style="vertical-align: top;"><wicket:message key="gb.repositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr>
|
| | | <tr><th></th><td class="editButton"><input type="submit" value="Save" wicket:message="value:gb.save" tabindex="7" /></td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </form> |
| | | </body>
|
| | | </wicket:extend>
|
| | | </html> |
New file |
| | |
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import java.util.ArrayList;
|
| | | import java.util.Iterator;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.extensions.markup.html.form.palette.Palette;
|
| | | import org.apache.wicket.markup.html.form.CheckBox;
|
| | | import org.apache.wicket.markup.html.form.ChoiceRenderer;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.html.form.PasswordTextField;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.model.CompoundPropertyModel;
|
| | | import org.apache.wicket.model.Model;
|
| | | import org.apache.wicket.model.util.CollectionModel;
|
| | | import org.apache.wicket.model.util.ListModel;
|
| | | import org.eclipse.jetty.http.security.Credential.MD5;
|
| | |
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.wicket.AdminPage;
|
| | | import com.gitblit.wicket.BasePage;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | @AdminPage
|
| | | public class EditUserPage extends BasePage {
|
| | |
|
| | | private final boolean isCreate;
|
| | |
|
| | | public EditUserPage() {
|
| | | // create constructor
|
| | | super();
|
| | | isCreate = true;
|
| | | setupPage(new User(""));
|
| | | }
|
| | |
|
| | | public EditUserPage(PageParameters params) {
|
| | | // edit constructor
|
| | | super(params);
|
| | | isCreate = false;
|
| | | String name = WicketUtils.getUsername(params);
|
| | | User model = GitBlit.self().getUser(name);
|
| | | setupPage(model);
|
| | | }
|
| | |
|
| | | protected void setupPage(final User userModel) {
|
| | | if (isCreate) {
|
| | | super.setupPage("", getString("gb.newUser"));
|
| | | } else {
|
| | | super.setupPage("", getString("gb.edit"));
|
| | | }
|
| | | final Model<String> confirmPassword = new Model<String>();
|
| | | CompoundPropertyModel<User> model = new CompoundPropertyModel<User>(userModel);
|
| | |
|
| | | List<String> repos = GitBlit.self().getRepositoryList();
|
| | | repos.add(0, "*"); // all repositories wildcard
|
| | | final Palette<String> repositories = new Palette<String>("repositories", new ListModel<String>(userModel.getRepositories()), new CollectionModel<String>(repos), new ChoiceRenderer<String>("", ""), 10, false); |
| | | Form<User> form = new Form<User>("editForm", model) {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onSubmit() {
|
| | | if (!userModel.getPassword().equals(confirmPassword.getObject())) {
|
| | | error("Passwords do not match!");
|
| | | return;
|
| | | }
|
| | | userModel.setPassword(MD5.digest(userModel.getPassword()));
|
| | | |
| | | Iterator<String> selectedRepositories = repositories.getSelectedChoices();
|
| | | List<String> repos = new ArrayList<String>();
|
| | | while (selectedRepositories.hasNext()) {
|
| | | repos.add(selectedRepositories.next());
|
| | | }
|
| | | userModel.setRepositories(repos);
|
| | | try {
|
| | | GitBlit.self().editUserModel(userModel, isCreate);
|
| | | } catch (GitBlitException e) {
|
| | | error(e.getMessage());
|
| | | return;
|
| | | }
|
| | | setRedirect(true);
|
| | | setResponsePage(EditUserPage.class);
|
| | | }
|
| | | };
|
| | |
|
| | | // field names reflective match UserModel fields
|
| | | form.add(new TextField<String>("username").setEnabled(isCreate));
|
| | | form.add(new PasswordTextField("password"));
|
| | | form.add(new PasswordTextField("confirmPassword", confirmPassword));
|
| | | form.add(new CheckBox("canAdmin"));
|
| | | form.add(repositories);
|
| | | add(form);
|
| | | }
|
| | | }
|
| | |
| | | <wicket:fragment wicket:id="adminLinks">
|
| | | <!-- page nav links -->
|
| | | <div class="page_nav">
|
| | | <a wicket:id="newRepository"><wicket:message key="gb.newRepository"></wicket:message></a> | <a wicket:id="newUser"><wicket:message key="gb.newUser"></wicket:message></a>
|
| | | <a wicket:id="newRepository"><wicket:message key="gb.newRepository"></wicket:message></a> | <a wicket:id="newUser"><wicket:message key="gb.newUser"></wicket:message></a> | <a wicket:id="editUsers"><wicket:message key="gb.editUsers"></wicket:message></a>
|
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | |
| | | import com.gitblit.wicket.LinkPanel;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.models.RepositoryModel;
|
| | | import com.gitblit.wicket.models.User;
|
| | |
|
| | | public class RepositoriesPage extends BasePage {
|
| | |
|
| | |
| | |
|
| | | Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
|
| | | adminLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
|
| | | adminLinks.add(new BookmarkablePageLink<Void>("newUser", RepositoriesPage.class));
|
| | | adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class));
|
| | | adminLinks.add(new BookmarkablePageLink<Void>("editUsers", RepositoriesPage.class));
|
| | | add(adminLinks.setVisible(showAdmin));
|
| | |
|
| | | // display an error message cached from a redirect
|
| | |
| | | error(cachedMessage);
|
| | | System.out.println("displayed message");
|
| | | }
|
| | | |
| | |
|
| | | // Load the markdown welcome message
|
| | | String messageSource = GitBlit.self().settings().getString(Keys.web.repositoriesMessage, "gitblit");
|
| | | String message = "";
|
| | |
| | | }
|
| | | add(repositoriesMessage);
|
| | |
|
| | | List<RepositoryModel> rows = GitBlit.self().getRepositoryModels();
|
| | | User user = GitBlitWebSession.get().getUser();
|
| | | List<RepositoryModel> rows = GitBlit.self().getRepositoryModels(user);
|
| | | DataProvider dp = new DataProvider(rows);
|
| | | DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repository", dp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
| | | } else {
|
| | | // New repository
|
| | | item.add(new Label("repositoryName", entry.name + "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
|
| | | item.add(new Label("repositoryDescription", entry.description)); |
| | | item.add(new Label("repositoryDescription", entry.description));
|
| | | }
|
| | | |
| | |
|
| | | if (entry.useTickets) {
|
| | | item.add(WicketUtils.newImage("ticketsIcon", "bug_16x16.png", getString("gb.tickets")));
|
| | | } else {
|
| | | item.add(WicketUtils.newClearPixel("ticketsIcon"));
|
| | | item.add(WicketUtils.newBlankImage("ticketsIcon"));
|
| | | }
|
| | | |
| | |
|
| | | if (entry.useDocs) {
|
| | | item.add(WicketUtils.newImage("docsIcon", "book_16x16.png", getString("gb.docs")));
|
| | | } else {
|
| | | item.add(WicketUtils.newClearPixel("docsIcon"));
|
| | | item.add(WicketUtils.newBlankImage("docsIcon"));
|
| | | }
|
| | | |
| | | if (entry.useRestrictedAccess) {
|
| | | item.add(WicketUtils.newImage("restrictedAccessIcon", "lock_16x16.png", getString("gb.restrictedAccess")));
|
| | | } else {
|
| | | item.add(WicketUtils.newClearPixel("restrictedAccessIcon"));
|
| | |
|
| | | switch (entry.accessRestriction) {
|
| | | case NONE:
|
| | | item.add(WicketUtils.newBlankImage("restrictedAccessIcon"));
|
| | | break;
|
| | | case PUSH:
|
| | | item.add(WicketUtils.newImage("restrictedAccessIcon", "lock_go_16x16.png", getString("gb.pushRestricted")));
|
| | | break;
|
| | | case CLONE:
|
| | | item.add(WicketUtils.newImage("restrictedAccessIcon", "lock_pull_16x16.png", getString("gb.cloneRestricted")));
|
| | | break;
|
| | | case VIEW:
|
| | | item.add(WicketUtils.newImage("restrictedAccessIcon", "shield_16x16.png", getString("gb.viewRestricted")));
|
| | | break;
|
| | | default:
|
| | | item.add(WicketUtils.newBlankImage("restrictedAccessIcon"));
|
| | | }
|
| | | |
| | |
|
| | | item.add(new Label("repositoryOwner", entry.owner));
|
| | |
|
| | | String lastChange = TimeUtils.timeAgo(entry.lastChange);
|
| | |
| | | padding: 8px;
|
| | | }
|
| | |
|
| | | table.plain td.edit {
|
| | | table.plain td.edit { |
| | | padding: 3px;
|
| | | }
|
| | |
|
| | | table.plain td.editButton {
|
| | | padding:0px;
|
| | | padding-top: 10px;
|
| | | }
|
| | |
|
| | | table.plain td.edit input {
|
| | |
| | | color: black;
|
| | | font-weight: bold;
|
| | | }
|
| | |
|
| | | table.palette { border:0;}
|
| | | table.palette td.header { |
| | | font-weight: bold; |
| | | background-color: #D2C3AF !important;
|
| | | padding: 3px !important; |
| | | border: 1px solid #808080 !important;
|
| | | border-bottom: 0px solid !important;
|
| | | border-radius: 3px 3px 0 0;
|
| | | }
|
| | | table.palette td.pane {
|
| | | padding: 0px; |
| | | } |
| | |
|
| | | tr th a { padding-right: 15px; background-position: right; background-repeat:no-repeat; }
|
| | | tr th.wicket_orderDown a {background-image: url(arrow_down.png); }
|
| | |
| | |
|
| | | span .otherRef {
|
| | | background-color: #ffaaff;
|
| | | border-color: #ffccff #ff00ee #ff00ee #ffccff;
|
| | | border-color: #ff00ee;
|
| | | }
|
| | |
|
| | | span .remoteRef {
|
| | | background-color: #cAc2f5;
|
| | | border-color: #ccccff #0033cc #0033cc #ccccff;
|
| | | border-color: #6c6cbf;
|
| | | }
|
| | |
|
| | | span .tagRef {
|
| | | background-color: #ffffaa;
|
| | | border-color: #ffcc00 #ffcc00 #ffcc00 #ffcc00;
|
| | | border-color: #ffcc00;
|
| | | }
|
| | |
|
| | | span .headRef {
|
| | | background-color: #ccffcc;
|
| | | border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
|
| | | border-color: #00cc33;
|
| | | }
|
| | |
|
| | | .feedbackPanelERROR {
|
| | |
| | | test: test,pull
|
| | | admin: admin,pull,push,admin
|
| | | #Wed May 11 21:30:28 EDT 2011
|
| | | admin=admin,\#admin
|
| | | test=test
|