Admin Dashboard

The Misk Admin Dashboard comes for free in Misk and is accessible at /_admin/ if the AdminDashboardModule is installed.

The admin dashboard comes with tabs like Config and Web-Actions that provide visibility and administrative tools to a running Misk service.

The admin dashboard is also extensible! You can add custom tabs to provide service specific operational or adminsitrative tools with the multibindings outlined below.

Generate all the multibindings for your tab with the included Misk-Web CLI command

$ miskweb misk

Multibindings

Add the following multibindings to a KAbstractModule in a Misk service.

If you have many tabs, it may make sense to create a dedicated {Service Name}AdminDashboardModule.kt

Note that there are areas in the generated multibindings below that you will need to fill out or customize to your specific use case.

The generated bindings assume you want to add your tab to the default Misk Admin Dashboard available at /_admin/ in a Misk service.

Dashboard Tab Binding

The Dashboard Tab multibinding adds a menu link for your tab to the Misk Admin Dashboard.

It is organized by link category and can also carry authentication permissions so that tabs only show up to appropriately authenticated users.

Example Dashboard Tab Binding. Generate your tab's bindings with $ miskweb misk.

// DinoAdminDashboardModule.kt

multibind<DashboardTab>().toProvider(DashboardTabProvider<AdminDashboard>(
  name = "Dino Tab",
  slug = "dino-tab",
  url_path_prefix = "/_admin/dino-tab/",
  category = "Dino Service Admin",
  capabilities = setOf("brontosaurus", "dino-service-administrators")
))

Dashboard Tab Binding with Access Annotation

Insted of explicitly coding the list of capabilities or services in the Dashboard Tab binding (above), a Dashboard Tab can be bound with an existing Access Annotation.

Access Annotations are a pattern in Misk where an annotation is associated to an AccessAnnotationEntry and installed as follows:

// DinoAccessModule.kt

@Qualifier
@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION)
annotation class DinoServiceAdministratorAccess

multibind<AccessAnnotationEntry>().toInstance(
  AccessAnnotationEntry<DinoServiceAdministratorAccess>(
    capabilities = listOf("brontosaurus", "dino-service-administrators")))

To use an Access Annotation to set the same authentication on web actions and dashboard tabs, you can use a DashboardTabProvider binding as below.

// DinoAdminDashboardModule.kt

multibind<DashboardTab>().toProvider(
  DashboardTabProvider<AdminDashboard, DinoServiceAdministratorAccess>(
    name = "Dino Tab",
    slug = "dino-tab",
    url_path_prefix = "/_admin/dino-tab/",
    category = "Dino Service Admin",
  ))

Web Tab Resource Module Binding

The Web Tab Resource Module multibinding tells Misk where to find the compiled tab code. It lives in two places:

  • In Classpath/JAR path after running $ miskweb build
  • Served from Webpack-Dev-Server over localhost on a specific port when running $ miskweb start

Note: the port must be unique within your service's tabs if you want to ever have multiple tabs in development simultaneously.

Example Web Tab Resource Module Binding. Generate your tab's bindings with $ miskweb misk.

// DinoAdminDashboardModule.kt

install(WebTabResourceModule(
    environment = environment,
    slug = "dino-tab",
    web_proxy_url = "http://localhost:4242/"
  ))

AdminDashboardTestingModule

To run your Misk Admin Dashboard in DEVELOPMENT or TESTING environments, you'll need to add the AdminDashboardTestingModule to your primary service applicationModules() function.

It will look something like below.

// DinoService.kt

fun main(args: Array<String>) {
  ServiceBuilder.getMiskApplication(::applicationModules).run(args)
}

fun applicationModules(serviceBuilder: ServiceBuilder<DinoConfig>):
  List<KAbstractModule> {
  val modules = mutableListOf(
      ConfigModule.create("dino", serviceBuilder.config),
      DinoAccessModule(),
      DinoActionModule(),
      DinoAdminDashboardModule(serviceBuilder.env)
      DinoPersistenceModule(serviceBuilder.config),
      EnvironmentModule(serviceBuilder.env)
  )

  when (serviceBuilder.env) {
    Environment.PRODUCTION, Environment.STAGING -> {
      modules.addAll(listOf(
          JurassicRealModule(serviceBuilder.env,
            serviceBuilder.config.jurassic)
      ))
    }
    Environment.DEVELOPMENT, Environment.TESTING -> {
      modules.addAll(listOf(
          JurassicTestingModule(serviceBuilder.env,
            serviceBuilder.config.jurassic),
          AdminDashboardTestingModule(serviceBuilder.env)
      ))
    }
  }

  return modules
}

Gradle Sourcesets (service/build.gradle)

You'll need to add your tabs to the build.gradle main.resources so that they are wrapped up in your service jar. Add the Gradle stanza below.

// service/build.gradle (Groovy)

sourceSets {
  main.resources {
    srcDirs += [
        'web/tabs/dino-tab/lib'
    ]
    exclude '**/node_modules'
  }
}

Project Structure in a Misk Service

Misk-Web tabs best live in a web/tabs directory at the same level of src.

See below for an example service project structure with a few tabs.

  trex-service/
    client/
    service/
      build/
      out/
      src/
      web/
        tabs/
          trexangermanagement/
            ...
          trexhealthcheck/
            ...
          trexfoodlog/
            lib/
            node_modules/
            src/
              ...
              index.ts
            package.json
            ...

Misk Admin Dashboard comes with some default links that show up in the top navbar.

You can add your tab to that list with the following multibinding, ensure that the order number is less than 100 so it shows up before the default Misk tabs.

multibind<DashboardNavbarItem>().toInstance(DashboardNavbarItem<AdminDashboard>(
  item = "<a href=\"/_admin/dino-tab/\">Dino Tab</a>",
  order = 1
))