Class SecuritySchema

java.lang.Object
com.codename1.backend.security.SecuritySchema

public final class SecuritySchema extends Object

The tables the security layer's database-backed stores keep, as a migration set of the layer's own.

Nothing registers it unless the application asks, and an application that does not ask carries none of it. To ask, set

cn1.security.schema.enabled=true

in application.properties -- the build reads it there and registers the set in the server's entry point -- or, in a server assembled by hand and in a test, call

Migrations.register(SecuritySchema.migrations());

before the server starts.

The setting is the build's to read. A server that finds it true anywhere at run time -- the environment, a system property, a properties file beside it -- without the set having been registered does not start, and says where the setting belongs. Found false at run time, in a server built with it, the set is not applied: the tables are then whatever the database has.

The set is named security, keeps its history in cn1_security_schema_history, and runs before the application's own migrations, so those may refer to its tables.

Every table is named cn1_..., and the same on SQLite, PostgreSQL and MySQL:

Version Tables Used by
1 cn1_users, cn1_authorities JdbcUserDetailsManager
2 cn1_api_key JdbcApiKeyRepository
3 cn1_persistent_logins JdbcTokenRepository
4 cn1_mfa_totp, cn1_mfa_recovery_code JdbcTotpRepository, JdbcRecoveryCodeRepository
5 cn1_rate_limit JdbcRateLimiter
6 cn1_federated_identity JdbcFederatedIdentityRepository
7 cn1_oauth2_registered_client JdbcRegisteredClientRepository
8 cn1_oauth2_authorization, cn1_oauth2_token JdbcOAuth2AuthorizationService
9 cn1_webauthn_user, cn1_webauthn_credential JdbcPublicKeyCredentialUserEntityRepository, JdbcUserCredentialRepository
10 cn1_rate_limit.window_end Expiry-aware cleanup for limiters with different periods
11 cn1_persistent_logins.previous_token_hash Concurrent remember-me rotation grace
12 cn1_persistent_logins.user_agent, cn1_persistent_logins.ip_address The device a remember-me sign-in came from
Adopting an existing schema

The names above are the defaults. Each one can be pointed at a table of another name, so that tables an application already has are used in place rather than copied:

cn1.security.table.cn1_users=app_users
cn1.security.table.cn1_persistent_logins=persistent_logins

or every one renamed at once by a prefix that replaces cn1_:

cn1.security.table-prefix=auth_

A per-table setting wins over the prefix. A name must be a plain SQL identifier (letters, digits and _, optionally qualified by one schema name); anything else is refused when the settings are read. The columns of an adopted table must be the ones described here. Every repository in this package, and the migrations of this set, use the configured names.

A user name is kept twice: as it was given, and folded to lower case in the username_key column every table is keyed by, which is what makes a lookup ignore case the same way on all three engines. Only A to Z are folded; see usernameKey(String).

A moment is epoch milliseconds in a 64-bit integer and a truth value is 0 or 1, as everywhere in the backend's own schemas.

  • Field Details

    • NAME

      public static final String NAME
      The name of the set.
      See Also:
    • ENABLED

      public static final String ENABLED
      The setting that makes the build register the set.
      See Also:
    • TABLE_PREFIX

      public static final String TABLE_PREFIX
      The prefix of a per-table name setting: cn1.security.table.<default name>.
      See Also:
    • TABLE_NAME_PREFIX

      public static final String TABLE_NAME_PREFIX
      The setting that replaces the cn1_ in front of every table name.
      See Also:
  • Method Details

    • configure

      public static void configure(Config config) throws IOException

      Reads the table name settings from config; see the class description. The server calls this with its own configuration. Without it, the settings are read from Config.load() the first time a name is needed.

      Throws
      • IllegalArgumentException: a configured name is not a safe SQL identifier
      Throws:
      IOException
    • setTableName

      public static void setTableName(String defaultName, String name)

      Points one table at another name, as the cn1.security.table.<name> setting does.

      Parameters
      • defaultName: the table's name in this class, such as cn1_users
      • name: the table to use instead, or null for the default
    • resetTableNames

      public static void resetTableNames()
      Restores every default name.
    • table

      public static String table(String defaultName)

      The name a table is used under, after the settings.

      Parameters
      • defaultName: the table's name in this class, such as cn1_users
    • migrations

      public static MigrationSet migrations()
      The set, for Migrations.register.
    • usernameKey

      public static String usernameKey(String username)
      A user name as the tables are keyed by it: A to Z folded to lower case, and nothing else changed. Folded by hand because the platform's own fold follows the server's locale, and a key must not.