////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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

https://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.
////

[[requestmapInstances]]
=== Requestmap Instances Stored in the Database

With this approach you use the `Requestmap` domain class to store mapping entries in the database. `Requestmap` has a `url` property that contains the secured URL pattern and a `configAttribute` property containing a comma-delimited list of required roles, SpEL expressions, and/or tokens such as `IS_AUTHENTICATED_FULLY`, `IS_AUTHENTICATED_REMEMBERED`, and `IS_AUTHENTICATED_ANONYMOUSLY`.

To use `Requestmap` entries, specify `securityConfigType="Requestmap"`:

[source,groovy]
.Listing {counter:listing}. Specifying `securityConfigType` as "`Requestmap`"
----
grails.plugin.springsecurity.securityConfigType = "Requestmap"
----

You create `Requestmap` entries as you create entries in any Grails domain class:

[source,groovy]
.Listing {counter:listing}. Creating `Requestmap` entries
----
for (String url in [
      '/', '/error', '/index', '/index.gsp', '/**/favicon.ico', '/shutdown',
      '/assets/**', '/**/js/**', '/**/css/**', '/**/images/**',
      '/login', '/login.*', '/login/*',
      '/logout', '/logout.*', '/logout/*']) {
   new Requestmap(url: url, configAttribute: 'permitAll').save()
}

new Requestmap(url: '/profile/**',    configAttribute: 'ROLE_USER').save()
new Requestmap(url: '/admin/**',      configAttribute: 'ROLE_ADMIN').save()
new Requestmap(url: '/admin/role/**', configAttribute: 'ROLE_SUPERVISOR').save()
new Requestmap(url: '/admin/user/**',
               configAttribute: 'ROLE_ADMIN,ROLE_SUPERVISOR').save()
new Requestmap(url: '/login/impersonate',
               configAttribute: 'ROLE_SWITCH_USER,IS_AUTHENTICATED_FULLY').save()
springSecurityService.clearCachedRequestmaps()
----

The `configAttribute` value can have a single value or have multiple comma-delimited values. In this example only users with `ROLE_ADMIN` or `ROLE_SUPERVISOR` can access `/admin/user/pass:[**]` urls, and only users with `ROLE_SWITCH_USER` can access the switch-user url (`/login/impersonate`) and in addition must be authenticated fully, i.e. not using a remember-me cookie. Note that when specifying multiple roles, the user must have at least one of them, but when combining `IS_AUTHENTICATED_FULLY`, `IS_AUTHENTICATED_REMEMBERED`, or `IS_AUTHENTICATED_ANONYMOUSLY` with one or more roles means the user must have one of the roles and satisty the `IS_AUTHENTICATED` rule.

Unlike the `application.groovy` Map approach (<<configGroovyMap>>), you do not need to revise the `Requestmap` entry order because the plugin calculates the most specific rule that applies to the current request.

==== Requestmap Cache

`Requestmap` entries are cached for performance, but caching affects runtime configurability. If you create, edit, or delete an instance, the cache must be flushed and repopulated to be consistent with the database. You can call `springSecurityService.clearCachedRequestmaps()` to do this. For example, if you create a `RequestmapController` the `save` action should look like this (and the update and delete actions should similarly call `clearCachedRequestmaps()`):

[source,groovy]
.Listing {counter:listing}. Calling `clearCachedRequestmaps()`
----
class RequestmapController {

   def springSecurityService

   ...

   def save(Requestmap requestmap) {
      if (!requestmap.save(flush: true)) {
         render view: 'create', model: [requestmapInstance: requestmap]
         return
      }

      springSecurityService.clearCachedRequestmaps()

      flash.message = ...
      redirect action: 'show', id: requestmap.id
   }
}
----
