/*
* Copyright 2016 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.web;
import com.thoughtworks.go.CurrentGoCDVersion;
import com.thoughtworks.go.server.security.GoAuthority;
import com.thoughtworks.go.server.service.RailsAssetsService;
import com.thoughtworks.go.server.service.VersionInfoService;
import com.thoughtworks.go.server.service.support.toggle.Toggles;
import com.thoughtworks.go.server.util.UserHelper;
import com.thoughtworks.go.util.SystemEnvironment;
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;
import org.springframework.security.Authentication;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContext;
import org.springframework.web.servlet.view.velocity.VelocityToolboxView;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import java.io.StringWriter;
import static org.springframework.security.context.HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY;
public class GoVelocityView extends VelocityToolboxView {
public static final String PRINCIPAL = "principal";
public static final String ADMINISTRATOR = "userHasAdministratorRights";
public static final String TEMPLATE_ADMINISTRATOR = "userHasTemplateAdministratorRights";
public static final String VIEW_ADMINISTRATOR_RIGHTS = "userHasViewAdministratorRights";
public static final String TEMPLATE_VIEW_USER = "userHasTemplateViewUserRights";
public static final String GROUP_ADMINISTRATOR = "userHasGroupAdministratorRights";
public static final String USE_COMPRESS_JS = "useCompressJS";
public static final String CONCATENATED_JAVASCRIPT_FILE_PATH = "concatenatedJavascriptFilePath";
public static final String CONCATENATED_APPLICATION_CSS_FILE_PATH = "concatenatedApplicationCssFilePath";
public static final String CURRENT_GOCD_VERSION = "currentGoCDVersion";
public static final String CONCATENATED_VM_APPLICATION_CSS_FILE_PATH = "concatenatedVmApplicationCssFilePath";
public static final String CONCATENATED_CSS_APPLICATION_CSS_FILE_PATH = "concatenatedCssApplicationCssFilePath";
public static final String CONCATENATED_NEW_THEME_CSS_FILE_PATH = "concatenatedNewThemeCssFilePath";
public static final String CONCATENATED_STAGE_BAR_CANCELLED_ICON_FILE_PATH = "concatenatedStageBarCancelledIconFilePath";
public static final String CONCATENATED_SPINNER_ICON_FILE_PATH = "concatenatedSpinnerIconFilePath";
public static final String CONCATENATED_CRUISE_ICON_FILE_PATH = "concatenatedCruiseIconFilePath";
public static final String PATH_RESOLVER = "pathResolver";
public static final String GO_UPDATE = "goUpdate";
public static final String GO_UPDATE_CHECK_ENABLED = "goUpdateCheckEnabled";
private final SystemEnvironment systemEnvironment;
public GoVelocityView() {
this(new SystemEnvironment());
}
RailsAssetsService getRailsAssetsService() {
return this.getApplicationContext().getAutowireCapableBeanFactory().getBean(RailsAssetsService.class);
}
VersionInfoService getVersionInfoService() {
return this.getApplicationContext().getAutowireCapableBeanFactory().getBean(VersionInfoService.class);
}
public GoVelocityView(SystemEnvironment systemEnvironment) {
this.systemEnvironment = systemEnvironment;
}
protected void exposeHelpers(Context velocityContext, HttpServletRequest request) throws Exception {
RailsAssetsService railsAssetsService = getRailsAssetsService();
VersionInfoService versionInfoService = getVersionInfoService();
velocityContext.put(ADMINISTRATOR, true);
velocityContext.put(GROUP_ADMINISTRATOR, true);
velocityContext.put(TEMPLATE_ADMINISTRATOR, true);
velocityContext.put(VIEW_ADMINISTRATOR_RIGHTS, true);
velocityContext.put(TEMPLATE_VIEW_USER, true);
velocityContext.put(USE_COMPRESS_JS, systemEnvironment.useCompressedJs());
velocityContext.put(Toggles.PIPELINE_COMMENT_FEATURE_TOGGLE_KEY, Toggles.isToggleOn(Toggles.PIPELINE_COMMENT_FEATURE_TOGGLE_KEY));
velocityContext.put(Toggles.AUTH_AND_ROLE_CONFIG_SPA_TOGGLE_KEY, Toggles.isToggleOn(Toggles.AUTH_AND_ROLE_CONFIG_SPA_TOGGLE_KEY));
velocityContext.put(CONCATENATED_JAVASCRIPT_FILE_PATH, railsAssetsService.getAssetPath("application.js"));
velocityContext.put(CONCATENATED_APPLICATION_CSS_FILE_PATH, railsAssetsService.getAssetPath("application.css"));
velocityContext.put(CURRENT_GOCD_VERSION, CurrentGoCDVersion.getInstance());
velocityContext.put(CONCATENATED_VM_APPLICATION_CSS_FILE_PATH, railsAssetsService.getAssetPath("vm/application.css"));
velocityContext.put(CONCATENATED_CSS_APPLICATION_CSS_FILE_PATH, railsAssetsService.getAssetPath("css/application.css"));
velocityContext.put(CONCATENATED_NEW_THEME_CSS_FILE_PATH, railsAssetsService.getAssetPath("new-theme.css"));
velocityContext.put(CONCATENATED_STAGE_BAR_CANCELLED_ICON_FILE_PATH, railsAssetsService.getAssetPath("g9/stage_bar_cancelled_icon.png"));
velocityContext.put(CONCATENATED_SPINNER_ICON_FILE_PATH, railsAssetsService.getAssetPath("spinner.gif"));
velocityContext.put(CONCATENATED_CRUISE_ICON_FILE_PATH, railsAssetsService.getAssetPath("cruise.ico"));
velocityContext.put(PATH_RESOLVER, railsAssetsService);
velocityContext.put(GO_UPDATE, versionInfoService.getGoUpdate());
velocityContext.put(GO_UPDATE_CHECK_ENABLED, versionInfoService.isGOUpdateCheckEnabled());
SecurityContext securityContext = (SecurityContext) request.getSession().getAttribute(
SPRING_SECURITY_CONTEXT_KEY);
if (securityContext == null || securityContext.getAuthentication() == null) {
return;
}
final Authentication authentication = securityContext.getAuthentication();
setPrincipal(velocityContext, authentication);
setAdmininstratorRole(velocityContext, authentication);
}
private void setPrincipal(Context velocityContext, Authentication authentication) throws NamingException {
velocityContext.put(PRINCIPAL, UserHelper.getUserName(authentication).getDisplayName());
}
private void setAdmininstratorRole(Context velocityContext, Authentication authentication) {
final GrantedAuthority[] authorities = authentication.getAuthorities();
if (authorities == null) {
return;
}
removeAdminFromContextIfNecessary(velocityContext, authorities);
removeGroupAdminFromContextIfNecessary(velocityContext, authorities);
removeTemplateAdminFromContextIfNecessary(velocityContext, authorities);
removeTemplateViewUserFromContextIfNecessary(velocityContext, authorities);
removeViewAdminRightsFromContextIfNecessary(velocityContext);
}
private void removeViewAdminRightsFromContextIfNecessary(Context context) {
if (!(context.containsKey(ADMINISTRATOR) || context.containsKey(GROUP_ADMINISTRATOR) || context.containsKey(TEMPLATE_ADMINISTRATOR) || context.containsKey(TEMPLATE_VIEW_USER)))
context.remove(VIEW_ADMINISTRATOR_RIGHTS);
}
private void removeGroupAdminFromContextIfNecessary(Context velocityContext, GrantedAuthority[] authorities) {
boolean administrator = false;
for (GrantedAuthority authority : authorities) {
if (isGroupAdministrator(authority)) {
administrator = true;
}
}
if (!administrator) {
velocityContext.remove(GROUP_ADMINISTRATOR);
}
}
private void removeTemplateAdminFromContextIfNecessary(Context velocityContext, GrantedAuthority[] authorities) {
boolean administrator = false;
for (GrantedAuthority authority : authorities) {
if (isTemplateAdministrator(authority)) {
administrator = true;
}
}
if (!administrator) {
velocityContext.remove(TEMPLATE_ADMINISTRATOR);
}
}
private void removeTemplateViewUserFromContextIfNecessary(Context velocityContext, GrantedAuthority[] authorities) {
boolean isTemplateViewUser = false;
for (GrantedAuthority authority : authorities) {
if(isTemplateViewUser(authority)) {
isTemplateViewUser = true;
}
}
if (!isTemplateViewUser) {
velocityContext.remove(TEMPLATE_VIEW_USER);
}
}
private void removeAdminFromContextIfNecessary(Context velocityContext, GrantedAuthority[] authorities) {
boolean administrator = false;
for (GrantedAuthority authority : authorities) {
if (isAdministrator(authority)) {
administrator = true;
}
}
if (!administrator) {
velocityContext.remove(ADMINISTRATOR);
}
}
private boolean isAdministrator(GrantedAuthority authority) {
return authority.getAuthority().equals(GoAuthority.ROLE_SUPERVISOR.toString());
}
private boolean isGroupAdministrator(GrantedAuthority authority) {
return authority.getAuthority().equals(GoAuthority.ROLE_GROUP_SUPERVISOR.toString());
}
private boolean isTemplateAdministrator(GrantedAuthority authority) {
return authority.getAuthority().equals(GoAuthority.ROLE_TEMPLATE_SUPERVISOR.toString());
}
private boolean isTemplateViewUser(GrantedAuthority authority) {
return authority.getAuthority().equals(GoAuthority.ROLE_TEMPLATE_VIEW_USER.toString());
}
public String getContentAsString() {
try {
Template template = getTemplate();
StringWriter writer = new StringWriter();
template.merge(null, writer);
return writer.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}