togglz aspect (#1743)

* togglz aspect

* formatting

* trigger travis build
This commit is contained in:
lor6 2017-04-30 11:39:11 +03:00 committed by Grzegorz Piwowarek
parent b9484b244b
commit 0735c03154
12 changed files with 325 additions and 0 deletions

View File

@ -40,6 +40,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -125,6 +130,18 @@
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.togglz</groupId>
<artifactId>togglz-spring-boot-starter</artifactId>
<version>${togglz.version}</version>
</dependency>
<dependency>
<groupId>org.togglz</groupId>
<artifactId>togglz-spring-security</artifactId>
<version>${togglz.version}</version>
</dependency>
</dependencies>
@ -262,6 +279,7 @@
<subethasmtp.version>3.1.7</subethasmtp.version>
<tomee-servlet-api.version>8.5.11</tomee-servlet-api.version>
<h2.version>1.4.194</h2.version>
<togglz.version>2.4.1.Final</togglz.version>
</properties>
</project>

View File

@ -0,0 +1,37 @@
package com.baeldung.toggle;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private long id;
private double salary;
public Employee() {
}
public Employee(long id, double salary) {
this.id = id;
this.salary = salary;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.toggle;
import org.springframework.data.repository.CrudRepository;
public interface EmployeeRepository extends CrudRepository<Employee, Long>{
}

View File

@ -0,0 +1,12 @@
package com.baeldung.toggle;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface FeatureAssociation {
MyFeatures value();
}

View File

@ -0,0 +1,27 @@
package com.baeldung.toggle;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class FeaturesAspect {
private static final Logger LOG = Logger.getLogger(FeaturesAspect.class);
@Around(value = "@within(featureAssociation) || @annotation(featureAssociation)")
public Object checkAspect(ProceedingJoinPoint joinPoint, FeatureAssociation featureAssociation) throws Throwable {
if (featureAssociation.value()
.isActive()) {
return joinPoint.proceed();
} else {
LOG.info("Feature " + featureAssociation.value()
.name() + " is not enabled!");
return null;
}
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.toggle;
import org.togglz.core.Feature;
import org.togglz.core.activation.UserRoleActivationStrategy;
import org.togglz.core.annotation.ActivationParameter;
import org.togglz.core.annotation.DefaultActivationStrategy;
import org.togglz.core.annotation.EnabledByDefault;
import org.togglz.core.annotation.Label;
import org.togglz.core.context.FeatureContext;
public enum MyFeatures implements Feature {
@Label("Administrator Feature")
@EnabledByDefault
@DefaultActivationStrategy(id = UserRoleActivationStrategy.ID, parameters = { @ActivationParameter(name = UserRoleActivationStrategy.PARAM_ROLES_NAME, value = "ROLE_ADMIN") })
ADMIN_FEATURE;
public boolean isActive() {
return FeatureContext.getFeatureManager()
.isActive(this);
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.toggle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SalaryController {
@Autowired
SalaryService salaryService;
@PostMapping(value = "/increaseSalary")
@ResponseBody
public void increaseSalary(@RequestParam long id) {
salaryService.increaseSalary(id);
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.toggle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SalaryService {
@Autowired
EmployeeRepository employeeRepository;
@FeatureAssociation(value = MyFeatures.ADMIN_FEATURE)
public void increaseSalary(long id) {
Employee employee = employeeRepository.findOne(id);
employee.setSalary(employee.getSalary() + employee.getSalary() * 0.1);
employeeRepository.save(employee);
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.toggle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//@formatter:off
auth.inMemoryAuthentication()
.withUser("user").password("pass").roles("USER")
.and()
.withUser("admin").password("pass").roles("ADMIN");
//@formatter:on
}
@Override
public void configure(HttpSecurity http) throws Exception {
//@formatter:off
http.authorizeRequests().antMatchers("/increaseSalary").permitAll()
.and()
.csrf().disable()
.httpBasic();
//@formatter:on
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.toggle;
import javax.annotation.security.RolesAllowed;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.baeldung.autoconfiguration.MySQLAutoconfiguration;
@SpringBootApplication(exclude = MySQLAutoconfiguration.class)
public class ToggleApplication {
@RolesAllowed("*")
public static void main(String[] args) {
System.setProperty("security.basic.enabled", "false");
SpringApplication.run(ToggleApplication.class, args);
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.toggle;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.togglz.core.manager.EnumBasedFeatureProvider;
import org.togglz.core.spi.FeatureProvider;
import org.togglz.core.user.UserProvider;
import org.togglz.spring.security.SpringSecurityUserProvider;
@Configuration
@EnableJpaRepositories("com.baeldung.toggle")
@EntityScan("com.baeldung.toggle")
public class ToggleConfiguration {
@Bean
public FeatureProvider featureProvider() {
return new EnumBasedFeatureProvider(MyFeatures.class);
}
@Bean
public UserProvider userProvider() {
return new SpringSecurityUserProvider("admin");
}
}

View File

@ -0,0 +1,84 @@
package com.baeldung.toggle;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = ToggleApplication.class)
@AutoConfigureMockMvc
public class ToggleTest {
@Autowired
SalaryService salaryService;
@Autowired
EmployeeRepository employeeRepository;
@Autowired
private MockMvc mvc;
@Autowired
private WebApplicationContext wac;
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Before
public void setup() {
this.mvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain)
.build();
}
@Test
public void givenNoAuthentication_whenIncreaseSalary_thenNoIncrease() throws Exception {
Employee emp = new Employee(1, 2000);
employeeRepository.save(emp);
mvc.perform(post("/increaseSalary").param("id", emp.getId() + ""))
.andExpect(status().is(200));
emp = employeeRepository.findOne(1L);
assertEquals("salary incorrect", 2000, emp.getSalary(), 0.5);
}
@Test
public void givenAdminAuthentication_whenIncreaseSalary_thenIncrease() throws Exception {
Employee emp = new Employee(1, 2000);
employeeRepository.save(emp);
mvc.perform(post("/increaseSalary").param("id", emp.getId() + "")
.with(httpBasic("admin", "pass")))
.andExpect(status().is(200));
emp = employeeRepository.findOne(1L);
assertEquals("salary incorrect", 2200, emp.getSalary(), 0.5);
}
@Test
public void givenUserAuthentication_whenIncreaseSalary_thenNoIncrease() throws Exception {
Employee emp = new Employee(1, 2000);
employeeRepository.save(emp);
mvc.perform(post("/increaseSalary").param("id", emp.getId() + "")
.with(httpBasic("user", "pass")))
.andExpect(status().is(200));
emp = employeeRepository.findOne(1L);
assertEquals("salary incorrect", 2000, emp.getSalary(), 0.5);
}
}