---
name: mmo-agent-login
description: Log into a local MMOFramework deployment (an application using mmo.oauth) without a password and test its pages in a browser. Use when asked to try, click through, smoke-test, screenshot or check the pages of an MMO application running on localhost, to see a page as a given user or role, or to call its json api as a logged-in user.
---
# Logging into a local MMOFramework site
An application using mmo.oauth answers every page with its login form until a session holds a token. Never type
a password into that form, ask for one, or keep one in a skill or a note: the application's command line hands out
a login link instead. It only needs a username: the project's own skill names the one to use (my.oviepro's
`oviepro-local-demo` does); otherwise ask the user which account to test with.
## 1. Get a link
From the application's folder (the one with `admin.php` and `bootstrap.php`):
```bash
php admin.php agent-login --user=<username> --url=<site url> [--redirect=<page>] [--as=<username>] [--ttl=PT8H] -m
```
- `--url` is the url Apache serves the site at (`http://localhost/my.oviepro`). The command line can't work it out
by itself, so always pass it.
- `-m` prints json: `data.url` is the link, `data.header` is an `Authorization: Bearer ...` header for the api,
`data.user` and `data.expires` describe the session. Without `-m`, the same is printed as text.
- `--as=<username>` logs in as someone else to see the site with that user's rights. The `--user` account needs
the `sudo.switchAccount` scope for that.
- The command is `AdminController::route_agentLogin` (mmo.core). It works only when the application is in dev mode
(`MMO_MODE` is `dev`) and gives a 403 otherwise. Each call stores a new access token, which lives for `--ttl`.
- If the command opens the interactive menu instead of answering, or the project has no `admin.php`, see
[No command line](#no-command-line).
Keep the link and the header out of your replies: anyone holding them is logged in until they expire.
## 2. Open it in the browser
Navigate the browser to `data.url`. The `login` route stores the token in the session and redirects to
`--redirect` (the site's root by default). From there the browser stays logged in like a user who typed the
password. `/logout` ends the session.
For the json api, send `data.header` with each request instead (`curl -H "$header" .../user/scopes.json`).
## 3. Visit every page
`GET <site url>/pages.json` (mmo.client's `PageController::routePages`), fetched from the logged-in browser or
with the header, lists every page the current user can open:
```json
{"data": [{"path": "incidents", "url": "http://localhost/my.oviepro/incidents", "title": "Incidents", "menu": true, "templated": false}, ...]}
```
- Pages the user's rights hide are not in the list. Compare two `--as` users to check a role's access.
- A `templated` page needs parameters (`?uid={uid}`), so it can't be opened from the list. Reach it from its
parent page, through a link the parent renders.
- An entity's own page is `entity?uid=<uid>`. Take a uid from a list page or the data api.
For each page, record:
1. the HTTP status and the page title (a login form means the session expired: get a new link);
2. console errors (`read_console_messages` with `onlyErrors`);
3. failed requests: status 400 or more (`read_network_requests`);
4. a PHP error printed into the page (in dev mode the framework prints the exception in a `<pre>`);
5. a screenshot when something is wrong.
Then report the failing pages: url, what failed, and the error text.
## No command line
The command needs a script that boots the application (its root `bootstrap.php`, so its configuration and keys)
and routes to `MMO\core\controllers\AdminController` or a subclass of it. my.oviepro's `admin.php` does. A project
made by `php tools/mmo.php project` doesn't: its `scripts/admin.php` is mmo.admin's deployment tool, which loads
neither. Add this one to the project's root, as `admin.php`, and say so to the user:
```php
<?php
require(__DIR__ . '/bootstrap.php');
$app = \MMO\app([\MMO\core\Application::class => ['=routes' => [\MMO\core\controllers\AdminController::class]]]);
$app->runInteractive();
```
An `admin.php` that already exists but doesn't route to `AdminController` gets it added to its routes. Several shell
controllers can share a script: the one with the command answers.