| | |
| | | import com.gitblit.Constants.FederationToken;
|
| | | import com.gitblit.Constants.PermissionType;
|
| | | import com.gitblit.Constants.RegistrantType;
|
| | | import com.gitblit.fanout.FanoutNioService;
|
| | | import com.gitblit.fanout.FanoutService;
|
| | | import com.gitblit.fanout.FanoutSocketService;
|
| | | import com.gitblit.models.FederationModel;
|
| | | import com.gitblit.models.FederationProposal;
|
| | | import com.gitblit.models.FederationSet;
|
| | |
| | | private final Map<String, ProjectModel> projectCache = new ConcurrentHashMap<String, ProjectModel>();
|
| | |
|
| | | private final AtomicReference<String> repositoryListSettingsChecksum = new AtomicReference<String>("");
|
| | | |
| | | private final ObjectCache<String> projectMarkdownCache = new ObjectCache<String>();
|
| | | |
| | | private final ObjectCache<String> projectRepositoriesMarkdownCache = new ObjectCache<String>();
|
| | |
|
| | | private ServletContext servletContext;
|
| | |
|
| | |
| | | private TimeZone timezone;
|
| | |
|
| | | private FileBasedConfig projectConfigs;
|
| | | |
| | | private FanoutService fanoutService;
|
| | |
|
| | | public GitBlit() {
|
| | | if (gitblit == null) {
|
| | |
| | | this.userService.setup(settings);
|
| | | }
|
| | |
|
| | | public boolean supportsAddUser() {
|
| | | return supportsCredentialChanges(new UserModel(""));
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns true if the user's credentials can be changed.
|
| | | *
|
| | | * @param user
|
| | | * @return true if the user service supports credential changes
|
| | | */
|
| | | public boolean supportsCredentialChanges() {
|
| | | return userService.supportsCredentialChanges();
|
| | | public boolean supportsCredentialChanges(UserModel user) {
|
| | | return (user != null && user.isLocalAccount()) || userService.supportsCredentialChanges();
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns true if the user's display name can be changed.
|
| | | *
|
| | | * @param user
|
| | | * @return true if the user service supports display name changes
|
| | | */
|
| | | public boolean supportsDisplayNameChanges() {
|
| | | return userService.supportsDisplayNameChanges();
|
| | | public boolean supportsDisplayNameChanges(UserModel user) {
|
| | | return (user != null && user.isLocalAccount()) || userService.supportsDisplayNameChanges();
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns true if the user's email address can be changed.
|
| | | *
|
| | | * @param user
|
| | | * @return true if the user service supports email address changes
|
| | | */
|
| | | public boolean supportsEmailAddressChanges() {
|
| | | return userService.supportsEmailAddressChanges();
|
| | | public boolean supportsEmailAddressChanges(UserModel user) {
|
| | | return (user != null && user.isLocalAccount()) || userService.supportsEmailAddressChanges();
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns true if the user's team memberships can be changed.
|
| | | *
|
| | | * @param user
|
| | | * @return true if the user service supports team membership changes
|
| | | */
|
| | | public boolean supportsTeamMembershipChanges() {
|
| | | return userService.supportsTeamMembershipChanges();
|
| | | public boolean supportsTeamMembershipChanges(UserModel user) {
|
| | | return (user != null && user.isLocalAccount()) || userService.supportsTeamMembershipChanges();
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | * @return the effective list of permissions for the user
|
| | | */
|
| | | public List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user) {
|
| | | if (StringUtils.isEmpty(user.username)) {
|
| | | // new user
|
| | | return new ArrayList<RegistrantAccessPermission>();
|
| | | }
|
| | | Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>();
|
| | | set.addAll(user.getRepositoryPermissions());
|
| | | // Flag missing repositories
|
| | |
| | | if (config.isOutdated()) {
|
| | | // reload model
|
| | | logger.info(MessageFormat.format("Config for \"{0}\" has changed. Reloading model and updating cache.", repositoryName));
|
| | | model = loadRepositoryModel(repositoryName);
|
| | | removeFromCachedRepositoryList(repositoryName);
|
| | | model = loadRepositoryModel(model.name);
|
| | | removeFromCachedRepositoryList(model.name);
|
| | | addToCachedRepositoryList(model);
|
| | | } else {
|
| | | // update a few repository parameters
|
| | |
| | | }
|
| | | project.title = projectConfigs.getString("project", name, "title");
|
| | | project.description = projectConfigs.getString("project", name, "description");
|
| | | configs.put(name.toLowerCase(), project); |
| | | |
| | | // project markdown
|
| | | File pmkd = new File(getRepositoriesFolder(), (project.isRoot ? "" : name) + "/project.mkd");
|
| | | if (pmkd.exists()) {
|
| | | Date lm = new Date(pmkd.lastModified());
|
| | | if (!projectMarkdownCache.hasCurrent(name, lm)) {
|
| | | String mkd = com.gitblit.utils.FileUtils.readContent(pmkd, "\n");
|
| | | projectMarkdownCache.updateObject(name, lm, mkd);
|
| | | }
|
| | | project.projectMarkdown = projectMarkdownCache.getObject(name);
|
| | | }
|
| | | |
| | | // project repositories markdown
|
| | | File rmkd = new File(getRepositoriesFolder(), (project.isRoot ? "" : name) + "/repositories.mkd");
|
| | | if (rmkd.exists()) {
|
| | | Date lm = new Date(rmkd.lastModified());
|
| | | if (!projectRepositoriesMarkdownCache.hasCurrent(name, lm)) {
|
| | | String mkd = com.gitblit.utils.FileUtils.readContent(rmkd, "\n");
|
| | | projectRepositoriesMarkdownCache.updateObject(name, lm, mkd);
|
| | | }
|
| | | project.repositoriesMarkdown = projectRepositoriesMarkdownCache.getObject(name);
|
| | | }
|
| | | |
| | | configs.put(name.toLowerCase(), project);
|
| | | }
|
| | | projectCache.clear();
|
| | | projectCache.putAll(configs);
|
| | |
| | | return null;
|
| | | }
|
| | | return project;
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns the list of project models that are referenced by the supplied
|
| | | * repository model list. This is an alternative method exists to ensure
|
| | | * Gitblit does not call getRepositoryModels(UserModel) twice in a request.
|
| | | * |
| | | * @param repositoryModels
|
| | | * @param includeUsers
|
| | | * @return a list of project models
|
| | | */
|
| | | public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) {
|
| | | Map<String, ProjectModel> projects = new LinkedHashMap<String, ProjectModel>();
|
| | | for (RepositoryModel repository : repositoryModels) {
|
| | | if (!includeUsers && repository.isPersonalRepository()) {
|
| | | // exclude personal repositories
|
| | | continue;
|
| | | }
|
| | | if (!projects.containsKey(repository.projectPath)) {
|
| | | ProjectModel project = getProjectModel(repository.projectPath);
|
| | | if (project == null) {
|
| | | logger.warn(MessageFormat.format("excluding project \"{0}\" from project list because it is empty!",
|
| | | repository.projectPath));
|
| | | continue;
|
| | | }
|
| | | projects.put(repository.projectPath, project);
|
| | | // clear the repo list in the project because that is the system
|
| | | // list, not the user-accessible list and start building the
|
| | | // user-accessible list
|
| | | project.repositories.clear();
|
| | | project.repositories.add(repository.name);
|
| | | project.lastChange = repository.lastChange;
|
| | | } else {
|
| | | // update the user-accessible list
|
| | | // this is used for repository count
|
| | | ProjectModel project = projects.get(repository.projectPath);
|
| | | project.repositories.add(repository.name);
|
| | | if (project.lastChange.before(repository.lastChange)) {
|
| | | project.lastChange = repository.lastChange;
|
| | | }
|
| | | }
|
| | | }
|
| | | return new ArrayList<ProjectModel>(projects.values());
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | * @return true if the repository exists
|
| | | */
|
| | | public boolean hasRepository(String repositoryName) {
|
| | | if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
|
| | | return hasRepository(repositoryName, false);
|
| | | }
|
| | | |
| | | /**
|
| | | * Determines if this server has the requested repository.
|
| | | * |
| | | * @param name
|
| | | * @param caseInsensitive
|
| | | * @return true if the repository exists
|
| | | */
|
| | | public boolean hasRepository(String repositoryName, boolean caseSensitiveCheck) {
|
| | | if (!caseSensitiveCheck && settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
|
| | | // if we are caching use the cache to determine availability
|
| | | // otherwise we end up adding a phantom repository to the cache
|
| | | return repositoryListCache.containsKey(repositoryName.toLowerCase());
|
| | |
| | | ProjectModel project = getProjectModel(userProject);
|
| | | for (String repository : project.repositories) {
|
| | | if (repository.startsWith(userProject)) {
|
| | | RepositoryModel model = repositoryListCache.get(repository);
|
| | | RepositoryModel model = getRepositoryModel(repository);
|
| | | if (model.originRepository.equalsIgnoreCase(origin)) {
|
| | | // user has a fork
|
| | | return model.name;
|
| | |
| | | */
|
| | | public ForkModel getForkNetwork(String repository) {
|
| | | if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
|
| | | // find the root
|
| | | // find the root, cached
|
| | | RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
|
| | | while (model.originRepository != null) {
|
| | | model = repositoryListCache.get(model.originRepository);
|
| | | }
|
| | | ForkModel root = getForkModelFromCache(model.name);
|
| | | return root;
|
| | | } else {
|
| | | // find the root, non-cached
|
| | | RepositoryModel model = getRepositoryModel(repository.toLowerCase());
|
| | | while (model.originRepository != null) {
|
| | | model = getRepositoryModel(model.originRepository);
|
| | | }
|
| | | ForkModel root = getForkModel(model.name);
|
| | | return root;
|
| | | }
|
| | | return null;
|
| | | }
|
| | | |
| | | private ForkModel getForkModelFromCache(String repository) {
|
| | | RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
|
| | | ForkModel fork = new ForkModel(model);
|
| | | if (!ArrayUtils.isEmpty(model.forks)) {
|
| | | for (String aFork : model.forks) {
|
| | | ForkModel fm = getForkModelFromCache(aFork);
|
| | | fork.forks.add(fm);
|
| | | }
|
| | | }
|
| | | return fork;
|
| | | }
|
| | |
|
| | | private ForkModel getForkModel(String repository) {
|
| | | RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
|
| | | RepositoryModel model = getRepositoryModel(repository.toLowerCase());
|
| | | ForkModel fork = new ForkModel(model);
|
| | | if (!ArrayUtils.isEmpty(model.forks)) {
|
| | | for (String aFork : model.forks) {
|
| | |
| | | }
|
| | |
|
| | | ContainerUtils.CVE_2007_0450.test();
|
| | | |
| | | // startup Fanout PubSub service
|
| | | if (settings.getInteger(Keys.fanout.port, 0) > 0) {
|
| | | String bindInterface = settings.getString(Keys.fanout.bindInterface, null);
|
| | | int port = settings.getInteger(Keys.fanout.port, FanoutService.DEFAULT_PORT);
|
| | | boolean useNio = settings.getBoolean(Keys.fanout.useNio, true);
|
| | | int limit = settings.getInteger(Keys.fanout.connectionLimit, 0);
|
| | | |
| | | if (useNio) {
|
| | | if (StringUtils.isEmpty(bindInterface)) {
|
| | | fanoutService = new FanoutNioService(port);
|
| | | } else {
|
| | | fanoutService = new FanoutNioService(bindInterface, port);
|
| | | }
|
| | | } else {
|
| | | if (StringUtils.isEmpty(bindInterface)) {
|
| | | fanoutService = new FanoutSocketService(port);
|
| | | } else {
|
| | | fanoutService = new FanoutSocketService(bindInterface, port);
|
| | | }
|
| | | }
|
| | | |
| | | fanoutService.setConcurrentConnectionLimit(limit);
|
| | | fanoutService.setAllowAllChannelAnnouncements(false);
|
| | | fanoutService.start();
|
| | | }
|
| | | }
|
| | |
|
| | | private void logTimezone(String type, TimeZone zone) {
|
| | |
| | | scheduledExecutor.shutdownNow();
|
| | | luceneExecutor.close();
|
| | | gcExecutor.close();
|
| | | if (fanoutService != null) {
|
| | | fanoutService.stop();
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|