/*
* Copyright 2017 ThoughtWorks, Inc.
*
* 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.thoughtworks.go.server.service;
import com.thoughtworks.go.config.*;
import com.thoughtworks.go.server.domain.Username;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class SecurityService {
private GoConfigService goConfigService;
@Autowired
public SecurityService(GoConfigService goConfigService) {
this.goConfigService = goConfigService;
}
public boolean hasViewPermissionForPipeline(Username username, String pipelineName) {
String groupName = goConfigService.findGroupNameByPipeline(new CaseInsensitiveString(pipelineName));
if (groupName == null) {
return true;
}
return hasViewPermissionForGroup(CaseInsensitiveString.str(username.getUsername()), groupName);
}
public boolean hasViewPermissionForGroup(String userName, String pipelineGroupName) {
CruiseConfig cruiseConfig = goConfigService.getCurrentConfig();
if (!cruiseConfig.isSecurityEnabled()) {
return true;
}
CaseInsensitiveString username = new CaseInsensitiveString(userName);
if (isUserAdmin(new Username(username))) {
return true;
}
PipelineConfigs group = cruiseConfig.getGroups().findGroup(pipelineGroupName);
return isUserAdminOfGroup(username, group) || group.hasViewPermission(username, new UserRoleMatcherImpl(cruiseConfig.server().security()));
}
private boolean isUserAdminOfGroup(final CaseInsensitiveString userName, PipelineConfigs group) {
return goConfigService.isUserAdminOfGroup(userName, group);
}
public boolean isUserAdminOfGroup(final CaseInsensitiveString userName, String groupName) {
return goConfigService.isUserAdminOfGroup(userName, groupName);
}
public boolean hasOperatePermissionForPipeline(final CaseInsensitiveString username, String pipelineName) {
String groupName = goConfigService.findGroupNameByPipeline(new CaseInsensitiveString(pipelineName));
if (groupName == null) {
return true;
}
return hasOperatePermissionForGroup(username, groupName);
}
public boolean hasAdminPermissionsForPipeline(Username username, CaseInsensitiveString pipelineName) {
String groupName = goConfigService.findGroupNameByPipeline(pipelineName);
if (groupName == null) {
return true;
}
return isUserAdminOfGroup(username.getUsername(), groupName);
}
public boolean hasOperatePermissionForGroup(final CaseInsensitiveString username, String groupName) {
CruiseConfig cruiseConfig = goConfigService.getCurrentConfig();
if (!cruiseConfig.isSecurityEnabled()) {
return true;
}
if (isUserAdmin(new Username(username))) {
return true;
}
PipelineConfigs group = cruiseConfig.getGroups().findGroup(groupName);
return isUserAdminOfGroup(username, group) || group.hasOperatePermission(username, new UserRoleMatcherImpl(cruiseConfig.server().security()));
}
public boolean hasOperatePermissionForStage(String pipelineName, String stageName, String username) {
if (!goConfigService.isSecurityEnabled()) {
return true;
}
if (!goConfigService.hasStageConfigNamed(pipelineName, stageName)) {
return false;
}
StageConfig stage = goConfigService.stageConfigNamed(pipelineName, stageName);
CaseInsensitiveString userName = new CaseInsensitiveString(username);
//TODO - #2517 - stage not exist
if (stage.hasOperatePermissionDefined()) {
CruiseConfig cruiseConfig = goConfigService.getCurrentConfig();
String groupName = goConfigService.findGroupNameByPipeline(new CaseInsensitiveString(pipelineName));
PipelineConfigs group = goConfigService.getCurrentConfig().findGroup(groupName);
if (isUserAdmin(new Username(userName)) || isUserAdminOfGroup(userName, group)) {
return true;
}
return goConfigService.readAclBy(pipelineName, stageName).isGranted(userName);
}
return hasOperatePermissionForPipeline(new CaseInsensitiveString(username), pipelineName);
}
public boolean isUserAdmin(Username username) {
return goConfigService.isUserAdmin(username);
}
public boolean isSecurityEnabled() {
return goConfigService.isSecurityEnabled();
}
public boolean hasOperatePermissionForFirstStage(String pipelineName, String userName) {
StageConfig stage = goConfigService.findFirstStageOfPipeline(new CaseInsensitiveString(pipelineName));
return hasOperatePermissionForStage(pipelineName, CaseInsensitiveString.str(stage.name()), userName);
}
public boolean canViewAdminPage(Username username) {
return isUserAdmin(username) || isUserGroupAdmin(username) || isAuthorizedToViewAndEditTemplates(username) || isAuthorizedToViewTemplates(username);
}
public boolean canCreatePipelines(Username username) {
return isUserAdmin(username) || isUserGroupAdmin(username);
}
public boolean hasOperatePermissionForAgents(Username username) {
return isUserAdmin(username);
}
public boolean hasViewOrOperatePermissionForPipeline(Username username, String pipelineName) {
return hasViewPermissionForPipeline(username, pipelineName) ||
hasOperatePermissionForPipeline(username.getUsername(), pipelineName);
}
public String logoutSuccessUrl() {
return "/";
}
public String casServiceBaseUrl() {
return goConfigService.serverConfig().getSiteUrlPreferablySecured().getUrl();
}
public List<CaseInsensitiveString> viewablePipelinesFor(Username username) {
List<CaseInsensitiveString> pipelines = new ArrayList<>();
for (String group : goConfigService.allGroups()) {
if (hasViewPermissionForGroup(CaseInsensitiveString.str(username.getUsername()), group)) {
pipelines.addAll(goConfigService.pipelines(group));
}
}
return pipelines;
}
public boolean isUserGroupAdmin(Username username) {
return goConfigService.isGroupAdministrator(username.getUsername());
}
public List<String> modifiableGroupsForUser(Username userName) {
if (isUserAdmin(userName)) {
return goConfigService.allGroups();
}
List<String> modifiableGroups = new ArrayList<>();
for (String group : goConfigService.allGroups()) {
if (isUserAdminOfGroup(userName.getUsername(), group)) {
modifiableGroups.add(group);
}
}
return modifiableGroups;
}
public boolean isAuthorizedToViewAndEditTemplates(Username username) {
return goConfigService.cruiseConfig().canViewAndEditTemplates(username.getUsername());
}
public boolean isAuthorizedToEditTemplate(String templateName, Username username) {
return goConfigService.cruiseConfig().isAuthorizedToEditTemplate(templateName, username.getUsername());
}
public boolean isAuthorizedToViewTemplate(String templateName, Username username) {
return goConfigService.cruiseConfig().isAuthorizedToViewTemplate(templateName, username.getUsername());
}
public boolean isAuthorizedToViewTemplates(Username username) {
return goConfigService.cruiseConfig().isAuthorizedToViewTemplates(username.getUsername());
}
public static class UserRoleMatcherImpl implements UserRoleMatcher {
private final SecurityConfig securityConfig;
public UserRoleMatcherImpl(SecurityConfig securityConfig) {
this.securityConfig = securityConfig;
}
public boolean match(CaseInsensitiveString user, CaseInsensitiveString role) {
return securityConfig.isUserMemberOfRole(user, role);
}
}
}