diff options
-rw-r--r-- | share/Makefile.am | 1 | ||||
-rw-r--r-- | share/www/script/futon.js | 13 | ||||
-rw-r--r-- | share/www/session.html | 96 | ||||
-rw-r--r-- | share/www/style/layout.css | 6 | ||||
-rw-r--r-- | src/couchdb/couch_httpd.erl | 42 |
5 files changed, 146 insertions, 12 deletions
diff --git a/share/Makefile.am b/share/Makefile.am index 3c4b5da5..9c68e159 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -42,6 +42,7 @@ nobase_dist_localdata_DATA = \ www/couch_tests.html \ www/custom_test.html \ www/database.html \ + www/session.html \ www/dialog/_admin_party.html \ www/dialog/_compact_cleanup.html \ www/dialog/_create_admin.html \ diff --git a/share/www/script/futon.js b/share/www/script/futon.js index 752717e9..2c29a5eb 100644 --- a/share/www/script/futon.js +++ b/share/www/script/futon.js @@ -10,6 +10,18 @@ // License for the specific language governing permissions and limitations under // the License. +// $$ inspired by @wycats: http://yehudakatz.com/2009/04/20/evented-programming-with-jquery/ +function $$(node) { + var data = $(node).data("$$"); + if (data) { + return data; + } else { + data = {}; + $(node).data("$$", data); + return data; + } +}; + (function($) { function Session() { @@ -126,6 +138,7 @@ $.couch.session({ success : function(r) { var userCtx = r.userCtx; + $$("#userCtx").userCtx = userCtx; if (userCtx.name) { $("#userCtx .name").text(userCtx.name).attr({href : "/_utils/document.html?"+encodeURIComponent(r.info.authentication_db)+"/org.couchdb.user%3A"+encodeURIComponent(userCtx.name)}); if (userCtx.roles.indexOf("_admin") != -1) { diff --git a/share/www/session.html b/share/www/session.html new file mode 100644 index 00000000..581640b0 --- /dev/null +++ b/share/www/session.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<!-- + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +--> +<html lang="en"> + <head> + <title>Session</title> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> + <link rel="stylesheet" href="style/layout.css?0.11.0" type="text/css"> + <script src="script/json2.js"></script> + <script src="script/sha1.js"></script> + <script src="script/jquery.js?1.4.2"></script> + <script src="script/jquery.couch.js?0.11.0"></script> + <script src="script/jquery.dialog.js?0.11.0"></script> + <script src="script/futon.js?0.11.0"></script> + <script src="script/futon.browse.js?0.11.0"></script> + <script src="script/futon.format.js?0.11.0"></script> + <script> + $(function() { + var ret, reason, q = window.location.search, qps = q.split("&"); + $.map(qps, function(qp) { + var m = qp.match(/return=(.*)/); + if (m) { + ret = decodeURIComponent(m[1]); + } + m = qp.match(/reason=(.*)/); + if (m) { + reason = decodeURIComponent(m[1]); + } + }); + if (reason) { + $("#aboutSession").append('<p>The application says: <em>'+reason+'</em></p>'); + } + if (ret) { + $("#aboutSession").append($('<p>Once you are logged in, click this link to return to your application: </p>').append($("<a></a>").attr("href", ret).text(ret))); + // todo this needs to look different if you are already logged in + // a note about you are logged in but you can't access this + } + // do the sidebar but in the middle without the sidebar + $.futon.storage.set("sidebar", "hidden"); + setTimeout(function() { + var ctx = $$("#userCtx").userCtx; + $.futon.storage.set("sidebar", "show"); + if (ctx && ctx.name) { + $("#aboutSession").append("<p>It looks like you are logged in, maybe you don't have access to that url.</p>"); + } + },100); + }); + </script> + </head> + <body> + <div id="wrap"> + <h1><a href="index.html">Overview</a> + <strong>Session</strong></h1> + <div id="content"> + <h2>Establish or Modify Your Session</h2> + <div id="loginSignup"> + <div id="aboutSession"></div> + <span id="userCtx"> + <span class="loggedout"> + <a href="#" class="signup">Signup</a> or <a href="#" class="login">Login</a> + </span> + <span class="loggedin"> + Welcome <a class="name">?</a>! + <br/> + <a href="#" class="logout">Logout</a> + </span> + <span class="loggedinadmin"> + Welcome <a class="name">?</a>! + <br/> + <a href="#" class="createadmin">Setup more admins</a> or + <a href="#" class="logout">Logout</a> + </span> + <span class="adminparty"> + Welcome to Admin Party! + <br/> + Everyone is admin. <a href="#" class="createadmin">Fix this</a> + </span> + </span> + </div> + </div> + + </div> + </body> +</html> diff --git a/share/www/style/layout.css b/share/www/style/layout.css index b8725f4a..191f3874 100644 --- a/share/www/style/layout.css +++ b/share/www/style/layout.css @@ -603,3 +603,9 @@ form#replicator p.actions { padding: 1px; clear: left; margin: 0; font-family: "DejaVu Sans Mono",Menlo,Courier,monospace; font-size: 11px; } + + +/* Session */ +#loginSignup { + font-size:200%; +}
\ No newline at end of file diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 96be539e..c05fca45 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -686,28 +686,46 @@ error_info({Error, Reason}) -> error_info(Error) -> {500, <<"unknown_error">>, couch_util:to_binary(Error)}. -send_error(_Req, {already_sent, Resp, _Error}) -> - {ok, Resp}; - -send_error(#httpd{mochi_req=MochiReq}=Req, Error) -> - {Code, ErrorStr, ReasonStr} = error_info(Error), - Headers = if Code == 401 -> +error_headers(#httpd{mochi_req=MochiReq}=Req, Code, ErrorStr, ReasonStr) -> + if Code == 401 -> % this is where the basic auth popup is triggered case MochiReq:get_header_value("X-CouchDB-WWW-Authenticate") of undefined -> case couch_config:get("httpd", "WWW-Authenticate", nil) of nil -> - []; + % If the client is a browser and the basic auth popup isn't turned on + % redirect to the session page. + case ErrorStr of + <<"unauthorized">> -> + % if the accept header matches html, then do the redirect. else proceed as usual. + case re:run(MochiReq:get_header_value("Accept"), "html", [{capture, none}]) of + nomatch -> + {Code, []}; + match -> + UrlReturn = ?l2b(couch_util:url_encode(MochiReq:get(path))), + UrlReason = ?l2b(couch_util:url_encode(ReasonStr)), + {302, [{"Location", couch_httpd:absolute_uri(Req, <<"/_utils/session.html?return=",UrlReturn/binary,"&reason=",UrlReason/binary>>)}]} + end; + _Else -> + {Code, []} + end; Type -> - [{"WWW-Authenticate", Type}] + {Code, [{"WWW-Authenticate", Type}]} end; Type -> - [{"WWW-Authenticate", Type}] + {Code, [{"WWW-Authenticate", Type}]} end; true -> - [] - end, - send_error(Req, Code, Headers, ErrorStr, ReasonStr). + {Code, []} + end. + +send_error(_Req, {already_sent, Resp, _Error}) -> + {ok, Resp}; + +send_error(Req, Error) -> + {Code, ErrorStr, ReasonStr} = error_info(Error), + {Code1, Headers} = error_headers(Req, Code, ErrorStr, ReasonStr), + send_error(Req, Code1, Headers, ErrorStr, ReasonStr). send_error(Req, Code, ErrorStr, ReasonStr) -> send_error(Req, Code, [], ErrorStr, ReasonStr). |