I have a contract like:
Contract.make {
ignoreForDevEnvironment() ? ignored() : ""
description ""
request {
method 'POST'
url '/something'
body($(execute("someMethod()")))
}
response {
status 200
}
}
private static Boolean ignoreForDevEnvironment() {
//read Spring Active profiles
//return true if `dev` profile is listed
}
I want my method ignoreForDevEnvironment to read the active spring profiles, how can I achieve this?
Related
I am working on the migration of swagger spring fox to spring doc open api. I followed below link.
https://deepak-shinde.medium.com/migrating-from-springfox-swagger-2-to-springdoc-openapi-3-79a79757b8d1
Below version used.
spring_boot_version= "2.5.5"
springdoc_openapi_version= "1.6.0"
In gradle dependency mentioned as below
implementation "org.springdoc:springdoc-openapi-ui:$springdoc_openapi_version"
implementation "org.springdoc:springdoc-openapi-javadoc:$springdoc_openapi_version"
I defined rest controller.
#RestController
#RequestMapping("/v1")
#Slf4j
#Tag(name = "Master", description = "Master service API")
public class MasterController {
#Operation(summary = "Get test data",security = {
#SecurityRequirement(name = MasterConstant.HTTP_AUTH_SECURITY_SCHEME) }, tags = {
"Master" } ,description = " This method is used to get test data")
#PostMapping("/codes")
public ResponseEntity<MasterCodeResponse> getTestData()
}
application.properties
springdoc.swagger-ui.path=swagger-ui
springdoc.packages-to-exclude=com.master.persistence.*
springdoc.packages-to-scan=com.master.controller,com.common.controller // here * by default not working as its not listing apis
springdoc.api-docs.resolve-schema-properties=false
When i invoke v3/apidocs - Tags is coming empty. No controller name or description is displayed.
"openapi":"3.0.1",
"info":{
"title":"Test REST API",
"version":"1.0.0"
},
"servers":[
{
"url":"http://localhost:8082/master-service/",
"description":"Generated server url"
}
],
"security":[
{
"bearerAuth":[
]
}
],
"tags":[
{
}
],
Same way for operations tags is coming empty.
"/v1/codes":{
"post":{
"tags":[
null
],
"o
Below bean is defined
#Bean
public OpenAPI customizeOpenAPI() {
final String securitySchemeName = "bearerAuth";
return new OpenAPI().addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(
new Components().addSecuritySchemes(securitySchemeName,
new SecurityScheme().name(securitySchemeName).type(SecurityScheme.Type.HTTP)
.scheme("bearer").bearerFormat("JWT")))
.info(new Info().title("Test REST API").version("1.0.0"));
}
Please let me know how to get the summary of the opertaion and controller tags in swagger as well as in the apidocs yaml. Please advice if i am doing something wrong here.
There were some issue about tags, as you can see here
You should try to update springdoc-openapi to at least version 1.6.7.
Here's my test :
#Test
fun `test config properties`() {
mockMvc.request(HttpMethod.GET,"someUrl") {
accept = MediaType.TEXT_PLAIN
}.andExpect {
status { isOk }
content { contentType(MediaType.TEXT_PLAIN) }
}
}
and it fails with this:
Expected :text/plain Actual :text/plain;charset=UTF-8
This is using the Kotlin DSL for MockMVC.
How do I change the accept to allow for charset=UTF-8 ?
There is one factory method which accepts custom value. Try:
MediaType.valueOf("text/plain;charset=UTF-8")
If charset is not the objective of the test Spring Boot provides more flexible assertion of the content-type using contentTypeCompatibleWith():
For instance, in Kotlin DSL it would look like this:
mockMvc.get("/") {
accept = TEXT_HTML
}.andExpect {
content {
contentTypeCompatibleWith(TEXT_HTML)
// ... more assertions here...
}
}
You can also use the constructor accepting the encoding as a parameter:
new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8)
I am new to spring 5.
1) How I can log the method params which are Mono and flux type without blocking them?
2) How to map Models at API layer to Business object at service layer using Map-struct?
Edit 1:
I have this imperative code which I am trying to convert into a reactive code. It has compilation issue at the moment due to introduction of Mono in the argument.
public Mono<UserContactsBO> getUserContacts(Mono<LoginBO> loginBOMono)
{
LOGGER.info("Get contact info for login: {}, and client: {}", loginId, clientId);
if (StringUtils.isAllEmpty(loginId, clientId)) {
LOGGER.error(ErrorCodes.LOGIN_ID_CLIENT_ID_NULL.getDescription());
throw new ServiceValidationException(
ErrorCodes.LOGIN_ID_CLIENT_ID_NULL.getErrorCode(),
ErrorCodes.LOGIN_ID_CLIENT_ID_NULL.getDescription());
}
if (!loginId.equals(clientId)) {
if (authorizationFeignClient.validateManagerClientAccess(new LoginDTO(loginId, clientId))) {
loginId = clientId;
} else {
LOGGER.error(ErrorCodes.LOGIN_ID_VALIDATION_ERROR.getDescription());
throw new AuthorizationException(
ErrorCodes.LOGIN_ID_VALIDATION_ERROR.getErrorCode(),
ErrorCodes.LOGIN_ID_VALIDATION_ERROR.getDescription());
}
}
UserContactDetailEntity userContactDetail = userContactRepository.findByLoginId(loginId);
LOGGER.debug("contact info returned from DB{}", userContactDetail);
//mapstruct to map entity to BO
return contactMapper.userEntityToUserContactBo(userContactDetail);
}
You can try like this.
If you want to add logs you may use .map and add logs there. if filters are not passed it will return empty you can get it with swichifempty
loginBOMono.filter(loginBO -> !StringUtils.isAllEmpty(loginId, clientId))
.filter(loginBOMono1 -> loginBOMono.loginId.equals(clientId))
.filter(loginBOMono1 -> authorizationFeignClient.validateManagerClientAccess(new LoginDTO(loginId, clientId)))
.map(loginBOMono1 -> {
loginBOMono1.loginId = clientId;
return loginBOMono1;
})
.flatMap(o -> {
return userContactRepository.findByLoginId(o.loginId);
})
I'm using Grails Spring Security Core and the Grails Spring Security REST plugin and I'm just starting to get things set up. I initialized the plugins with a User class and an Authority class (defaults) and went to write an integration test, following a guide I found on the Grails website.
It said to put the following in an integration test:
def "test a user with the role ROLE_BOSS is able to access /api/announcements url"() {
when: 'login with the sherlock'
RestBuilder rest = new RestBuilder()
def resp = rest.post("http://localhost:${serverPort}/api/login") {
accept('application/json')
contentType('application/json')
json {
username = 'sherlock'
password = 'elementary'
}
}
then:
resp.status == 200
resp.json.roles.find { it == 'ROLE_BOSS' }
}
I went ahead and did something similar and it worked with a bootstrapped User, but when I tried to do the exact same test with a User created in the test method itself, it would fail with a 401 HTTP response code.
The code I'm trying to run:
void "check get access token"() {
given:
RestBuilder rest = new RestBuilder()
new User(username: "securitySpecTestUserName", password: "securitySpecTestPassword").save(flush: true)
assert User.count == 2
when:
def resp = rest.post("http://localhost:${serverPort}/api/login") {
accept('application/json')
contentType('application/json')
json {
username = "securitySpecTestUserName"
password = "securitySpecTestPassword"
}
}
then:
resp.status == 200
}
Note that the User.count == 2 assertion passes because there is one User in Bootstrap.groovy and the one create in the test method.
Why does this work and pass with the bootstrapped User without any issues at all but not the one created in the method? Is there a way I can write this integration test so that I can test the /api/login endpoint included in the grails-spring-security-rest plugin in this way?
The User you create in the given section is in a transaction that has not been committed. When you make the REST call, the api/login controller will be run in a new transaction that cannot see your un-committed User.
A few options (there are others)...
Create User in BootStrap.groovy
def init = { servletContext ->
environments {
test {
new User(username: "securitySpecTestUserName", password: "securitySpecTestPassword").save(flush: true)
}
}
}
Make REST calls to create the User - assuming you have such functionality
Create User in setup
#Integration
#Rollback
class UserIntSpec extends Specification {
def setup() {
new User(username: "securitySpecTestUserName", password: "securitySpecTestPassword").save(flush: true)
}
void "check get access token"() {
given:
RestBuilder rest = new RestBuilder()
when:
def response = rest.post("http://localhost:${serverPort}/api/login") {
accept('application/json')
contentType('application/json')
json {
username = "securitySpecTestUserName"
password = "securitySpecTestPassword"
}
}
then:
response.status == HttpServletResponse.SC_OK
when:
def token = response.json.access_token
then:
token
}
}
Note: In Grails >= 3.0, setup() is run in a separate transaction and persisted (why it solves your problem) which is not rolled back. Any data will need to be cleaned up manually.
I suggest you read the grails documentation on testing: Integration Testing
So I just started learning Grails, and I am trying incorporate the Spring Security REST plugin into my app, the plugin is installed in addition to spring security core which is working. In my REST client, when I hit "api/login" I am able to get an access token and it says I have the role of "ROLE_ADMIN", but then when I try to hit something using that, I keep getting a 403 Forbidden. In Postman, the REST client I am using, I have my Authorization header with "Bearer {key}", with my url of "http://localhost:8080/test/api/secret" and it gives the 403 error. I am trying to setup the log4j logging to see any other issues, but does anyone know what I should look into, any help would be appreciated. I provided my classes below if that helps, I generally used default values for everything such as the UrlMappings.
RandomController.groovy
package test
import grails.plugin.springsecurity.annotation.Secured
#Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
class MyController {
#Secured(['ROLE_ADMIN'])
def secret() {
render "You have ACCESS!!!"
}
}
Bootstrap.groovy
class BootStrap {
def init = { servletContext ->
def adminRole = new SecRole(authority: 'ROLE_ADMIN').save(flush: true)
def testUser = new SecUser(username: 'bob', password: 'test')
testUser.save(flush: true)
SecUserSecRole.create testUser, adminRole, true
}
def destroy = {
}
}
UrlMappings.groovy
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
"/api/$controller/$action?/$id?(.$format)?"{ constraints { // apply constraints here
} }
"/"(view:"/index")
"500"(view:'/error')
}
}
For what I can see from the code you posted, if you invoke url http://localhost:8080/test/api/secret, it should execute default action (maybe index) in SecretController but the controller you posted is called MyController.
To investigate further, you should enable more verbose logging using log4j configuration as suggested in the doc http://alvarosanchez.github.io/grails-spring-security-rest/1.5.1/docs/guide/debugging.html