83 lines
		
	
	
	
		
			3.6 KiB
			
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			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. :)
 |