Skip to content

Commit

Permalink
FORGE-2390: Adds some JavaEE security commands
Browse files Browse the repository at this point in the history
Adds login config
Adds security role
Adds security constraint
  • Loading branch information
ivannov authored and gastaldi committed Jul 29, 2015
1 parent 8dbc065 commit 685c4be
Show file tree
Hide file tree
Showing 16 changed files with 1,116 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jboss.forge.addon.javaee.security;

/**
* The value of the transport-guarantee element in the web.xml.
* <p>
* As defined in the Servlet specification, can be CONFIDENTIAL, INTEGRAL and NONE.
*
* @author <a href="mailto:ivan.st.ivanov@gmail.com">Ivan St. Ivanov</a>
*/
public enum TransportGuarantee
{
CONFIDENTIAL, INTEGRAL, NONE
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
*/
package org.jboss.forge.addon.javaee.servlet;

import java.util.List;

import org.jboss.forge.addon.facets.constraints.FacetConstraint;
import org.jboss.forge.addon.facets.constraints.FacetConstraintType;
import org.jboss.forge.addon.facets.constraints.FacetConstraints;
import org.jboss.forge.addon.javaee.Configurable;
import org.jboss.forge.addon.javaee.JavaEEFacet;
import org.jboss.forge.addon.javaee.security.TransportGuarantee;
import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.ProjectFacet;
import org.jboss.forge.addon.projects.facets.WebResourcesFacet;
Expand All @@ -21,6 +20,8 @@
import org.jboss.forge.addon.resource.ResourceFilter;
import org.jboss.shrinkwrap.descriptor.api.webapp.WebAppCommonDescriptor;

import java.util.List;

/**
* If installed, this {@link Project} supports features from the Servlet specification.
*
Expand Down Expand Up @@ -49,4 +50,49 @@ public interface ServletFacet<DESCRIPTOR extends WebAppCommonDescriptor> extends
* Return a reference to the WEB-INF directory of this project.
*/
DirectoryResource getWebInfDirectory();

/**
* Adds a login-config element to the web.xml of the current project.
*
* @param authMethod The authentication mechanism for this login config
* @param realmName The realm name to be used for the authentication scheme chosen for this login config
*/
void addLoginConfig(String authMethod, String realmName);

/**
* Adds a security role to the current project.
*
* @param roleName The name of the security role. Must conform to the NMTOKEN lexical rules
*/
void addSecurityRole(String roleName);

/**
* Returns all the security roles defined for the current project.
*/
List<String> getSecurityRoles();

/**
* Removes a security role from the current project.
*
* @param roleName The name of the role that should be removed
* @return Returns <code>true</code> if the role was successfully removed. If for some reason, e.g. the role was not
* found, the role could not be removed, returns <code>false</code>.
*/
boolean removeSecurityRole(String roleName);

/**
* Adds a security constraint to the current project.
*
* @param displayName The display name of the new security constraints
* @param webResourceName The name of the web resource collection of the new security constraint. Cannot be null
* @param webResourceDescription The description of the web resource collection of the new security constraint
* @param httpMethods The HTTP methods that are protected by the new security constraint. May be empty
* @param urlPatterns The URL patterns that are protected by the new security constraint. May be empty
* @param roleNames The role names which are part of the authentication constraint of the new security constraint. May be empty
* @param transportGuarantee The user data constraint of the new security constraint
*/
void addSecurityConstraint(String displayName, String webResourceName, String webResourceDescription,
Iterable<String> httpMethods, Iterable<String> urlPatterns, Iterable<String> roleNames,
TransportGuarantee transportGuarantee);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.jboss.forge.addon.javaee.security.ui;

import org.jboss.forge.addon.facets.constraints.FacetConstraint;
import org.jboss.forge.addon.javaee.servlet.ServletFacet;
import org.jboss.forge.addon.javaee.ui.AbstractJavaEECommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIContext;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.input.InputComponent;
import org.jboss.forge.addon.ui.input.UICompleter;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.metadata.UICommandMetadata;
import org.jboss.forge.addon.ui.metadata.WithAttributes;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;
import org.jboss.forge.addon.ui.util.Categories;
import org.jboss.forge.addon.ui.util.Metadata;

import javax.inject.Inject;
import java.util.Arrays;

/**
* Adds a login config to the current project.
*
* @author <a href="mailto:ivan.st.ivanov@gmail.com">Ivan St. Ivanov</a>
*/
@FacetConstraint(ServletFacet.class)
public class AddLoginConfigCommand extends AbstractJavaEECommand
{

@Inject
@WithAttributes(label = "Security realm", required = true)
private UIInput<String> securityRealm;

@Inject
@WithAttributes(label = "Authentication method", required = true)
private UIInput<String> authMethod;

@Override
protected boolean isProjectRequired()
{
return true;
}

@Override
public void initializeUI(UIBuilder builder) throws Exception
{
authMethod.setCompleter(new UICompleter<String>()
{
@Override
public Iterable<String> getCompletionProposals(UIContext context, InputComponent<?, String> input,
String value)
{
return Arrays.asList("BASIC", "DIGEST", "FORM", "CLIENT_CERT");
}
});
builder.add(securityRealm).add(authMethod);
}

@Override
public Result execute(UIExecutionContext context) throws Exception
{
ServletFacet servletFacet = getSelectedProject(context).getFacet(ServletFacet.class);
servletFacet.addLoginConfig(authMethod.getValue(), securityRealm.getValue());
return Results.success("Security realm " + securityRealm.getValue() + " and authentication method " +
authMethod.getValue() + " were configured");
}


@Override
public UICommandMetadata getMetadata(UIContext context)
{
return Metadata.from(super.getMetadata(context), getClass()).name("Security: Add login config")
.description("Adds a login config element to the current project")
.category(Categories.create(super.getMetadata(context).getCategory().getName(), "Security"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package org.jboss.forge.addon.javaee.security.ui;

import org.jboss.forge.addon.facets.constraints.FacetConstraint;
import org.jboss.forge.addon.javaee.security.TransportGuarantee;
import org.jboss.forge.addon.javaee.servlet.ServletFacet;
import org.jboss.forge.addon.javaee.ui.AbstractJavaEECommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIContext;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.input.InputComponent;
import org.jboss.forge.addon.ui.input.UICompleter;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.input.UIInputMany;
import org.jboss.forge.addon.ui.metadata.UICommandMetadata;
import org.jboss.forge.addon.ui.metadata.WithAttributes;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;
import org.jboss.forge.addon.ui.util.Categories;
import org.jboss.forge.addon.ui.util.Metadata;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;

/**
* Adds a security constraint to a web resource collection.
*
* @author <a href="mailto:ivan.st.ivanov@gmail.com">Ivan St. Ivanov</a>
*/
@FacetConstraint(ServletFacet.class)
public class AddSecurityConstraintCommand extends AbstractJavaEECommand
{

@Inject
@WithAttributes(label = "Display name", shortName = 'n', description = "The display name of this security constraint")
private UIInput<String> displayName;

@Inject
@WithAttributes(label = "Web resource name", shortName = 'w', required = true, description = "The collective name of the web resources covered by this constraint")
private UIInput<String> webResourceName;

@Inject
@WithAttributes(label = "Description", shortName = 'd', description = "Short description of this web resource collection")
private UIInput<String> description;

@Inject
@WithAttributes(label = "URL patterns", shortName = 'u', required = true, description = "The URL patterns that will be covered by ths web resource collection")
private UIInputMany<String> urlPatterns;

@Inject
@WithAttributes(label = "HTTP methods", shortName = 'h', description = "The HTTP methods that will be covered by ths web resource collection")
private UIInputMany<String> httpMethods;

@Inject
@WithAttributes(label = "Security roles", shortName = 'r', description = "The roles permitted to perform the constrained requests")
private UIInputMany<String> securityRoles;

@Inject
@WithAttributes(label = "Enable user data constraint", shortName = 'u', description = "Establish a requirement to access the constrained request over a protected transport layer")
private UIInput<Boolean> enableUserDataConstraint;

@Inject
@WithAttributes(label = "Transport guarantee", shortName = 't', description = "The type of requirement for used data constraint")
private UIInput<TransportGuarantee> transportGuarantee;

@Override
public void initializeUI(UIBuilder builder) throws Exception
{
ServletFacet<?> servletFacet = getSelectedProject(builder.getUIContext()).getFacet(ServletFacet.class);
final List<String> roles = servletFacet.getSecurityRoles();
httpMethods.setCompleter(new UICompleter<String>()
{
@Override public Iterable<String> getCompletionProposals(UIContext context, InputComponent<?, String> input,
String value)
{
return Arrays.asList("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS");
}
});
securityRoles.setCompleter(new UICompleter<String>()
{
@Override public Iterable<String> getCompletionProposals(UIContext context, InputComponent<?, String> input,
String value)
{
return roles;
}
});
enableUserDataConstraint.setDefaultValue(false);
transportGuarantee.setEnabled(new Callable<Boolean>()
{
@Override public Boolean call() throws Exception
{
return enableUserDataConstraint.getValue();
}
});
builder.add(displayName).add(webResourceName).add(description).add(urlPatterns).add(httpMethods)
.add(securityRoles).add(enableUserDataConstraint).add(transportGuarantee);
}

@Override
public Result execute(UIExecutionContext context) throws Exception
{
ServletFacet servletFacet = getSelectedProject(context).getFacet(ServletFacet.class);

if (securityRoles.getValue().iterator().hasNext())
{
createNonExistingRoles(servletFacet, securityRoles.getValue());
}

TransportGuarantee transportGuaranteeValue = null;
if (enableUserDataConstraint.getValue())
{
transportGuaranteeValue = transportGuarantee.getValue();
}

servletFacet.addSecurityConstraint(displayName.getValue(), webResourceName.getValue(), description.getValue(),
httpMethods.getValue(), urlPatterns.getValue(), securityRoles.getValue(), transportGuaranteeValue);
return Results.success("Security constraint was added successfully");
}

private void createNonExistingRoles(ServletFacet<?> servletFacet, Iterable<String> securityRoles)
{
List<String> existingRoles = servletFacet.getSecurityRoles();
for (String securityRole : securityRoles)
{
if (!existingRoles.contains(securityRole))
{
servletFacet.addSecurityRole(securityRole);
}
}
}

@Override
public UICommandMetadata getMetadata(UIContext context)
{
return Metadata.from(super.getMetadata(context), getClass()).name("Security: Add Constraint")
.description("Add security constraint")
.category(Categories.create(super.getMetadata(context).getCategory().getName(), "Security"));
}

@Override
protected boolean isProjectRequired()
{
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package org.jboss.forge.addon.javaee.security.ui;

import org.jboss.forge.addon.facets.constraints.FacetConstraint;
import org.jboss.forge.addon.javaee.servlet.ServletFacet;
import org.jboss.forge.addon.javaee.ui.AbstractJavaEECommand;
import org.jboss.forge.addon.ui.command.PrerequisiteCommandsProvider;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIContext;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.metadata.UICommandMetadata;
import org.jboss.forge.addon.ui.metadata.WithAttributes;
import org.jboss.forge.addon.ui.result.NavigationResult;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;
import org.jboss.forge.addon.ui.result.navigation.NavigationResultBuilder;
import org.jboss.forge.addon.ui.util.Categories;
import org.jboss.forge.addon.ui.util.Metadata;

import javax.inject.Inject;

/**
* Adds a security role to the current project.
*
* @author <a href="mailto:ivan.st.ivanov@gmail.com">Ivan St. Ivanov</a>
*/
@FacetConstraint(ServletFacet.class)
public class AddSecurityRoleCommand extends AbstractJavaEECommand
{

@Inject
@WithAttributes(label = "Role name", required = true, requiredMessage = "You should enter the role name")
private UIInput<String> roleName;

@Override
protected boolean isProjectRequired()
{
return true;
}

@Override
public void initializeUI(UIBuilder builder) throws Exception
{
builder.add(roleName);
}

@Override
public Result execute(UIExecutionContext context) throws Exception
{
ServletFacet servletFacet = getSelectedProject(context).getFacet(ServletFacet.class);
String roleName = this.roleName.getValue();
servletFacet.addSecurityRole(roleName);
return Results.success("Security role " + roleName + " was created");
}


@Override
public UICommandMetadata getMetadata(UIContext context)
{
return Metadata.from(super.getMetadata(context), getClass()).name("Security: Add Role")
.description("Add security role")
.category(Categories.create(super.getMetadata(context).getCategory().getName(), "Security"));
}

}
Loading

0 comments on commit 685c4be

Please sign in to comment.