Skip to content

Add an admin to an app

You will add a studio at /admin to an app that already uses gisila_orm, register two models, and sign in to browse and edit them.

  • A Postgres database and gisila_orm models generated from a .gisila.yaml schema, with migrations applied. See the ORM section.
  • A database.yaml (or another way to build a DatabaseConfig).
dependencies:
gisila_orm: ^0.2.0
gisila_studio: ^0.3.0
shelf: ^1.4.1
shelf_router: ^1.1.4
Terminal window
dart pub get
lib/admin.dart
import 'package:gisila_orm/gisila.dart';
import 'package:gisila_studio/gisila_studio.dart';
import 'package:shelf/shelf.dart';
import 'models/blog.gisila.g.dart';
Handler buildAdmin(Database db) {
final studio = GisilaStudio(db: db, title: 'Blog Admin');
studio.register<User>(
UserTable.metadata,
listDisplay: ['id', 'firstName', 'lastName', 'email', 'dateJoined'],
searchFields: ['firstName', 'lastName', 'email'],
readonlyFields: ['id', 'dateJoined'],
onSave: {'password': (v) => hashPassword(v as String)}, // your app's hasher
ordering: ['-dateJoined'],
group: 'Users & Auth',
);
studio.register<Author>(
AuthorTable.metadata,
listDisplay: ['id', 'firstName', 'lastName', 'email'],
searchFields: ['firstName', 'lastName', 'email'],
readonlyFields: ['id'],
);
return studio.handler(prefix: '/admin');
}

handler(prefix:) must get the same path you mount it at.

Plain Shelf:

bin/server.dart
import 'package:gisila_orm/gisila.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
import 'package:blog/admin.dart';
Future<void> main() async {
final db = await Database.connect(await DatabaseConfig.fromFile('database.yaml'));
final router = Router()
..get('/', (Request _) => Response.found('/admin/'))
..mount('/admin', buildAdmin(db));
final handler = const Pipeline().addMiddleware(logRequests()).addHandler(router.call);
await io.serve(handler, '0.0.0.0', 8080);
}

Inside a gisila app: mount it from a controller attacher, next to your controllers:

app.registerController(attacher: (app, router, {String prefix = ''}) {
router.mount('/admin', buildAdmin(db));
});

gisila’s global middleware (logging, CORS, rate limits) then applies to studio requests too. See the framework section.

The studio will not serve without a login. Set a username and a password of at least 12 characters:

Terminal window
export STUDIO_USERNAME=admin
export STUDIO_PASSWORD='correct-horse-battery'
# optional, for JWT sessions that work across isolates and restarts:
export STUDIO_SECRET="$(openssl rand -base64 48)"
dart run bin/server.dart

For a throwaway local database you can instead pass allowUnauthenticated: true to GisilaStudio; never do that on a reachable server.

/admin/login/
curl -si localhost:8080/admin/ | head -3
# HTTP/1.1 302 Found

If you get 503 instead, read the server’s stderr: it says why the studio is disabled (missing or weak credentials).

Open http://localhost:8080/admin/, sign in, and you should see the dashboard with Users and Authors and their row counts. Click Users, use the search box, open a row, edit a field and save.