Added AccessRestrictionFilter and simplified authentication.
Replaced servlet container basic authentication with a custom servlet
filter which performs the same function. The advantage to this is
that the servlet container is now divorced from the webapp.
The login service (realm) also simplified a great deal and removes its
Jetty dependencies.
Additionally, the basic authorization pop-up will be displayed as
needed based on the repository's access restriction. This was
necessary for view-restricted repositories with the RSS feature. Its
also necessary for completely open repositories as before it would
prompt for credentials.
Improved feed syndication feature.
1 files renamed
1 files deleted
4 files added
20 files modified
| | |
| | | - Gitblit may have security holes. Patches welcome. :)
|
| | |
|
| | | ### Todo List
|
| | | - Custom BASIC authentication servlet or servlet filter
|
| | | - Code documentation
|
| | | - Unit testing
|
| | | - Update Build.java to JGit 1.0.0, when its released
|
| | | - WAR solution
|
| | |
|
| | | ### Idea List
|
| | | - Consider clone remote repository feature
|
| | | - Consider [Apache Shiro](http://shiro.apache.org) for authentication
|
| | | - Stronger Ticgit read-only integration
|
| | | - activity/timeline
|
| | | - query feature with paging support
|
New file |
| | |
| | | /*
|
| | | * Copyright 2011 gitblit.com.
|
| | | *
|
| | | * Licensed under the Apache License, Version 2.0 (the "License");
|
| | | * you may not use this file except in compliance with the License.
|
| | | * You may obtain a copy of the License at
|
| | | *
|
| | | * http://www.apache.org/licenses/LICENSE-2.0
|
| | | *
|
| | | * Unless required by applicable law or agreed to in writing, software
|
| | | * distributed under the License is distributed on an "AS IS" BASIS,
|
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| | | * See the License for the specific language governing permissions and
|
| | | * limitations under the License.
|
| | | */
|
| | | package com.gitblit;
|
| | |
|
| | | import java.io.IOException;
|
| | | import java.security.Principal;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.Enumeration;
|
| | | import java.util.HashMap;
|
| | | import java.util.Map;
|
| | |
|
| | | import javax.servlet.Filter;
|
| | | import javax.servlet.FilterChain;
|
| | | import javax.servlet.FilterConfig;
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.ServletRequest;
|
| | | import javax.servlet.ServletResponse;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | | import javax.servlet.http.HttpServletResponse;
|
| | | import javax.servlet.http.HttpSession;
|
| | |
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | | /**
|
| | | * |
| | | * http://en.wikipedia.org/wiki/Basic_access_authentication
|
| | | */
|
| | | public abstract class AccessRestrictionFilter implements Filter {
|
| | |
|
| | | private static final String BASIC = "Basic";
|
| | |
|
| | | private static final String CHALLENGE = BASIC + " realm=\"" + Constants.NAME + "\"";
|
| | |
|
| | | private static final String SESSION_SECURED = "com.gitblit.secured";
|
| | |
|
| | | protected transient Logger logger;
|
| | |
|
| | | public AccessRestrictionFilter() {
|
| | | logger = LoggerFactory.getLogger(getClass());
|
| | | }
|
| | |
|
| | | protected abstract String extractRepositoryName(String url);
|
| | |
|
| | | protected abstract String getUrlRequestType(String url);
|
| | |
|
| | | protected abstract boolean requiresAuthentication(RepositoryModel repository);
|
| | |
|
| | | protected abstract boolean canAccess(RepositoryModel repository, UserModel user,
|
| | | String restrictedUrl);
|
| | |
|
| | | @Override
|
| | | public void doFilter(final ServletRequest request, final ServletResponse response,
|
| | | final FilterChain chain) throws IOException, ServletException {
|
| | |
|
| | | HttpServletRequest httpRequest = (HttpServletRequest) request;
|
| | | HttpServletResponse httpResponse = (HttpServletResponse) response;
|
| | |
|
| | | // Wrap the HttpServletRequest with the AccessRestrictionRequest which
|
| | | // overrides the servlet container user principal methods.
|
| | | // JGit requires either:
|
| | | //
|
| | | // 1. servlet container authenticated user
|
| | | // 2. http.receivepack = true in each repository's config
|
| | | //
|
| | | // Gitblit must conditionally authenticate users per-repository so just
|
| | | // enabling http.receivepack is insufficient.
|
| | |
|
| | | AccessRestrictionRequest accessRequest = new AccessRestrictionRequest(httpRequest);
|
| | |
|
| | | String url = httpRequest.getRequestURI().substring(httpRequest.getServletPath().length());
|
| | | String params = httpRequest.getQueryString();
|
| | | if (url.length() > 0 && url.charAt(0) == '/') {
|
| | | url = url.substring(1);
|
| | | }
|
| | | String fullUrl = url + (StringUtils.isEmpty(params) ? "" : ("?" + params));
|
| | |
|
| | | String repository = extractRepositoryName(url);
|
| | |
|
| | | // Determine if the request URL is restricted
|
| | | String fullSuffix = fullUrl.substring(repository.length());
|
| | | String urlRequestType = getUrlRequestType(fullSuffix);
|
| | |
|
| | | // Load the repository model
|
| | | RepositoryModel model = GitBlit.self().getRepositoryModel(repository);
|
| | | if (model == null) {
|
| | | // repository not found. send 404.
|
| | | logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_NOT_FOUND + ")");
|
| | | httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
|
| | | return;
|
| | | }
|
| | |
|
| | | // BASIC authentication challenge and response processing
|
| | | if (!StringUtils.isEmpty(urlRequestType) && requiresAuthentication(model)) {
|
| | | // look for client authorization credentials in header
|
| | | final String authorization = httpRequest.getHeader("Authorization");
|
| | | if (authorization != null && authorization.startsWith(BASIC)) {
|
| | | // Authorization: Basic base64credentials
|
| | | String base64Credentials = authorization.substring(BASIC.length()).trim();
|
| | | String credentials = StringUtils.decodeBase64(base64Credentials);
|
| | | if (GitBlit.isDebugMode()) {
|
| | | logger.info(MessageFormat.format("AUTH: {0} ({1})", authorization, credentials));
|
| | | }
|
| | | // credentials = username:password
|
| | | final String[] values = credentials.split(":");
|
| | |
|
| | | if (values.length == 2) {
|
| | | String username = values[0];
|
| | | char[] password = values[1].toCharArray();
|
| | | UserModel user = GitBlit.self().authenticate(username, password);
|
| | | if (user != null) {
|
| | | accessRequest.setUser(user);
|
| | | if (user.canAdmin || canAccess(model, user, urlRequestType)) {
|
| | | // authenticated request permitted.
|
| | | // pass processing to the restricted servlet.
|
| | | newSession(accessRequest, httpResponse);
|
| | | logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_CONTINUE + ") authenticated");
|
| | | chain.doFilter(accessRequest, httpResponse);
|
| | | return;
|
| | | }
|
| | | // valid user, but not for requested access. send 403.
|
| | | if (GitBlit.isDebugMode()) {
|
| | | logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_FORBIDDEN
|
| | | + ")");
|
| | | logger.info(MessageFormat.format("AUTH: {0} forbidden to access {1}",
|
| | | user.username, url));
|
| | | }
|
| | | httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
|
| | | return;
|
| | | }
|
| | | }
|
| | | if (GitBlit.isDebugMode()) {
|
| | | logger.info(MessageFormat
|
| | | .format("AUTH: invalid credentials ({0})", credentials));
|
| | | }
|
| | | }
|
| | |
|
| | | // challenge client to provide credentials. send 401.
|
| | | if (GitBlit.isDebugMode()) {
|
| | | logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_UNAUTHORIZED + ")");
|
| | | logger.info("AUTH: Challenge " + CHALLENGE);
|
| | | }
|
| | | httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
|
| | | httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
| | | return;
|
| | | }
|
| | |
|
| | | if (GitBlit.isDebugMode()) {
|
| | | logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_CONTINUE + ") unauthenticated");
|
| | | }
|
| | | // unauthenticated request permitted.
|
| | | // pass processing to the restricted servlet.
|
| | | chain.doFilter(accessRequest, httpResponse);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Taken from Jetty's LoginAuthenticator.renewSessionOnAuthentication()
|
| | | */
|
| | | protected void newSession(HttpServletRequest request, HttpServletResponse response) {
|
| | | HttpSession oldSession = request.getSession(false);
|
| | | if (oldSession != null && oldSession.getAttribute(SESSION_SECURED) == null) {
|
| | | synchronized (this) {
|
| | | Map<String, Object> attributes = new HashMap<String, Object>();
|
| | | Enumeration<String> e = oldSession.getAttributeNames();
|
| | | while (e.hasMoreElements()) {
|
| | | String name = e.nextElement();
|
| | | attributes.put(name, oldSession.getAttribute(name));
|
| | | oldSession.removeAttribute(name);
|
| | | }
|
| | | oldSession.invalidate();
|
| | |
|
| | | HttpSession newSession = request.getSession(true);
|
| | | newSession.setAttribute(SESSION_SECURED, Boolean.TRUE);
|
| | | for (Map.Entry<String, Object> entry : attributes.entrySet()) {
|
| | | newSession.setAttribute(entry.getKey(), entry.getValue());
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void init(final FilterConfig config) throws ServletException {
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void destroy() {
|
| | | }
|
| | | |
| | | /**
|
| | | * Wraps a standard HttpServletRequest and overrides user principal methods.
|
| | | */
|
| | | public static class AccessRestrictionRequest extends ServletRequestWrapper {
|
| | |
|
| | | private UserModel user;
|
| | | |
| | | public AccessRestrictionRequest(HttpServletRequest req) {
|
| | | super(req);
|
| | | user = new UserModel("anonymous");
|
| | | }
|
| | | |
| | | void setUser(UserModel user) {
|
| | | this.user = user;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getRemoteUser() {
|
| | | return user.username;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isUserInRole(String role) {
|
| | | if (role.equals(Constants.ADMIN_ROLE)) {
|
| | | return user.canAdmin;
|
| | | }
|
| | | return user.canAccessRepository(role);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Principal getUserPrincipal() {
|
| | | return user;
|
| | | }
|
| | | }
|
| | | } |
| | |
| | | public static final String ZIP_SERVLET_PATH = "/zip/";
|
| | |
|
| | | public static final String SYNDICATION_SERVLET_PATH = "/feed/";
|
| | | |
| | | public static final String RESOURCE_PATH = "/com/gitblit/wicket/resources/";
|
| | |
|
| | | public static final String BORDER = "***********************************************************";
|
| | |
|
| | |
| | | }
|
| | |
|
| | | public static String asLink(String baseURL, String repository, String objectId, String path) {
|
| | | if (baseURL.charAt(baseURL.length() - 1) == '/') {
|
| | | if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
|
| | | baseURL = baseURL.substring(0, baseURL.length() - 1);
|
| | | }
|
| | | return baseURL + Constants.ZIP_SERVLET_PATH + "?r=" + repository
|
File was renamed from src/com/gitblit/JettyLoginService.java |
| | |
| | | package com.gitblit;
|
| | |
|
| | | import java.io.File;
|
| | | import java.io.FileReader;
|
| | | import java.io.FileWriter;
|
| | | import java.io.IOException;
|
| | | import java.security.Principal;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.HashSet;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Properties;
|
| | | import java.util.Set;
|
| | |
|
| | | 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 org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | | public class JettyLoginService extends MappedLoginService implements ILoginService {
|
| | | public class FileLoginService extends FileSettings implements ILoginService {
|
| | |
|
| | | private final Logger logger = LoggerFactory.getLogger(JettyLoginService.class);
|
| | | private final Logger logger = LoggerFactory.getLogger(FileLoginService.class);
|
| | |
|
| | | private final File realmFile;
|
| | |
|
| | | public JettyLoginService(File realmFile) {
|
| | | super();
|
| | | setName(Constants.NAME);
|
| | | this.realmFile = realmFile;
|
| | | public FileLoginService(File realmFile) {
|
| | | super(realmFile.getAbsolutePath());
|
| | | }
|
| | |
|
| | | @Override
|
| | | public UserModel authenticate(String username, char[] password) {
|
| | | UserIdentity identity = login(username, new String(password));
|
| | | if (identity == null || identity.equals(UserIdentity.UNAUTHENTICATED_IDENTITY)) {
|
| | | Properties allUsers = read();
|
| | | String userInfo = allUsers.getProperty(username);
|
| | | if (StringUtils.isEmpty(userInfo)) {
|
| | | return null;
|
| | | }
|
| | | UserModel user = new UserModel(username);
|
| | | user.canAdmin = identity.isUserInRole(Constants.ADMIN_ROLE, null);
|
| | |
|
| | | // Add repositories
|
| | | for (Principal principal : identity.getSubject().getPrincipals()) {
|
| | | if (principal instanceof RolePrincipal) {
|
| | | RolePrincipal role = (RolePrincipal) principal;
|
| | | String roleName = role.getName();
|
| | | if (roleName.charAt(0) != '#') {
|
| | | user.addRepository(roleName);
|
| | | }
|
| | | UserModel returnedUser = null;
|
| | | UserModel user = getUserModel(username);
|
| | | if (user.password.startsWith(StringUtils.MD5_TYPE)) {
|
| | | String md5 = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(password));
|
| | | if (user.password.equalsIgnoreCase(md5)) {
|
| | | returnedUser = user;
|
| | | }
|
| | | }
|
| | | return user;
|
| | | if (user.password.equals(new String(password))) {
|
| | | returnedUser = user;
|
| | | }
|
| | | return returnedUser;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public UserModel getUserModel(String username) {
|
| | | UserIdentity identity = _users.get(username);
|
| | | if (identity == null) {
|
| | | Properties allUsers = read();
|
| | | String userInfo = allUsers.getProperty(username);
|
| | | if (userInfo == null) {
|
| | | return null;
|
| | | }
|
| | | UserModel model = new UserModel(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);
|
| | | String[] userValues = userInfo.split(",");
|
| | | model.password = userValues[0];
|
| | | for (int i = 1; i < userValues.length; i++) {
|
| | | String role = userValues[i];
|
| | | switch (role.charAt(0)) {
|
| | | case '#':
|
| | | // Permissions
|
| | | if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
|
| | | model.canAdmin = true;
|
| | | }
|
| | | break;
|
| | | default:
|
| | | model.addRepository(role);
|
| | | }
|
| | | }
|
| | | // Retrieve the password from the realm file.
|
| | | // Stupid, I know, but the password is buried within protected inner
|
| | | // classes in private variables. Too much work to reflectively retrieve.
|
| | | try {
|
| | | Properties allUsers = readRealmFile();
|
| | | String value = allUsers.getProperty(username);
|
| | | String password = value.split(",")[0];
|
| | | model.password = password;
|
| | | } catch (Throwable t) {
|
| | | logger.error(MessageFormat.format("Failed to read password for user {0}!", username), t);
|
| | | }
|
| | | return model;
|
| | | }
|
| | |
| | | @Override
|
| | | public boolean updateUserModel(String username, UserModel model) {
|
| | | try {
|
| | | Properties allUsers = readRealmFile();
|
| | | Properties allUsers = read();
|
| | | ArrayList<String> roles = new ArrayList<String>(model.repositories);
|
| | |
|
| | | // Permissions
|
| | |
| | | allUsers.remove(username);
|
| | | allUsers.put(model.username, sb.toString());
|
| | |
|
| | | writeRealmFile(allUsers);
|
| | |
|
| | | // Update login service
|
| | | removeUser(username);
|
| | | putUser(model.username, Credential.getCredential(model.password),
|
| | | roles.toArray(new String[0]));
|
| | | write(allUsers);
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),
|
| | |
| | | public boolean deleteUser(String username) {
|
| | | try {
|
| | | // Read realm file
|
| | | Properties allUsers = readRealmFile();
|
| | | Properties allUsers = read();
|
| | | allUsers.remove(username);
|
| | | writeRealmFile(allUsers);
|
| | |
|
| | | // Drop user from map
|
| | | removeUser(username);
|
| | | write(allUsers);
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | logger.error(MessageFormat.format("Failed to delete user {0}!", username), t);
|
| | |
| | |
|
| | | @Override
|
| | | public List<String> getAllUsernames() {
|
| | | List<String> list = new ArrayList<String>();
|
| | | list.addAll(_users.keySet());
|
| | | Properties allUsers = read();
|
| | | List<String> list = new ArrayList<String>(allUsers.stringPropertyNames());
|
| | | return list;
|
| | | }
|
| | |
|
| | |
| | | public List<String> getUsernamesForRole(String role) {
|
| | | List<String> list = new ArrayList<String>();
|
| | | try {
|
| | | Properties allUsers = readRealmFile();
|
| | | Properties allUsers = read();
|
| | | for (String username : allUsers.stringPropertyNames()) {
|
| | | String value = allUsers.getProperty(username);
|
| | | String[] values = value.split(",");
|
| | |
| | | Set<String> needsRemoveRole = new HashSet<String>();
|
| | |
|
| | | // identify users which require add and remove role
|
| | | Properties allUsers = readRealmFile();
|
| | | Properties allUsers = read();
|
| | | for (String username : allUsers.stringPropertyNames()) {
|
| | | String value = allUsers.getProperty(username);
|
| | | String[] values = value.split(",");
|
| | |
| | | String userValues = allUsers.getProperty(user);
|
| | | userValues += "," + role;
|
| | | allUsers.put(user, userValues);
|
| | | String[] values = userValues.split(",");
|
| | | String password = values[0];
|
| | | String[] roles = new String[values.length - 1];
|
| | | System.arraycopy(values, 1, roles, 0, values.length - 1);
|
| | | putUser(user, Credential.getCredential(password), roles);
|
| | | }
|
| | |
|
| | | // remove role from user
|
| | |
| | |
|
| | | // update properties
|
| | | allUsers.put(user, sb.toString());
|
| | |
|
| | | // update memory
|
| | | putUser(user, Credential.getCredential(password),
|
| | | revisedRoles.toArray(new String[0]));
|
| | | }
|
| | |
|
| | | // persist changes
|
| | | writeRealmFile(allUsers);
|
| | | write(allUsers);
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | logger.error(MessageFormat.format("Failed to set usernames for role {0}!", role), t);
|
| | |
| | | @Override
|
| | | public boolean renameRole(String oldRole, String newRole) {
|
| | | try {
|
| | | Properties allUsers = readRealmFile();
|
| | | Properties allUsers = read();
|
| | | Set<String> needsRenameRole = new HashSet<String>();
|
| | |
|
| | | // identify users which require role rename
|
| | |
| | |
|
| | | // update properties
|
| | | allUsers.put(user, sb.toString());
|
| | |
|
| | | // update memory
|
| | | putUser(user, Credential.getCredential(password),
|
| | | revisedRoles.toArray(new String[0]));
|
| | | }
|
| | |
|
| | | // persist changes
|
| | | writeRealmFile(allUsers);
|
| | | write(allUsers);
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | logger.error(
|
| | |
| | | @Override
|
| | | public boolean deleteRole(String role) {
|
| | | try {
|
| | | Properties allUsers = readRealmFile();
|
| | | Properties allUsers = read();
|
| | | Set<String> needsDeleteRole = new HashSet<String>();
|
| | |
|
| | | // identify users which require role rename
|
| | |
| | |
|
| | | // update properties
|
| | | allUsers.put(user, sb.toString());
|
| | |
|
| | | // update memory
|
| | | putUser(user, Credential.getCredential(password),
|
| | | revisedRoles.toArray(new String[0]));
|
| | | }
|
| | |
|
| | | // persist changes
|
| | | writeRealmFile(allUsers);
|
| | | write(allUsers);
|
| | | return true;
|
| | | } catch (Throwable t) {
|
| | | logger.error(MessageFormat.format("Failed to delete role {0}!", role), t);
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | private Properties readRealmFile() throws IOException {
|
| | | Properties allUsers = new Properties();
|
| | | FileReader reader = new FileReader(realmFile);
|
| | | allUsers.load(reader);
|
| | | reader.close();
|
| | | return allUsers;
|
| | | }
|
| | |
|
| | | private void writeRealmFile(Properties properties) throws IOException {
|
| | | private void write(Properties properties) throws IOException {
|
| | | // Update realm file
|
| | | File realmFileCopy = new File(realmFile.getAbsolutePath() + ".tmp");
|
| | | File realmFileCopy = new File(propertiesFile.getAbsolutePath() + ".tmp");
|
| | | FileWriter writer = new FileWriter(realmFileCopy);
|
| | | properties
|
| | | .store(writer,
|
| | | "# Gitblit realm file format: username=password,\\#permission,repository1,repository2...");
|
| | | writer.close();
|
| | | if (realmFileCopy.exists() && realmFileCopy.length() > 0) {
|
| | | if (realmFile.delete()) {
|
| | | if (!realmFileCopy.renameTo(realmFile)) {
|
| | | if (propertiesFile.delete()) {
|
| | | if (!realmFileCopy.renameTo(propertiesFile)) {
|
| | | throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",
|
| | | realmFileCopy.getAbsolutePath(), realmFile.getAbsolutePath()));
|
| | | realmFileCopy.getAbsolutePath(), propertiesFile.getAbsolutePath()));
|
| | | }
|
| | | } else {
|
| | | throw new IOException(MessageFormat.format("Failed to delete (0)!",
|
| | | realmFile.getAbsolutePath()));
|
| | | propertiesFile.getAbsolutePath()));
|
| | | }
|
| | | } else {
|
| | | throw new IOException(MessageFormat.format("Failed to save {0}!",
|
| | | realmFileCopy.getAbsolutePath()));
|
| | | }
|
| | | }
|
| | |
|
| | | /* ------------------------------------------------------------ */
|
| | | @Override
|
| | | public void loadUsers() throws IOException {
|
| | | if (realmFile == null) {
|
| | | return;
|
| | | }
|
| | |
|
| | | if (Log.isDebugEnabled()) {
|
| | | Log.debug("Load " + this + " from " + realmFile);
|
| | | }
|
| | | Properties allUsers = readRealmFile();
|
| | |
|
| | | // Map Users
|
| | | for (Map.Entry<Object, Object> entry : allUsers.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;
|
| | | }
|
| | | }
|
| | |
| | | */
|
| | | public class FileSettings extends IStoredSettings {
|
| | |
|
| | | private final File propertiesFile;
|
| | | protected final File propertiesFile;
|
| | |
|
| | | private final Properties properties = new Properties();
|
| | |
|
| | |
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Collections;
|
| | | import java.util.HashMap;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Map.Entry;
|
| | |
|
| | | import javax.servlet.ServletContextEvent;
|
| | | import javax.servlet.ServletContextListener;
|
| | |
| | | return GITBLIT.storedSettings.getAllKeys(startingWith);
|
| | | }
|
| | |
|
| | | public boolean isDebugMode() {
|
| | | return storedSettings.getBoolean(Keys.web.debugMode, false);
|
| | | public static boolean isDebugMode() {
|
| | | return GITBLIT.storedSettings.getBoolean(Keys.web.debugMode, false);
|
| | | }
|
| | |
|
| | | public List<String> getOtherCloneUrls(String repositoryName) {
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | public String processCommitMessage(String repositoryName, String text) {
|
| | | String html = StringUtils.breakLinesForHtml(text);
|
| | | Map<String, String> map = new HashMap<String, String>();
|
| | | // global regex keys
|
| | | if (storedSettings.getBoolean(Keys.regex.global, false)) {
|
| | | for (String key : storedSettings.getAllKeys(Keys.regex.global)) {
|
| | | if (!key.equals(Keys.regex.global)) {
|
| | | String subKey = key.substring(key.lastIndexOf('.') + 1);
|
| | | map.put(subKey, storedSettings.getString(key, ""));
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // repository-specific regex keys
|
| | | List<String> keys = storedSettings.getAllKeys(Keys.regex._ROOT + "."
|
| | | + repositoryName.toLowerCase());
|
| | | for (String key : keys) {
|
| | | String subKey = key.substring(key.lastIndexOf('.') + 1);
|
| | | map.put(subKey, storedSettings.getString(key, ""));
|
| | | }
|
| | |
|
| | | for (Entry<String, String> entry : map.entrySet()) {
|
| | | String definition = entry.getValue().trim();
|
| | | String[] chunks = definition.split("!!!");
|
| | | if (chunks.length == 2) {
|
| | | html = html.replaceAll(chunks[0], chunks[1]);
|
| | | } else {
|
| | | logger.warn(entry.getKey()
|
| | | + " improperly formatted. Use !!! to separate match from replacement: "
|
| | | + definition);
|
| | | }
|
| | | }
|
| | | return html;
|
| | | }
|
| | |
|
| | | public void configureContext(IStoredSettings settings) {
|
| | | logger.info("Reading configuration from " + settings.toString());
|
| | | this.storedSettings = settings;
|
| | |
| | | @Override
|
| | | public void contextInitialized(ServletContextEvent contextEvent) {
|
| | | if (storedSettings == null) {
|
| | | // for running gitblit as a traditional webapp in a servlet container
|
| | | // for running gitblit as a traditional webapp in a servlet
|
| | | // container
|
| | | WebXmlSettings webxmlSettings = new WebXmlSettings(contextEvent.getServletContext());
|
| | | configureContext(webxmlSettings);
|
| | | }
|
| | |
| | | import org.apache.log4j.PatternLayout;
|
| | | import org.apache.wicket.protocol.http.ContextParamWebApplicationFactory;
|
| | | import org.apache.wicket.protocol.http.WicketFilter;
|
| | | import org.eclipse.jetty.http.security.Constraint;
|
| | | import org.eclipse.jetty.security.ConstraintMapping;
|
| | | import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
| | | import org.eclipse.jetty.security.LoginService;
|
| | | import org.eclipse.jetty.security.authentication.BasicAuthenticator;
|
| | | import org.eclipse.jetty.server.Connector;
|
| | | import org.eclipse.jetty.server.Handler;
|
| | | import org.eclipse.jetty.server.Server;
|
| | | import org.eclipse.jetty.server.bio.SocketConnector;
|
| | | import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
| | |
| | | import org.eclipse.jetty.servlet.ServletHolder;
|
| | | import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
| | | import org.eclipse.jetty.webapp.WebAppContext;
|
| | | import org.eclipse.jgit.http.server.GitServlet;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | |
| | | wicketFilter.setInitParameter(ContextParamWebApplicationFactory.APP_CLASS_PARAM,
|
| | | GitBlitWebApp.class.getName());
|
| | | wicketFilter.setInitParameter(WicketFilter.FILTER_MAPPING_PARAM, wicketPathSpec);
|
| | | wicketFilter.setInitParameter(WicketFilter.IGNORE_PATHS_PARAM, "git/");
|
| | | wicketFilter.setInitParameter(WicketFilter.IGNORE_PATHS_PARAM, "git/,feed/,zip/");
|
| | | rootContext.addFilter(wicketFilter, wicketPathSpec, FilterMapping.DEFAULT);
|
| | |
|
| | | // JGit Filter and Servlet
|
| | | if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
|
| | | String jgitPathSpec = Constants.GIT_SERVLET_PATH + "*";
|
| | | rootContext.addFilter(GitFilter.class, jgitPathSpec, FilterMapping.DEFAULT);
|
| | | ServletHolder jGitServlet = rootContext.addServlet(GitServlet.class, jgitPathSpec);
|
| | | jGitServlet.setInitParameter("base-path", params.repositoriesFolder);
|
| | | jGitServlet.setInitParameter("export-all",
|
| | | settings.getBoolean(Keys.git.exportAll, true) ? "1" : "0");
|
| | | }
|
| | |
|
| | | // Syndication Filter and Servlet
|
| | | String feedPathSpec = Constants.SYNDICATION_SERVLET_PATH + "*";
|
| | | rootContext.addFilter(SyndicationFilter.class, feedPathSpec, FilterMapping.DEFAULT);
|
| | | rootContext.addServlet(SyndicationServlet.class, feedPathSpec);
|
| | |
|
| | | // Zip Servlet
|
| | | rootContext.addServlet(DownloadZipServlet.class, Constants.ZIP_SERVLET_PATH + "*");
|
| | |
|
| | | // Syndication Servlet
|
| | | rootContext.addServlet(SyndicationServlet.class, Constants.SYNDICATION_SERVLET_PATH + "*");
|
| | |
|
| | | // Git Servlet
|
| | | ServletHolder gitServlet = null;
|
| | | String gitServletPathSpec = Constants.GIT_SERVLET_PATH + "*";
|
| | | if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
|
| | | gitServlet = rootContext.addServlet(GitBlitServlet.class, gitServletPathSpec);
|
| | | gitServlet.setInitParameter("base-path", params.repositoriesFolder);
|
| | | gitServlet.setInitParameter("export-all",
|
| | | settings.getBoolean(Keys.git.exportAll, true) ? "1" : "0");
|
| | | }
|
| | |
|
| | | // Login Service
|
| | | LoginService loginService = null;
|
| | | 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;
|
| | | if (StringUtils.isEmpty(realmUsers)) {
|
| | | logger.error(MessageFormat.format("PLEASE SPECIFY {0}!!", Keys.realm.realmFile));
|
| | | return;
|
| | | }
|
| | | File realmFile = new File(realmUsers);
|
| | | if (!realmFile.exists()) {
|
| | | try {
|
| | | realmFile.createNewFile();
|
| | | } catch (IOException x) {
|
| | | logger.error(MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmUsers),
|
| | | x);
|
| | | return;
|
| | | }
|
| | | }
|
| | |
|
| | | // Determine what handler to use
|
| | | Handler handler;
|
| | | if (gitServlet != null) {
|
| | | if (loginService != null) {
|
| | | // Authenticate Clone/Push
|
| | | logger.info("Setting up authenticated git servlet clone/push access");
|
| | |
|
| | | Constraint constraint = new Constraint();
|
| | | constraint.setAuthenticate(true);
|
| | | constraint.setRoles(new String[] { "*" });
|
| | |
|
| | | ConstraintMapping mapping = new ConstraintMapping();
|
| | | mapping.setPathSpec(gitServletPathSpec);
|
| | | mapping.setConstraint(constraint);
|
| | |
|
| | | ConstraintSecurityHandler security = new ConstraintSecurityHandler();
|
| | | security.addConstraintMapping(mapping);
|
| | | security.setAuthenticator(new BasicAuthenticator());
|
| | | security.setLoginService(loginService);
|
| | | security.setStrict(false);
|
| | |
|
| | | security.setHandler(rootContext);
|
| | |
|
| | | handler = security;
|
| | | } else {
|
| | | // Anonymous Pull/Push
|
| | | logger.info("Setting up anonymous git servlet pull/push access");
|
| | | handler = rootContext;
|
| | | }
|
| | | } else {
|
| | | logger.info("Git servlet clone/push disabled");
|
| | | handler = rootContext;
|
| | | }
|
| | | logger.info("Setting up login service from " + realmUsers);
|
| | | FileLoginService loginService = new FileLoginService(realmFile);
|
| | | GitBlit.self().setLoginService(loginService);
|
| | |
|
| | | logger.info("Git repositories folder "
|
| | | + new File(params.repositoriesFolder).getAbsolutePath());
|
| | |
|
| | | // Set the server's contexts
|
| | | server.setHandler(handler);
|
| | | server.setHandler(rootContext);
|
| | |
|
| | | // Setup the GitBlit context
|
| | | GitBlit gitblit = GitBlit.self();
|
New file |
| | |
| | | /*
|
| | | * Copyright 2011 gitblit.com.
|
| | | *
|
| | | * Licensed under the Apache License, Version 2.0 (the "License");
|
| | | * you may not use this file except in compliance with the License.
|
| | | * You may obtain a copy of the License at
|
| | | *
|
| | | * http://www.apache.org/licenses/LICENSE-2.0
|
| | | *
|
| | | * Unless required by applicable law or agreed to in writing, software
|
| | | * distributed under the License is distributed on an "AS IS" BASIS,
|
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| | | * See the License for the specific language governing permissions and
|
| | | * limitations under the License.
|
| | | */
|
| | | package com.gitblit;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | | public class GitFilter extends AccessRestrictionFilter {
|
| | |
|
| | | protected final String gitReceivePack = "/git-receive-pack";
|
| | |
|
| | | protected final String gitUploadPack = "/git-upload-pack";
|
| | |
|
| | | protected final String[] suffixes = { gitReceivePack, gitUploadPack, "/info/refs", "/HEAD",
|
| | | "/objects" };
|
| | |
|
| | | @Override
|
| | | protected String extractRepositoryName(String url) {
|
| | | String repository = url;
|
| | | for (String urlSuffix : suffixes) {
|
| | | if (repository.indexOf(urlSuffix) > -1) {
|
| | | repository = repository.substring(0, repository.indexOf(urlSuffix));
|
| | | }
|
| | | }
|
| | | return repository;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected String getUrlRequestType(String suffix) {
|
| | | if (!StringUtils.isEmpty(suffix)) {
|
| | | if (suffix.startsWith(gitReceivePack)) {
|
| | | return gitReceivePack;
|
| | | } else if (suffix.startsWith(gitUploadPack)) {
|
| | | return gitUploadPack;
|
| | | } else if (suffix.contains("?service=git-receive-pack")) {
|
| | | return gitReceivePack;
|
| | | } else if (suffix.contains("?service=git-upload-pack")) {
|
| | | return gitUploadPack;
|
| | | }
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean requiresAuthentication(RepositoryModel repository) {
|
| | | return repository.accessRestriction.atLeast(AccessRestrictionType.PUSH);
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean canAccess(RepositoryModel repository, UserModel user, String urlRequestType) {
|
| | | if (repository.isFrozen || repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {
|
| | | boolean authorizedUser = user.canAccessRepository(repository.name);
|
| | | if (urlRequestType.equals(gitReceivePack)) {
|
| | | // Push request
|
| | | if (!repository.isFrozen && authorizedUser) {
|
| | | // clone-restricted or push-authorized
|
| | | return true;
|
| | | } else {
|
| | | // user is unauthorized to push to this repository
|
| | | logger.warn(MessageFormat.format("user {0} is not authorized to push to {1}",
|
| | | user.username, repository));
|
| | | return false;
|
| | | }
|
| | | } else if (urlRequestType.equals(gitUploadPack)) {
|
| | | // Clone request
|
| | | boolean cloneRestricted = repository.accessRestriction
|
| | | .atLeast(AccessRestrictionType.CLONE);
|
| | | if (!cloneRestricted || (cloneRestricted && authorizedUser)) {
|
| | | // push-restricted or clone-authorized
|
| | | return true;
|
| | | } else {
|
| | | // user is unauthorized to clone this repository
|
| | | logger.warn(MessageFormat.format("user {0} is not authorized to clone {1}",
|
| | | user.username, repository));
|
| | | return false;
|
| | | }
|
| | | }
|
| | | }
|
| | | return true;
|
| | | }
|
| | | }
|
New file |
| | |
| | | /*
|
| | | * Copyright 2011 gitblit.com.
|
| | | *
|
| | | * Licensed under the Apache License, Version 2.0 (the "License");
|
| | | * you may not use this file except in compliance with the License.
|
| | | * You may obtain a copy of the License at
|
| | | *
|
| | | * http://www.apache.org/licenses/LICENSE-2.0
|
| | | *
|
| | | * Unless required by applicable law or agreed to in writing, software
|
| | | * distributed under the License is distributed on an "AS IS" BASIS,
|
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| | | * See the License for the specific language governing permissions and
|
| | | * limitations under the License.
|
| | | */
|
| | | package com.gitblit;
|
| | |
|
| | | import java.io.BufferedReader;
|
| | | import java.io.IOException;
|
| | | import java.io.UnsupportedEncodingException;
|
| | | import java.security.Principal;
|
| | | import java.util.Enumeration;
|
| | | import java.util.Locale;
|
| | | import java.util.Map;
|
| | |
|
| | | import javax.servlet.RequestDispatcher;
|
| | | import javax.servlet.ServletInputStream;
|
| | | import javax.servlet.http.Cookie;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | | import javax.servlet.http.HttpSession;
|
| | |
|
| | | public abstract class ServletRequestWrapper implements HttpServletRequest {
|
| | |
|
| | | protected final HttpServletRequest req;
|
| | |
|
| | | public ServletRequestWrapper(HttpServletRequest req) {
|
| | | this.req = req;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Object getAttribute(String name) {
|
| | | return req.getAttribute(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Enumeration getAttributeNames() {
|
| | | return req.getAttributeNames();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getCharacterEncoding() {
|
| | | return req.getCharacterEncoding();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
|
| | | req.setCharacterEncoding(env);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int getContentLength() {
|
| | | return req.getContentLength();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getContentType() {
|
| | | return req.getContentType();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public ServletInputStream getInputStream() throws IOException {
|
| | | return req.getInputStream();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getParameter(String name) {
|
| | | return req.getParameter(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Enumeration getParameterNames() {
|
| | | return req.getParameterNames();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String[] getParameterValues(String name) {
|
| | | return req.getParameterValues(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Map getParameterMap() {
|
| | | return req.getParameterMap();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getProtocol() {
|
| | | return req.getProtocol();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getScheme() {
|
| | | return req.getScheme();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getServerName() {
|
| | | return req.getServerName();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int getServerPort() {
|
| | | return req.getServerPort();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public BufferedReader getReader() throws IOException {
|
| | | return req.getReader();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getRemoteAddr() {
|
| | | return req.getRemoteAddr();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getRemoteHost() {
|
| | | return req.getRemoteHost();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void setAttribute(String name, Object o) {
|
| | | req.setAttribute(name, o);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void removeAttribute(String name) {
|
| | | req.removeAttribute(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Locale getLocale() {
|
| | | return req.getLocale();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Enumeration getLocales() {
|
| | | return req.getLocales();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isSecure() {
|
| | | return req.isSecure();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public RequestDispatcher getRequestDispatcher(String path) {
|
| | | return req.getRequestDispatcher(path);
|
| | | }
|
| | |
|
| | | @Override
|
| | | @Deprecated
|
| | | public String getRealPath(String path) {
|
| | | return req.getRealPath(path);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int getRemotePort() {
|
| | | return req.getRemotePort();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getLocalName() {
|
| | | return req.getLocalName();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getLocalAddr() {
|
| | | return req.getLocalAddr();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int getLocalPort() {
|
| | | return req.getLocalPort();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getAuthType() {
|
| | | return req.getAuthType();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Cookie[] getCookies() {
|
| | | return req.getCookies();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public long getDateHeader(String name) {
|
| | | return req.getDateHeader(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getHeader(String name) {
|
| | | return req.getHeader(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Enumeration getHeaders(String name) {
|
| | | return req.getHeaders(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Enumeration getHeaderNames() {
|
| | | return req.getHeaderNames();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int getIntHeader(String name) {
|
| | | return req.getIntHeader(name);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getMethod() {
|
| | | return req.getMethod();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getPathInfo() {
|
| | | return req.getPathInfo();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getPathTranslated() {
|
| | | return req.getPathTranslated();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getContextPath() {
|
| | | return req.getContextPath();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getQueryString() {
|
| | | return req.getQueryString();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getRemoteUser() {
|
| | | return req.getRemoteUser();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isUserInRole(String role) {
|
| | | return req.isUserInRole(role);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public Principal getUserPrincipal() {
|
| | | return req.getUserPrincipal();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getRequestedSessionId() {
|
| | | return req.getRequestedSessionId();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getRequestURI() {
|
| | | return req.getRequestURI();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public StringBuffer getRequestURL() {
|
| | | return req.getRequestURL();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getServletPath() {
|
| | | return req.getServletPath();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public HttpSession getSession(boolean create) {
|
| | | return req.getSession(create);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public HttpSession getSession() {
|
| | | return req.getSession();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isRequestedSessionIdValid() {
|
| | | return req.isRequestedSessionIdValid();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isRequestedSessionIdFromCookie() {
|
| | | return req.isRequestedSessionIdFromCookie();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isRequestedSessionIdFromURL() {
|
| | | return req.isRequestedSessionIdFromURL();
|
| | | }
|
| | |
|
| | | @Override
|
| | | @Deprecated
|
| | | public boolean isRequestedSessionIdFromUrl() {
|
| | | return req.isRequestedSessionIdFromUrl();
|
| | | }
|
| | | } |
New file |
| | |
| | | /*
|
| | | * Copyright 2011 gitblit.com.
|
| | | *
|
| | | * Licensed under the Apache License, Version 2.0 (the "License");
|
| | | * you may not use this file except in compliance with the License.
|
| | | * You may obtain a copy of the License at
|
| | | *
|
| | | * http://www.apache.org/licenses/LICENSE-2.0
|
| | | *
|
| | | * Unless required by applicable law or agreed to in writing, software
|
| | | * distributed under the License is distributed on an "AS IS" BASIS,
|
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| | | * See the License for the specific language governing permissions and
|
| | | * limitations under the License.
|
| | | */
|
| | | package com.gitblit;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | |
|
| | | public class SyndicationFilter extends AccessRestrictionFilter {
|
| | |
|
| | | @Override
|
| | | protected String extractRepositoryName(String url) {
|
| | | return url;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected String getUrlRequestType(String url) {
|
| | | return "RESTRICTED";
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean requiresAuthentication(RepositoryModel repository) {
|
| | | return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW);
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean canAccess(RepositoryModel repository, UserModel user, String restrictedURL) {
|
| | | return user.canAccessRepository(repository.name);
|
| | | }
|
| | |
|
| | | }
|
| | |
| | | */
|
| | | package com.gitblit;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.List;
|
| | |
|
| | | import javax.servlet.http.HttpServlet;
|
| | |
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.SyndicationUtils;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | public class SyndicationServlet extends HttpServlet {
|
| | |
|
| | |
| | | private transient Logger logger = LoggerFactory.getLogger(SyndicationServlet.class);
|
| | |
|
| | | public static String asLink(String baseURL, String repository, String objectId, int length) {
|
| | | if (baseURL.charAt(baseURL.length() - 1) == '/') {
|
| | | if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
|
| | | baseURL = baseURL.substring(0, baseURL.length() - 1);
|
| | | }
|
| | | return baseURL + Constants.SYNDICATION_SERVLET_PATH + "?r=" + repository
|
| | | + (objectId == null ? "" : ("&h=" + objectId)) + (length > 0 ? "&l=" + length : "");
|
| | | StringBuilder url = new StringBuilder();
|
| | | url.append(baseURL);
|
| | | url.append(Constants.SYNDICATION_SERVLET_PATH);
|
| | | url.append(repository);
|
| | | if (!StringUtils.isEmpty(objectId) || length > 0) {
|
| | | StringBuilder parameters = new StringBuilder("?");
|
| | | if (StringUtils.isEmpty(objectId)) {
|
| | | parameters.append("l=");
|
| | | parameters.append(length);
|
| | | } else {
|
| | | parameters.append("h=");
|
| | | parameters.append(objectId);
|
| | | if (length > 0) {
|
| | | parameters.append("&l=");
|
| | | parameters.append(length);
|
| | | }
|
| | | }
|
| | | url.append(parameters);
|
| | | }
|
| | | return url.toString();
|
| | | }
|
| | | |
| | | public static String getTitle(String repository, String objectId) {
|
| | | String id = objectId;
|
| | | if (!StringUtils.isEmpty(id)) {
|
| | | if (id.startsWith(org.eclipse.jgit.lib.Constants.R_HEADS)) {
|
| | | id = id.substring(org.eclipse.jgit.lib.Constants.R_HEADS.length());
|
| | | } else if (id.startsWith(org.eclipse.jgit.lib.Constants.R_REMOTES)) {
|
| | | id = id.substring(org.eclipse.jgit.lib.Constants.R_REMOTES.length());
|
| | | } else if (id.startsWith(org.eclipse.jgit.lib.Constants.R_TAGS)) {
|
| | | id = id.substring(org.eclipse.jgit.lib.Constants.R_TAGS.length());
|
| | | }
|
| | | }
|
| | | return MessageFormat.format("{0} ({1})", repository, id);
|
| | | }
|
| | |
|
| | | private void processRequest(javax.servlet.http.HttpServletRequest request,
|
| | | javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
|
| | | java.io.IOException {
|
| | | String hostUrl = request.getRequestURL().toString();
|
| | | String servlet = request.getServletPath();
|
| | | hostUrl = hostUrl.substring(0, hostUrl.indexOf(servlet));
|
| | | String repositoryName = request.getParameter("r");
|
| | |
|
| | | String hostURL = WicketUtils.getHostURL(request);
|
| | | String url = request.getRequestURI().substring(request.getServletPath().length());
|
| | | if (url.charAt(0) == '/' && url.length() > 1) {
|
| | | url = url.substring(1);
|
| | | }
|
| | | String repositoryName = url;
|
| | | String objectId = request.getParameter("h");
|
| | | String l = request.getParameter("l");
|
| | | int length = GitBlit.getInteger(Keys.web.syndicationEntries, 25);
|
| | |
| | | } catch (NumberFormatException x) {
|
| | | }
|
| | | }
|
| | | |
| | | // TODO confirm repository is accessible!!
|
| | |
|
| | | Repository repository = GitBlit.self().getRepository(repositoryName);
|
| | | RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
|
| | | List<RevCommit> commits = JGitUtils.getRevLog(repository, objectId, 0, length);
|
| | | try {
|
| | | SyndicationUtils.toRSS(hostUrl, model.name + " " + objectId, model.description, model.name, commits, response.getOutputStream());
|
| | | SyndicationUtils.toRSS(hostURL, getTitle(model.name, objectId), model.description,
|
| | | model.name, commits, response.getOutputStream());
|
| | | } catch (Exception e) {
|
| | | logger.error("An error occurred during feed generation", e);
|
| | | }
|
| | |
| | | package com.gitblit.models;
|
| | |
|
| | | import java.io.Serializable;
|
| | | import java.security.Principal;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | public class UserModel implements Serializable {
|
| | | public class UserModel implements Principal, Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | public String getName() { |
| | | return username;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String toString() {
|
| | | return username;
|
| | | }
|
| | |
| | | package com.gitblit.utils;
|
| | |
|
| | | import java.io.UnsupportedEncodingException;
|
| | | import java.nio.charset.Charset;
|
| | | import java.security.MessageDigest;
|
| | | import java.security.NoSuchAlgorithmException;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | | import java.util.regex.PatternSyntaxException;
|
| | |
|
| | | import org.eclipse.jetty.util.log.Log;
|
| | | import org.eclipse.jgit.util.Base64;
|
| | |
|
| | | public class StringUtils {
|
| | |
|
| | | public static final String MD5_TYPE = "MD5:";
|
| | |
|
| | | public static boolean isEmpty(String value) {
|
| | | return value == null || value.trim().length() == 0;
|
| | |
| | | retStr.append(" ");
|
| | | } else if (changeSpace && inStr.charAt(i) == '\t') {
|
| | | retStr.append(" ");
|
| | | } else {
|
| | | retStr.append(inStr.charAt(i));
|
| | | }
|
| | | i++;
|
| | | }
|
| | | return retStr.toString();
|
| | | }
|
| | |
|
| | | public static String encodeURL(String inStr) {
|
| | | StringBuffer retStr = new StringBuffer();
|
| | | int i = 0;
|
| | | while (i < inStr.length()) {
|
| | | if (inStr.charAt(i) == '/') {
|
| | | retStr.append("%2F");
|
| | | } else if (inStr.charAt(i) == ' ') {
|
| | | retStr.append("%20");
|
| | | } else {
|
| | | retStr.append(inStr.charAt(i));
|
| | | }
|
| | |
| | | try {
|
| | | MessageDigest md = MessageDigest.getInstance("SHA-1");
|
| | | md.update(bytes, 0, bytes.length);
|
| | | byte[] sha1hash = md.digest();
|
| | | StringBuilder sb = new StringBuilder(sha1hash.length * 2);
|
| | | for (int i = 0; i < sha1hash.length; i++) {
|
| | | if (((int) sha1hash[i] & 0xff) < 0x10) {
|
| | | sb.append('0');
|
| | | }
|
| | | sb.append(Long.toString((int) sha1hash[i] & 0xff, 16));
|
| | | }
|
| | | return sb.toString();
|
| | | byte[] digest = md.digest();
|
| | | return toHex(digest);
|
| | | } catch (NoSuchAlgorithmException t) {
|
| | | throw new RuntimeException(t);
|
| | | }
|
| | | }
|
| | |
|
| | | public static String getMD5(String string) {
|
| | | try {
|
| | | MessageDigest md = MessageDigest.getInstance("MD5");
|
| | | md.reset();
|
| | | md.update(string.getBytes("iso-8859-1"));
|
| | | byte[] digest = md.digest();
|
| | | return toHex(digest);
|
| | | } catch (Exception e) {
|
| | | Log.warn(e);
|
| | | return null;
|
| | | }
|
| | | }
|
| | |
|
| | | private static String toHex(byte[] bytes) {
|
| | | StringBuilder sb = new StringBuilder(bytes.length * 2);
|
| | | for (int i = 0; i < bytes.length; i++) {
|
| | | if (((int) bytes[i] & 0xff) < 0x10) {
|
| | | sb.append('0');
|
| | | }
|
| | | sb.append(Long.toString((int) bytes[i] & 0xff, 16));
|
| | | }
|
| | | return sb.toString();
|
| | | }
|
| | |
|
| | | public static String decodeBase64(String base64) {
|
| | | return new String(Base64.decode(base64), Charset.forName("UTF-8"));
|
| | | }
|
| | |
|
| | | public static String getRootPath(String path) {
|
| | |
| | | }
|
| | | return relativePath;
|
| | | }
|
| | | |
| | |
|
| | | public static List<String> getStringsFromValue(String value) {
|
| | | return getStringsFromValue(value, " ");
|
| | | }
|
| | | |
| | |
|
| | | public static List<String> getStringsFromValue(String value, String separator) {
|
| | | List<String> strings = new ArrayList<String>();
|
| | | try {
|
| | |
| | |
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.sun.syndication.feed.synd.SyndContent;
|
| | | import com.sun.syndication.feed.synd.SyndContentImpl;
|
| | | import com.sun.syndication.feed.synd.SyndEntry;
|
| | | import com.sun.syndication.feed.synd.SyndEntryImpl;
|
| | | import com.sun.syndication.feed.synd.SyndFeed;
|
| | | import com.sun.syndication.feed.synd.SyndFeedImpl;
|
| | | import com.sun.syndication.feed.synd.SyndImageImpl;
|
| | | import com.sun.syndication.io.FeedException;
|
| | | import com.sun.syndication.io.SyndFeedOutput;
|
| | |
|
| | | public class SyndicationUtils {
|
| | |
|
| | | public static void toRSS(String hostUrl, String title, String description, String repository, List<RevCommit> commits, OutputStream os)
|
| | | throws IOException, FeedException {
|
| | | public static void toRSS(String hostUrl, String title, String description, String repository,
|
| | | List<RevCommit> commits, OutputStream os) throws IOException, FeedException {
|
| | |
|
| | | SyndFeed feed = new SyndFeedImpl();
|
| | | feed.setFeedType("rss_1.0");
|
| | | feed.setFeedType("rss_2.0");
|
| | | feed.setTitle(title);
|
| | | feed.setLink(MessageFormat.format("{0}/summary/{1}", hostUrl, repository));
|
| | | feed.setLink(MessageFormat.format("{0}/summary/{1}", hostUrl,
|
| | | StringUtils.encodeURL(repository)));
|
| | | feed.setDescription(description);
|
| | | SyndImageImpl image = new SyndImageImpl();
|
| | | image.setTitle(Constants.NAME);
|
| | | image.setUrl(hostUrl + Constants.RESOURCE_PATH + "gitblt_25.png");
|
| | | image.setLink(hostUrl);
|
| | | feed.setImage(image);
|
| | |
|
| | | List<SyndEntry> entries = new ArrayList<SyndEntry>();
|
| | | for (RevCommit commit : commits) {
|
| | | SyndEntry entry = new SyndEntryImpl();
|
| | | entry.setTitle(commit.getShortMessage());
|
| | | entry.setAuthor(commit.getAuthorIdent().getName());
|
| | | entry.setLink(MessageFormat.format("{0}/commit/{1}/{2}", hostUrl, repository, commit.getName()));
|
| | | entry.setLink(MessageFormat.format("{0}/commit/{1}/{2}", hostUrl,
|
| | | StringUtils.encodeURL(repository), commit.getName()));
|
| | | entry.setPublishedDate(commit.getCommitterIdent().getWhen());
|
| | |
|
| | | SyndContent content = new SyndContentImpl();
|
| | |
| | |
|
| | | @Override
|
| | | public final String getConfigurationType() {
|
| | | if (GitBlit.self().isDebugMode()) {
|
| | | if (GitBlit.isDebugMode()) {
|
| | | return Application.DEVELOPMENT;
|
| | | }
|
| | | return Application.DEPLOYMENT;
|
| | |
| | | import java.util.List;
|
| | | import java.util.TimeZone;
|
| | |
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | |
|
| | | import org.apache.wicket.Component;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.Request;
|
| | | import org.apache.wicket.behavior.HeaderContributor;
|
| | | import org.apache.wicket.behavior.SimpleAttributeModifier;
|
| | | import org.apache.wicket.markup.html.IHeaderContributor;
|
| | | import org.apache.wicket.markup.html.IHeaderResponse;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.image.ContextImage;
|
| | | import org.apache.wicket.protocol.http.WebRequest;
|
| | | import org.apache.wicket.resource.ContextRelativeResource;
|
| | | import org.eclipse.jgit.diff.DiffEntry.ChangeType;
|
| | | import org.eclipse.jgit.lib.Constants;
|
| | |
| | | }
|
| | |
|
| | | public static ContextImage newImage(String wicketId, String file, String tooltip) {
|
| | | ContextImage img = new ContextImage(wicketId, "/com/gitblit/wicket/resources/" + file);
|
| | | ContextImage img = new ContextImage(wicketId, com.gitblit.Constants.RESOURCE_PATH + file);
|
| | | if (!StringUtils.isEmpty(tooltip)) {
|
| | | setHtmlTooltip(img, tooltip);
|
| | | }
|
| | |
| | | }
|
| | |
|
| | | public static ContextRelativeResource getResource(String file) {
|
| | | return new ContextRelativeResource("/com/gitblit/wicket/resources/" + file);
|
| | | return new ContextRelativeResource(com.gitblit.Constants.RESOURCE_PATH + file);
|
| | | }
|
| | |
|
| | | public static String getHostURL(Request request) {
|
| | | HttpServletRequest req = ((WebRequest) request).getHttpServletRequest();
|
| | | return getHostURL(req);
|
| | | }
|
| | |
|
| | | public static String getHostURL(HttpServletRequest request) {
|
| | | StringBuilder sb = new StringBuilder();
|
| | | sb.append(request.getScheme());
|
| | | sb.append("://");
|
| | | sb.append(request.getServerName());
|
| | | if ((request.getScheme().equals("http") && request.getServerPort() != 80)
|
| | | || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
|
| | | sb.append(":" + request.getServerPort());
|
| | | }
|
| | | return sb.toString();
|
| | | }
|
| | |
|
| | | public static HeaderContributor syndicationDiscoveryLink(final String feedTitle,
|
| | | final String url) {
|
| | | return new HeaderContributor(new IHeaderContributor() {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public void renderHead(IHeaderResponse response) {
|
| | | String contentType = "application/rss+xml";
|
| | |
|
| | | StringBuffer buffer = new StringBuffer();
|
| | | buffer.append("<link rel=\"alternate\" ");
|
| | | buffer.append("type=\"").append(contentType).append("\" ");
|
| | | buffer.append("title=\"").append(feedTitle).append("\" ");
|
| | | buffer.append("href=\"").append(url).append("\" />");
|
| | | response.renderString(buffer.toString());
|
| | | }
|
| | | });
|
| | | }
|
| | |
|
| | | public static PageParameters newUsernameParameter(String username) {
|
| | |
| | | SearchType.AUTHOR));
|
| | | item.add(WicketUtils.createTimestampLabel("authorDate", entry.notesRef
|
| | | .getAuthorIdent().getWhen(), getTimeZone()));
|
| | | item.add(new Label("noteContent", substituteText(entry.content))
|
| | | item.add(new Label("noteContent", GitBlit.self().processCommitMessage(repositoryName, entry.content))
|
| | | .setEscapeModelStrings(false));
|
| | | }
|
| | | };
|
| | |
| | | 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.Crypt;
|
| | | import org.eclipse.jetty.http.security.Credential.MD5;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.GitBlit;
|
| | |
| | | return;
|
| | | }
|
| | | String password = userModel.password;
|
| | | if (!password.toUpperCase().startsWith(Crypt.__TYPE)
|
| | | && !password.toUpperCase().startsWith(MD5.__TYPE)) {
|
| | | if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE)) {
|
| | | // This is a plain text password.
|
| | | // Check length.
|
| | | int minLength = GitBlit.getInteger(Keys.realm.minPasswordLength, 5);
|
| | |
| | | String type = GitBlit.getString(Keys.realm.passwordStorage, "md5");
|
| | | if (type.equalsIgnoreCase("md5")) {
|
| | | // store MD5 digest of password
|
| | | userModel.password = MD5.digest(userModel.password);
|
| | | userModel.password = StringUtils.MD5_TYPE + StringUtils.getMD5(userModel.password);
|
| | | }
|
| | | }
|
| | |
|
| | |
| | | public LogPage(PageParameters params) {
|
| | | super(params);
|
| | |
|
| | | addSyndicationDiscoveryLink();
|
| | | |
| | | int pageNumber = WicketUtils.getPage(params);
|
| | | int prevPage = Math.max(0, pageNumber - 1);
|
| | | int nextPage = pageNumber + 1;
|
| | |
| | | import java.util.HashMap;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Map.Entry;
|
| | |
|
| | | import org.apache.wicket.Component;
|
| | | import org.apache.wicket.PageParameters;
|
| | |
| | | }
|
| | | };
|
| | | add(extrasView);
|
| | | |
| | |
|
| | | add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()
|
| | | .getRelativePathPrefixToContextRoot(), repositoryName, null, 0)));
|
| | |
|
| | |
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | protected void addSyndicationDiscoveryLink() {
|
| | | add(WicketUtils.syndicationDiscoveryLink(SyndicationServlet.getTitle(repositoryName,
|
| | | objectId), SyndicationServlet.asLink(getRequest()
|
| | | .getRelativePathPrefixToContextRoot(), repositoryName, objectId, 0)));
|
| | | }
|
| | |
|
| | | protected Repository getRepository() {
|
| | |
| | | protected void addFullText(String wicketId, String text, boolean substituteRegex) {
|
| | | String html;
|
| | | if (substituteRegex) {
|
| | | html = substituteText(text);
|
| | | html = GitBlit.self().processCommitMessage(repositoryName, text);
|
| | | } else {
|
| | | html = StringUtils.breakLinesForHtml(text);
|
| | | }
|
| | | add(new Label(wicketId, html).setEscapeModelStrings(false));
|
| | | }
|
| | |
|
| | | protected String substituteText(String text) {
|
| | | String html = StringUtils.breakLinesForHtml(text);
|
| | | Map<String, String> map = new HashMap<String, String>();
|
| | | // global regex keys
|
| | | if (GitBlit.getBoolean(Keys.regex.global, false)) {
|
| | | for (String key : GitBlit.getAllKeys(Keys.regex.global)) {
|
| | | if (!key.equals(Keys.regex.global)) {
|
| | | String subKey = key.substring(key.lastIndexOf('.') + 1);
|
| | | map.put(subKey, GitBlit.getString(key, ""));
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // repository-specific regex keys
|
| | | List<String> keys = GitBlit.getAllKeys(Keys.regex._ROOT + "."
|
| | | + repositoryName.toLowerCase());
|
| | | for (String key : keys) {
|
| | | String subKey = key.substring(key.lastIndexOf('.') + 1);
|
| | | map.put(subKey, GitBlit.getString(key, ""));
|
| | | }
|
| | |
|
| | | for (Entry<String, String> entry : map.entrySet()) {
|
| | | String definition = entry.getValue().trim();
|
| | | String[] chunks = definition.split("!!!");
|
| | | if (chunks.length == 2) {
|
| | | html = html.replaceAll(chunks[0], chunks[1]);
|
| | | } else {
|
| | | logger.warn(entry.getKey()
|
| | | + " improperly formatted. Use !!! to separate match from replacement: "
|
| | | + definition);
|
| | | }
|
| | | }
|
| | | return html;
|
| | | }
|
| | |
|
| | | protected abstract String getPageName();
|
| | |
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.protocol.http.WebRequest;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | | import org.wicketstuff.googlecharts.Chart;
|
| | |
| | | metrics = MetricUtils.getDateMetrics(r, null, true, null);
|
| | | metricsTotal = metrics.remove(0);
|
| | | }
|
| | | |
| | | addSyndicationDiscoveryLink();
|
| | |
|
| | | // repository description
|
| | | add(new Label("repositoryDescription", getRepositoryModel().description));
|
| | |
| | | default:
|
| | | add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));
|
| | | }
|
| | |
|
| | | HttpServletRequest req = ((WebRequest) getRequestCycle().getRequest())
|
| | | .getHttpServletRequest();
|
| | | StringBuilder sb = new StringBuilder();
|
| | | sb.append(req.getScheme());
|
| | | sb.append("://");
|
| | | sb.append(req.getServerName());
|
| | | if ((req.getScheme().equals("http") && req.getServerPort() != 80)
|
| | | || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
|
| | | sb.append(":" + req.getServerPort());
|
| | | }
|
| | | sb.append(WicketUtils.getHostURL(getRequestCycle().getRequest())); |
| | | sb.append(Constants.GIT_SERVLET_PATH);
|
| | | sb.append(repositoryName);
|
| | | repositoryUrls.add(sb.toString());
|
| | |
| | | <th wicket:id="orderByOwner"><wicket:message key="gb.owner">Owner</wicket:message></th>
|
| | | <th></th>
|
| | | <th wicket:id="orderByDate"><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
|
| | | <th clas="right"></th>
|
| | | <th class="right"></th>
|
| | | </tr>
|
| | | </wicket:fragment>
|
| | |
|
| | |
| | | <td class="author"><span wicket:id="repositoryOwner">[repository owner]</span></td>
|
| | | <td style="text-align: right;padding-right:10px;"><img class="inlineIcon" wicket:id="ticketsIcon" /><img class="inlineIcon" wicket:id="docsIcon" /><img class="inlineIcon" wicket:id="frozenIcon" /><img class="inlineIcon" wicket:id="accessRestrictionIcon" /></td>
|
| | | <td><span wicket:id="repositoryLastChange">[last change]</span></td>
|
| | | <td class="rightAlign"><span wicket:id="repositoryLinks"></span></td>
|
| | | <td class="rightAlign">
|
| | | <span wicket:id="repositoryLinks"></span>
|
| | | <a style="text-decoration: none;" wicket:id="syndication">
|
| | | <img style="border:0px;vertical-align:middle;" src="/com/gitblit/wicket/resources/feed_16x16.png"></img>
|
| | | </a>
|
| | | </td> |
| | | </wicket:fragment>
|
| | |
|
| | | </wicket:panel>
|
| | |
| | | import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.link.Link;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | |
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.SyndicationServlet;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
| | | } else {
|
| | | row.add(new Label("repositoryLinks"));
|
| | | }
|
| | | row.add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()
|
| | | .getRelativePathPrefixToContextRoot(), entry.name, null, 0)));
|
| | | WicketUtils.setAlternatingBackground(item, counter);
|
| | | counter++;
|
| | | }
|
| | |
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.storage.file.FileRepository;
|
| | |
|
| | | import com.gitblit.FileLoginService;
|
| | | import com.gitblit.FileSettings;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.JettyLoginService;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | |
|
| | |
| | | protected void setUp() throws Exception {
|
| | | FileSettings settings = new FileSettings("distrib/gitblit.properties");
|
| | | GitBlit.self().configureContext(settings);
|
| | | JettyLoginService loginService = new JettyLoginService(new File("distrib/users.properties"));
|
| | | loginService.loadUsers();
|
| | | FileLoginService loginService = new FileLoginService(new File("distrib/users.properties"));
|
| | | GitBlit.self().setLoginService(loginService);
|
| | |
|
| | | if (REPOSITORIES.exists() || REPOSITORIES.mkdirs()) {
|