There is a good answer for reloading the Grails Bootstrap in Reloading bootstrap with Grails
But I have environments defined in my init closure and so I get the error:
groovy.lang.MissingMethodException: No signature of method: BootStrap.environments() is applicable for argument types: (BootStrap$_closure1_closure3) values: [BootStrap$_closure1_closure3#19ad0326]
Bootstrap code is basically the spring-security domain classes for role, user, user_role
import org.mine.*
class BootStrap
{
def init =
{ servletContext ->
environments
{
development
{
def adminRole = new DummyRole(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new DummyRole(authority: 'ROLE_USER').save(flush: true)
def user = new DummyUser(username: 'user1', email_address: 'user1#mine.org', enabled: true, password: 'password')
def user1 = new DummyUser(username: 'user2', email_address: 'user2#mine.org', enabled: true, password: 'password')
def user2 = new DummyUser(username: 'user3', email_address: 'user3#mine.org', enabled: true, password: 'password')
user.save(flush: true)
user1.save(flush: true)
user2.save(flush: true)
DummyUserDummyRole.create manager, adminRole, true
DummyUserDummyRole.create user, userRole, true
DummyUserDummyRole.create user1, userRole, true
DummyUserDummyRole.create user2, userRole, true
assert DummyUser.count() >= 9
assert DummyRole.count() >= 10
assert DummyUserDummyRole.count() >= 9
} // end-development
test {
// bootstrap data for test environment
}
production {
// bootstrap data for production environment
}
}
}
def destroy =
{
// code here
}
}
This works for me:
def servletCtx = org.codehaus.groovy.grails.web.context.ServletContextHolder.servletContext
def myBootstrapArtefact = grailsApplication.getArtefacts('Bootstrap')[-1]
BootStrap.metaClass.environments = grails.util.Environment.&executeForCurrentEnvironment
myBootstrapArtefact.referenceInstance.init(servletCtx)
Lovingly copied (and then modified) from the answer you referenced :-)
I alway used this solution and it worked for me. Works with Grails 3.x too. Here
It is much easier to just swap your syntax to:
Environment.executeForCurrentEnvironment {
production {
// do something in production
}
development {
// do something only in development
}
}
Related
When i logged into my application as a superuser user type 'superuser' stored in localstorage after successful login. But when i logged in as a admin user 'admin' usertype stored into localstorage & it will call the services which only accessible by superuser for the admin user.
Login component where local storage item set as a userInfo key
this.commonService.login(loginData).subscribe(res => {
let encodeCode = AES.encrypt(res['user'].organizationId, myGlobals.ENC_KEY).toString();
// if (res['user'].type == 'admin'){
// this.router.navigate(["../admin/organization/edit"], { queryParams: { id: encodeCode }, relativeTo: this.route });
// } else {
this.router.navigate([""]);
// }
this.spinner.hide();
Toast.fire({
type: 'success',
title: 'Logged in successfully'
})
this.isError = false;
localStorage.setItem('token', res['accessToken']);
localStorage.setItem("userInfo", JSON.stringify(res['user']));
let defaultSet: any = { org: true, user: true, flow: true, conn: true };
localStorage.setItem("default", JSON.stringify(defaultSet));
}, error => {
this.isError = true;
});
Organization component where condition is set
ngOnInit() {
this.searchValid();
if (this.userType.type == 'superuser') {
this.organizationList();
} else {
this.projectList();
}
$("#orgLink").addClass('active');
// Initialize Socket
if (myGlobals.SOCKET) {
this.initSocket();
}
}
This is driving me nuts. 2.4.4 My integration tests all pass. Upgrading to 2.5.5 and I get errors like this all over the place:
No signature of method: Project.addToMonitorings() is applicable for argument types: (Monitoring) values: [Monitoring : (unsaved)] Possible solutions: getMonitorings()
I cannot seem to track down how to update the integration tests to make them pass again.
Example (current) Test:
class MonitoringServiceSpec extends Specification {
def monitoringService
TestDataFactory f // factory that builds objects so we can use them in other tests
def setup() {
f = new TestDataFactory()
}
void "results can be limited"() {
given:
Project p = f.getProject()
p.save(flush: true, failOnError: true)
def params = new EcosListParams(new GrailsParameterMap ([offset: 0, max:1, sortColumn: 'id', order: 'asc'], null))
when:
p.addToMonitorings(f.getMonitoring(p)).save(flush: true, failOnError: true)
p.refresh()
def results = monitoringService.getProjectMonitorings(params, p.id)
then:
results.totalCount == 2
results.size() == 1
}
...
}
I get this error everywhere in my app that have one-to-many relationships. They worked perfectly fine in 2.4.4.
Here is what I had to do to get it to work. The getMonitoring method in the data factory already added the Project to the object. It must implicitly do an addTo
import groovy.sql.Sql;
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsParameterMap
import spock.lang.*
class MonitoringServiceSpec extends Specification {
def f = new TestDataFactory()
def proj
def sql
def dataSource
def monitoringService
def setup() {
sql = new Sql(dataSource);
proj = f.getProject().save()
Monitoring mon1 = f.getMonitoring(proj).save()
Monitoring mon2 = f.getMonitoring(proj).save()
// don't need addTo, the getMonitoring method above implicitly adds it to the project
proj.save(flush: true, failOnError: true).refresh()
}
void "results can be limited"() {
given:
def params = new EcosListParams(new GrailsParameterMap ([offset: 0, max:1, sortColumn: 'id', order: 'asc'], null))
when:
def results = monitoringService.getProjectMonitorings(params, proj.id)
then:
results.totalCount == 2
results.size() == 1
}
void "results can be offset"() {
given:
def params1 = new EcosListParams(new GrailsParameterMap ([offset: 0, max:1, sortColumn: 'id', order: 'asc'], null))
def params2 = new EcosListParams(new GrailsParameterMap ([offset: 1, max:1, sortColumn: 'id', order: 'asc'], null))
when:
def results1 = monitoringService.getProjectMonitorings(params1, proj.id)
def results2 = monitoringService.getProjectMonitorings(params2, proj.id)
then:
results1.size() > 0
results1.id != results2
}
}
TestDataFactory
Monitoring getMonitoring(Project p) {
HabitatObjectiveSuccess hos = HabitatObjectiveSuccess.list(max: 1).get(0);
return new Monitoring(visitDate: new Date(), notes: 'notes', created: new Date(), createdBy: getPerson(),
lastUpdated: new Date(), lastUpdatedBy: getPerson(), maintActivitiesOccurring: 2,
maintActivitiesOccurrText: 'maintActivitiesOccurrText', landownerObjectivesMet: 1,
landownerObjectivesMetText: 'landownerObjectivesMetText', speciesObjectivesMet: 1,
speciesObjectivesMetText: 'speciesObjectivesMetText', habitatObjectiveSuccess: hos,
habitatObjectiveSuccessText: 'habitatObjectiveSuccessText', project: p
)
}
I know I can skip validations for an individual save, like this:
User.new(name: 'John').save(validate: false)
But how can I do that when saving multiple objects at once? Like this:
Category.create([
{ name: 'Apps' },
{ name: 'Songs' },
{ name: 'Movies' }
])
I found this gem: https://github.com/zdennis/activerecord-import
It works like this:
categories = [
Category.new(name: 'Apps'),
Category.new(name: 'Songs'),
Category.new(name: 'Movies')
]
Category.import(categories, validate: false)
It is also possible to use plain arrays instead of ActiveRecord objects.
I guess it generates pure SQL when validate is set to false so it can skip validations.
You can't do that with create. If you really must skip validations you can do something like this:
[
{ name: 'Apps' },
{ name: 'Songs' },
{ name: 'Movies' }
].each do |attributes|
c = Category.new(attributes)
s.save(validate: false)
end
I'm using Grails with Spring Security plugin and want to create default User when application starts.
I have default User and Authority classes
My BootStrap.groovy is as follows:
class BootStrap {
def init = { servletContext ->
def userAuthority = Authority.findByAuthority('ROLE_USER') ?: new Authority(authority: 'ROLE_USER').save(flush: true)
def adminAuthority = Authority.findByAuthority('ROLE_ADMIN') ?: new Authority(authority: 'ROLE_ADMIN').save(flush: true)
def defaultUser = new User(username: "admin", password: "password", accountExpired: false, accountLocked: false,
passwordExpired: false, enabled: true).save(flush: true)
assert defaultUser != null
if (!defaultUser.getAuthorities().contains(userAuthority)) {
UserAuthority.create defaultUser , userAuthority, true
}
if (!defaultUser.getAuthorities().contains(adminAuthority)) {
UserAuthority.create defaultUser , adminAuthority, true
}
assert User.count() == 1
assert Authority.count() == 2
assert UserAuthority.count() == 2
}
def destroy = {}
}
When I start the application it gives me an exception and fails:
Error initializing the application: Cannot invoke method getAuthorities() on null object
So it doesn't create a User instance for some reason (have no idea why).
I'm using default in memory H2 database.
What it can be? I'll really appreciate any help because I've spent a couple of hours on resolving this :(
I'm trying to render some content for all users and some for the ROLE_ADMIN. I can login as both the adminuser and useruser (authed via CAS) but see the same content for both
Here's the controller
package college.infotech.edu
import java.awt.GraphicsConfiguration.DefaultBufferCapabilities;
import grails.plugin.springsecurity.annotation.Secured
class SecureController {
#Secured(['ROLE_ADMIN', 'ROLE_USER'])
def index() {
render 'All Users see this'
def showUserName
render "<br />"
render request.remoteUser
#Secured(['ROLE_ADMIN'])
def showAdmin = {
render "<br />"
render "admin users see this"
}
}
Here's my bootstrap.groovy (which has been working and does authenticate via CAS
.......
def init = { servletContext ->
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
def testUser = new AppUser(username: 'adminuser', password:'password', enabled: true, accountExpired: false, accountLocked: false, passwordExpired: false)
testUser.save(flush: true)
def testUser2 = new AppUser(username: 'useruser', password:'password', enabled: true, accountExpired: false, accountLocked: false, passwordExpired: false)
testUser2.save(flush: true)
UserRole.create testUser, adminRole, true
UserRole.create testUser2, userRole, true
assert AppUser.count() == 2
assert Role.count() == 2
assert UserRole.count() == 2
}
.......
Here's some relevant logs entries
[http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /secure/index; Attributes: [ROLE_ADMIN, ROLE_USER]
[http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.cas.authentication.CasAuthenticationToken#5d4cb3a4: Principal: grails.plugin.springsecurity.userdetails.GrailsUser#17617e0a: Username: adminuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: CCFEACE94A4EC5FFB3B13ACA0E06BB1A; Granted Authorities: ROLE_ADMIN Assertion: org.jasig.cas.client.validation.AssertionImpl#37b7e6ad [http-bio-8080-exec-8] DEBUG hierarchicalroles.RoleHierarchyImpl - getReachableGrantedAuthorities() - From the roles [ROLE_ADMIN] one can reach [ROLE_ADMIN] in zero or more steps.
[http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Authorization successful
That's a weird looking controller action. It's a method called index secured with either ROLE_ADMIN or ROLE_USER, and multiple render calls and a mysterious annotated showAdmin closure. In general you should only have one render call, and if Grails concatenates the rendered output from multiple calls for you, you should consider it a bug that will be fixed at some point.
The inner showAdmin closure isn't doing anything. It's just a closure in the middle of a method, and it's not called by Grails or your code. Since it's just an object inside a method, it's not seen by Grails as a callable action, and it's not seen by Spring Security as something to be guarded or processed.