git-annex/doc/design/assistant/blog/day_44__webapp_basics.mdwn
Joey Hess 7189dfd77d git-annex (5.20131127) unstable; urgency=low
* webapp: Detect when upgrades are available, and upgrade if the user
    desires.
    (Only when git-annex is installed using the prebuilt binaries
    from git-annex upstream, not from eg Debian.)
  * assistant: Detect when the git-annex binary is modified or replaced,
    and either prompt the user to restart the program, or automatically
    restart it.
  * annex.autoupgrade configures both the above upgrade behaviors.
  * Added support for quvi 0.9. Slightly suboptimal due to limitations in its
    interface compared with the old version.
  * Bug fix: annex.version did not get set on automatic upgrade to v5 direct
    mode repo, so the upgrade was performed repeatedly, slowing commands down.
  * webapp: Fix bug that broke switching between local repositories
    that use the new guarded direct mode.
  * Android: Fix stripping of the git-annex binary.
  * Android: Make terminal app show git-annex version number.
  * Android: Re-enable XMPP support.
  * reinject: Allow to be used in direct mode.
  * Futher improvements to git repo repair. Has now been tested in tens
    of thousands of intentionally damaged repos, and successfully
    repaired them all.
  * Allow use of --unused in bare repository.

# imported from the archive
2013-11-27 18:41:44 -04:00

83 lines
3.6 KiB
Markdown

After an all-nighter, I have `git annex webapp` launching a WebApp!
It doesn't do anything useful yet, just uses Yesod to display a couple of
hyperlinked pages and a favicon, securely.
The binary size grew rather alarmingly, BTW. :) Indeed, it's been growing
for months..
-rwxr-xr-x 1 root root 9.4M Jul 21 16:59 git-annex-no-assistant-stripped
-rwxr-xr-x 1 joey joey 12M Jul 25 20:54 git-annex-no-webapp-stripped
-rwxr-xr-x 1 joey joey 17M Jul 25 20:52 git-annex-with-webapp-stripped
----
Along the way, some Not Invented Here occurred:
I didn't use the yesod scaffolded site, because it's a lot of what
seems mostly to be cruft in this use case. And because I don't like
code generated from templates that people are then expected to edit. Ugh.
That's my least favorite part of Yesod. This added some pain, since
I had to do everything the hard way.
I didn't use [wai-handler-launch](http://hackage.haskell.org/package/wai-handler-launch)
because:
* It seems broken on IPv6 capable machines (it always opens
`http://127.0.0.1:port/` even though it apparently doesn't always
listen there.. I think it was listening on my machine's ipv6 address
instead. I know, I know; I should file a bug about this..)
* It always uses port 4587, which is **insane**. What if you have two
webapps?
* It requires javascript in the web browser, which
is used to ping the server, and shut it down when the web browser closes
(which behavior is wrong for git-annex anyway, since the daemon should
stay running across browser closes).
* It opens the webapp on web server startup, which is wrong for git-annex;
instead the command `git annex webapp` will open the webapp,
after `git annex assistant` started the web server.
Instead, I rolled my own WAI webapp laucher, that binds to any free port
on localhost, It does use `xdg-open` to launch the web browser,
like wai-handler-launch (or just `open` on OS X).
Also, I wrote my own WAI logger, which logs using System.Log.Logger,
instead of to stdout, like `runDebug` does.
----
The webapp only listens for connections from localhost, but that's
not sufficient "security". Instead, I added a secret token to
every url in the webapp, that only `git annex webapp` knows about.
But, if that token is passed to `xdg-open` on its command line,
it will be briefly visible to local attackers in the parameters of
`xdg-open`.. And if the web browser's not already running, it'll run
with it as a parameter, and be *very* visible.
So instead, I used a nasty hack. On startup, the assistant
will create a html file, readably only by the user, that redirects
the user to the real site url. Then `git annex webapp` will run
xdg-open on that file.
----
Making Yesod check the `auth=` parameter (to verify that the secret token
is right) is when using Yesod started to pay off. Yesod has a simple
`isAuthorized` method that can be overridden to do your own authentication
like this.
But Yesod really started to shine when I went to add the `auth=` parameter
to every url in the webapp. There's a `joinPath` method can can be used
to override the default url builder. And every type-safe url in the
application goes through there, so it's perfect for this.
I just had to be careful to make it not add `auth=` to the url for the
favicon, which is included in the "Permission Denied" error page. That'd be
an amusing security hole..
----
Next up: Doing some AJAX to get a dynamic view of the state of the daemon,
including currently running transfers, in the webapp. AKA stuff I've never
done before, and that, unlike all this heavy Haskell Yesod, scares me. :)