Initial token management

Change-Id: I6177b46961b7a0e53b9fa1fa9430a4d5562ae2da
diff --git a/t/intro.t b/t/intro.t
index ed8181a..0069713 100644
--- a/t/intro.t
+++ b/t/intro.t
@@ -16,6 +16,10 @@
   ->text_is('div.intro > p > strong', 'KorAP')
   ;
 
+# Only routed when existing
+$t->get_ok('/settings')
+  ->status_is(404);
+
 push @{$t->app->renderer->paths}, path(path(__FILE__)->dirname);
 
 $t->app->plugin(Localize => {
diff --git a/t/navigation.t b/t/navigation.t
index f9518e8..b1a9f8e 100644
--- a/t/navigation.t
+++ b/t/navigation.t
@@ -141,6 +141,10 @@
      'Path matches doc/ql/poliqarp-plus#complex');
 like($render, qr!/doc/faq!, 'Path matches doc/faq');
 
+ok($app->navi->exists('doc'));
+ok(!$app->navi->exists('xy'));
+is($app->navigation('xy'), '');;
+
 
 my $c = $app->build_controller;
 $c->stash(page => 'korap');
diff --git a/t/plugin/auth-oauth.t b/t/plugin/auth-oauth.t
index f03f61e..c9c4207 100644
--- a/t/plugin/auth-oauth.t
+++ b/t/plugin/auth-oauth.t
@@ -18,7 +18,8 @@
   'Kalamar-Auth' => {
     client_id => 2,
     client_secret => 'k414m4r-s3cr3t',
-    oauth2 => 1
+    oauth2 => 1,
+    experimental_client_registration => 1
   }
 });
 
@@ -371,7 +372,7 @@
 
 
 # The token is invalid and can't be refreshed!
-$t->get_ok('/?q=baum&cutoff=true')
+$csrf = $t->get_ok('/?q=baum&cutoff=true')
   ->status_is(200)
   ->session_hasnt('/auth')
   ->session_hasnt('/auth_r')
@@ -380,8 +381,57 @@
   ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
   ->content_unlike(qr/\"authorized\"\:\"yes\"/)
   ->element_exists('p.no-results')
+  ->tx->res->dom->at('input[name="csrf_token"]')
+  ->attr('value')
   ;
 
+# Login:
+$t->post_ok('/user/login' => form => {
+  handle_or_email => 'test',
+  pwd => 'pass',
+  csrf_token => $csrf
+})
+  ->status_is(302)
+  ->content_is('')
+  ->header_is('Location' => '/');
+
+$t->get_ok('/')
+  ->status_is(200)
+  ->element_exists_not('div.notify-error')
+  ->element_exists('div.notify-success')
+  ->text_is('div.notify-success', 'Login successful')
+  ->element_exists('aside.off')
+  ->element_exists_not('aside.active')
+  ;
+
+$t->get_ok('/settings/oauth')
+  ->text_is('form.form-table legend', 'Register new client application')
+  ->attr_is('form.oauth-register','action', '/settings/oauth/register')
+  ;
+
+$csrf = $t->post_ok('/settings/oauth/register' => form => {
+  name => 'MyApp',
+  type => 'PUBLIC',
+  desc => 'This is my application'
+})
+  ->text_is('div.notify-error', 'Bad CSRF token')
+  ->tx->res->dom->at('input[name="csrf_token"]')
+  ->attr('value')
+  ;
+
+$t->post_ok('/settings/oauth/register' => form => {
+  name => 'MyApp',
+  type => 'CONFIDENTIAL',
+  desc => 'This is my application',
+  csrf_token => $csrf
+})
+  ->status_is(200)
+  ->element_exists('div.notify-success')
+  ->text_is('legend', 'Client Credentials')
+  ->text_is('label[for=client_id]', 'ID of the client application')
+  ->element_exists('input[name=client_id][readonly][value]')
+  ->element_exists('input[name=client_secret][readonly][value]')
+  ;
 
 done_testing;
 __END__
diff --git a/t/server/mock.pl b/t/server/mock.pl
index a1f0596..21192f0 100644
--- a/t/server/mock.pl
+++ b/t/server/mock.pl
@@ -15,10 +15,12 @@
 my $fixture_path = path(Mojo::File->new(__FILE__)->dirname)->child('..', 'fixtures');
 
 our %tokens = (
-  "access_token"    => "4dcf8784ccfd26fac9bdb82778fe60e2",
-  "refresh_token"   => "hlWci75xb8atDiq3924NUSvOdtAh7Nlf9z",
-  "access_token_2"  => "abcde",
-  "refresh_token_2" => "fghijk"
+  'access_token'    => "4dcf8784ccfd26fac9bdb82778fe60e2",
+  'refresh_token'   => "hlWci75xb8atDiq3924NUSvOdtAh7Nlf9z",
+  'access_token_2'  => "abcde",
+  'refresh_token_2' => "fghijk",
+  'new_client_id' => 'fCBbQkA2NDA3MzM1Yw==',
+  'new_client_secret' => 'KUMaFxs6R1WGud4HM22w3HbmYKHMnNHIiLJ2ihaWtB4N5JxGzZgyqs5GTLutrORj',
 );
 
 helper get_token => sub {
@@ -487,6 +489,31 @@
   )
 };
 
+# Register a client
+post '/v1.0/oauth2/client/register' => sub {
+  my $c = shift;
+  my $json = $c->req->json;
+
+  my $name = $json->{name};
+  my $desc = $json->{desc};
+  my $type = $json->{type};
+  my $url  = $json->{url};
+  my $redirect_url = $json->{redirectURI};
+
+  # Confidential server application
+  if ($type eq 'CONFIDENTIAL') {
+    return $c->render(json => {
+      client_id => $tokens{new_client_id},
+      client_secret => $tokens{new_client_secret}
+    });
+  };
+
+  # Desktop application
+  return $c->render(json => {
+    client_id => $tokens{new_client_id}
+  });
+};
+
 
 app->start;
 
diff --git a/t/settings.t b/t/settings.t
index 9620504..9eb0655 100644
--- a/t/settings.t
+++ b/t/settings.t
@@ -31,21 +31,15 @@
   }
 });
 
-my $app = $t->app;
-
-$app->routes->get('/settings')->to(cb => sub { shift->render('settings') })->name('settings_start');
-$app->routes->get('/settings/:scope/:page')->to(scope => undef, page => undef)->name('settings');
-
-
 $t->get_ok('/settings')
   ->text_is('a[href~/settings/oauth]','OAuth Token Management')
-  ->text_is('h2#page-top', 'Settings')
+  ->text_is('h1 span', 'Settings')
   ;
 
 $t->get_ok('/settings/oauth')
   ->text_is('a[href~/settings/oauth]','OAuth Token Management')
-  ->text_is('h2#page-top', 'Settings')
-  ->text_is('#abc', 'My Settings')
+  ->text_is('h1 span', 'Settings')
+  ->text_is('p#abc', 'My Settings')
   ;
 
 done_testing;