Class AppPushConfigs

java.lang.Object
com.iizix.server.push.engine.AppPushConfigs

public final class AppPushConfigs extends Object
Finds the push configuration of an application: its .iiziPush container, which holds the VAPID key pair, the VAPID subject, the Firebase project ID and the Firebase service account.

get(String) is singular. It answers "which credentials do I sign with" for one application, and that is a question with one answer per message. NO_APP (*) is the server itself: the iiziRun clients that name no application subscribe with the server's own pair, served by ServerPushKeys. Any other ID is looked up among the server's loaded applications, and its first module project that carries a .iiziPush answers. The fan-out of a send to every application is not here: the resolver expands the subscription store over the application dimension and each row comes back to this lookup with its own ID.

A row is signed by what it was made under (PUSH-CLUSTER-DESIGN 3.3, B-10b, ruled PC-8 and PC-9). signer(SubscriptionRecord) chooses the configuration a stored row is signed with: a row that records no key or project - stored before B-10a - is the application's, as before; one made under the application's key or project is the application's; one made under the server's own * key or project - a subscription made inside iiziRun Developer for an application (RR-21 C) - is *'s; and one made under neither has no credentials on this server and is reported KEY_MISMATCH.

Nothing is held but which (application, key) pairs a KEY_MISMATCH WARNING has been logged for. An application can be hot-deployed, and its container is a live property tree the lookup reaches through ServerShell.getApplication, which performs the hot-deploy reload. Callers carry the application ID and resolve at use, so a redeployed push configuration takes effect at the next lookup.

Key files are the server's own (PUSH-KEYFILES-DESIGN.md section 9, ruling PP-1). With a PushKeyResolver wired, the container of NO_APP that names its VAPID key file or its Firebase service-account key file (VPrivKeyFile, fcmServiceAccountFile) is answered as a detached clone with the secrets filled in from the files - or empty where a file cannot be used, which the transport reports as not configured. An application's container is answered as it is: its secrets were resolved from this machine's secrets store when the application was loaded (PushProps.setSecretsContext), and a reference it carried was dropped then.

Names are canonical. An application is reachable by aliases as well as by its ID; canonicalAppId(String) maps either to the ID getApplications() reports, so that the subscription store never splits one application across an alias and its name.

Author:
Christopher Mindus
  • Field Details

    • NO_APP

      public static final String NO_APP
      The application ID of the subscriptions made with no application chosen: the server's own, served with its own key pair. This is the SUBSCRIBE side of *; the SEND side, SubscriptionStore.ALL_APPS, is the same character meaning every application.
      See Also:
  • Constructor Details

    • AppPushConfigs

      public AppPushConfigs(Function<String, PushProps> lookup)
      Constructor with a custom lookup, for tests. An ID is canonical when the lookup answers it, and no application is enumerated.
      Parameters:
      lookup - Maps an application ID, * included, to its container or null.
    • AppPushConfigs

      public AppPushConfigs(Function<String, PushProps> lookup, UnaryOperator<String> canonical, Supplier<List<String>> appIds)
      Constructor with every seam.
      Parameters:
      lookup - Maps a canonical application ID, * included, to its container or null.
      canonical - Maps an application ID or alias to its canonical ID, * to itself, and an unknown name to null.
      appIds - Supplies the canonical IDs of the loaded applications.
    • AppPushConfigs

      public AppPushConfigs(Function<String, PushProps> lookup, UnaryOperator<String> canonical, Supplier<List<String>> appIds, PushKeyResolver resolver)
      Constructor with every seam and the key-file resolution.
      Parameters:
      lookup - Maps a canonical application ID, * included, to its container or null.
      canonical - Maps an application ID or alias to its canonical ID, * to itself, and an unknown name to null.
      appIds - Supplies the canonical IDs of the loaded applications.
      resolver - Resolves the key references of NO_APP into a detached clone, or null for none.
  • Method Details

    • forServer

      public static AppPushConfigs forServer(IServer server, ServerPushKeys serverKeys)
      Creates the lookup over a running server, without key-file resolution: a container is answered as it is.
      Parameters:
      server - The server.
      serverKeys - The server's own container, for NO_APP.
      Returns:
      The configs.
    • forServer

      public static AppPushConfigs forServer(IServer server, ServerPushKeys serverKeys, PushKeyResolver resolver)
      Creates the lookup over a running server, resolving the key references of the server's own container.
      Parameters:
      server - The server.
      serverKeys - The server's own container, for NO_APP.
      resolver - Resolves the key references of NO_APP into a detached clone, or null for none.
      Returns:
      The configs.
    • get

      public PushProps get(String appId)
      Gets the push container of an application: the container to sign with. An application's own container, as it is: its secrets come from this machine's secrets store (ruling PP-1). For NO_APP with a resolver, the server's own container naming a key file is a detached clone with the secret filled in (or empty when the file cannot be used).
      Parameters:
      appId - The application ID or an alias, * for the server itself.
      Returns:
      The container, or null when the application is unknown or has none.
    • signer

      Chooses the configuration a stored row is signed with, by what the row was made under (PUSH-CLUSTER-DESIGN 3.3, B-10b): the VAPID key fingerprint of a PushTransport.VAPID row, the Firebase project of an PushTransport.FCM row.
      The choice
      The row recordsSigned with
      nothing (stored before B-10a), or another transportthe application's configuration, as before
      the application's key or projectthe application's configuration
      the server's own * key or project*'s configuration (RR-21 C: made inside iiziRun Developer)
      neithernone: KEY_MISMATCH, the row kept

      The keys and projects compared are those of the configurations get(String) answers now, so a key file put right, or a hot-deployed .iiziPush, takes effect at the next send. A KEY_MISMATCH is logged as a WARNING once per (transport, application, key) streak: until a row of that pair can be signed again. Neither the reason nor the log line carries anything but the application, project IDs, which are public, and the first eight characters of each fingerprint (DeviceTokenStore.abbreviate(String), I-D-13): enough to tell two keys apart, never the whole identifier of a key.

      Parameters:
      row - The stored row.
      Returns:
      The choice, never null.
    • getResolver

      public PushKeyResolver getResolver()
      Gets the key-file resolver of the server's own container.
      Returns:
      The resolver, or null when NO_APP's container is answered as it is.
    • canonicalAppId

      public String canonicalAppId(String appId)
      Gets the canonical ID of an application: what ServerShell.getApplications() reports, whichever alias the client used.
      Parameters:
      appId - The application ID or an alias, * for the server itself.
      Returns:
      The canonical ID, * for *, or null when the application is not loaded on this server.
    • getAppIds

      public List<String> getAppIds()
      Gets the canonical IDs of the applications loaded on this server, NO_APP not among them.
      Returns:
      The IDs, never null.
    • dispose

      public void dispose()
      Disposes of the Push Notification when iiziServer is shut-down.