Permalink
Browse files

Added an optional login link/status to the search public top nav bar.

Thus allowing a more convenient way (wihout the need to go to the admin
section) to login when searching on your remote or password protected
peer and benefit from extended search features such as Heuristics,
Bookmarking or JavasScript resorting.

Can be disabled using the ConfigSearchPage_p.html.
  • Loading branch information...
luccioman committed Oct 21, 2017
1 parent 1de86cf commit af198b990be05a1962b5b9b9962084a2c3a69d6b
@@ -1057,6 +1057,9 @@ publicSearchpage = true
# to /Status.html to get the main memu bar back
publicTopmenu = true
# set to true to include a login link/status in the search page public top navigation bar
search.publicTopNavBar.login = true
# Wiki access rights
# the built-in wiki system allows by default only that the administrator is allowed to make changes
# this can be changed. There are three options:
@@ -40,11 +40,25 @@ <h4>Page Template</h4>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" id="navbar-brand-cfg" href="#[promoteSearchPageGreeting.homepage]#" style="position:absolute;top:-6px;display:inline;white-space:nowrap;">
<img id="greeting-icon" class="yacylogo" src="#[promoteSearchPageGreeting.smallImage]#" alt="#[promoteSearchPageGreeting.imageAlt]#" style="height:auto; width:auto; max-width:200px; max-height:32px;vertical-align:middle;float:left;">&nbsp;<span id="greeting" style="position:absolute; top:50%;float:left;"></span>
<a class="navbar-brand" id="navbar-brand-cfg" href="#[promoteSearchPageGreeting.homepage]#" style="margin-top:-6px;white-space:nowrap;">
<img id="greeting-icon" class="yacylogo" src="#[promoteSearchPageGreeting.smallImage]#" alt="#[promoteSearchPageGreeting.imageAlt]#" style="height:auto; width:auto; max-width:200px; max-height:32px;vertical-align:middle;float:left;">&nbsp;
<span id="greeting"></span>
</a>
</div>
<div class="navbar-collapse collapse">
<input type="checkbox" name="search.publicTopNavBar.login" title="Enable login link/status" value="true" #(search.publicTopNavBar.login)#::checked="checked" #(/search.publicTopNavBar.login)# />
<ul class="nav navbar-nav">
<li id="header_login">
<a title="Log in to use extended search features" href="#" onclick="document.getElementById('header_login').className='hidden';document.getElementById('header_login_logged').className='navbar-text';return false;">
<span>Log in</span>
<span class="glyphicon glyphicon-log-in"></span>
</a>
</li>
<li id="header_login_logged" title="You are authenticated as userName" class="navbar-text hidden">
<span class="glyphicon glyphicon-user text-info"></span>
<span>userName</span>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li id="header_search-cfg" class="dropdown">
<a href="#" data-toggle="dropdown" class="dropdown-toggle">Search Interfaces<b class="caret"></b></a>
@@ -62,6 +62,10 @@ public static serverObjects respond(final RequestHeader header, final serverObje
sb.tables.recordAPICall(post, "ConfigPortal_p.html", WorkTables.TABLE_API_TYPE_CONFIGURATION, "new portal design. greeting: " + newGreeting);
sb.setConfig("publicTopmenu", post.getBoolean("publicTopmenu"));
sb.setConfig(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
post.getBoolean(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN));
sb.setConfig("search.options", post.getBoolean("search.options"));
sb.setConfig("search.text", post.getBoolean("search.text"));
@@ -162,6 +166,9 @@ public static serverObjects respond(final RequestHeader header, final serverObje
}
}
sb.setConfig("publicTopmenu", config.getProperty("publicTopmenu","true"));
sb.setConfig(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
config.getProperty(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
Boolean.toString(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT)));
sb.setConfig("search.navigation", config.getProperty("search.navigation","hosts,authors,namespace,topics"));
sb.setConfig("search.options", config.getProperty("search.options","true"));
sb.setConfig("search.text", config.getProperty("search.text","true"));
@@ -204,6 +211,11 @@ public static serverObjects respond(final RequestHeader header, final serverObje
prop.putHTML(SwitchboardConstants.GREETING_IMAGE_ALT, sb.getConfig(SwitchboardConstants.GREETING_IMAGE_ALT, ""));
prop.putHTML(SwitchboardConstants.INDEX_FORWARD, sb.getConfig(SwitchboardConstants.INDEX_FORWARD, ""));
prop.put("publicTopmenu", sb.getConfigBool("publicTopmenu", false) ? 1 : 0);
prop.put(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
sb.getConfigBool(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT) ? 1 : 0);
prop.put("search.options", sb.getConfigBool("search.options", false) ? 1 : 0);
prop.put("search.text", sb.getConfigBool("search.text", false) ? 1 : 0);
@@ -8,11 +8,28 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand hidden-xs" id="navbar-brand" href="#[promoteSearchPageGreeting.homepage]#" style="position:absolute;top:-6px;display:inline;white-space:nowrap;">
<img id="greeting-icon" class="yacylogo" src="#[promoteSearchPageGreeting.smallImage]#" alt="#[promoteSearchPageGreeting.imageAlt]#" style="height:auto; width:auto; max-width:200px; max-height:32px;vertical-align:middle;float:left;">&nbsp;<span id="greeting" style="position:absolute; top:50%;float:left;"></span>
<a class="navbar-brand hidden-xs" id="navbar-brand" href="#[promoteSearchPageGreeting.homepage]#" style="margin-top:-6px;white-space:nowrap;">
<img id="greeting-icon" class="yacylogo" src="#[promoteSearchPageGreeting.smallImage]#" alt="#[promoteSearchPageGreeting.imageAlt]#"
style="height:auto; width:auto; max-width:200px; max-height:32px;vertical-align:middle;float:left;">&nbsp;
<span id="greeting"></span>
</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
#(showLogin)#::
<li id="header_login" title="You are authenticated as #[userName]#" class="navbar-text">
<span class="glyphicon glyphicon-user text-info"></span>
<span>#[userName]#</span>
</li>
::
<li id="header_login">
<a title="Log in to use extended search features" href="#[loginURL]#">
<span>Log in</span>
<span class="glyphicon glyphicon-log-in"></span>
</a>
</li>
#(/showLogin)#
</ul>
<ul class="nav navbar-nav navbar-right">
<li id="header_search" class="dropdown">
<a href="#" data-toggle="dropdown" class="dropdown-toggle" role="button" aria-haspopup="true" aria-expanded="false" title="Search Interfaces">
@@ -101,14 +101,23 @@ public static serverObjects respond(
final Switchboard sb = (Switchboard) env;
sb.localSearchLastAccess = System.currentTimeMillis();
final boolean authorized = sb.verifyAuthentication(header);
final boolean searchAllowed = sb.getConfigBool(SwitchboardConstants.PUBLIC_SEARCHPAGE, true) || authorized;
String authenticatedUserName = null;
final boolean adminAuthenticated = sb.verifyAuthentication(header);
final boolean searchAllowed = sb.getConfigBool(SwitchboardConstants.PUBLIC_SEARCHPAGE, true) || adminAuthenticated;
boolean authenticated = sb.adminAuthenticated(header) >= 2;
if ( !authenticated ) {
boolean extendedSearchRights = adminAuthenticated;
if(adminAuthenticated) {
authenticatedUserName = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin");
}
if (!extendedSearchRights) {
final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null;
authenticated = (user != null && user.hasRight(UserDB.AccessRight.EXTENDED_SEARCH_RIGHT));
if(user != null) {
extendedSearchRights = user.hasRight(UserDB.AccessRight.EXTENDED_SEARCH_RIGHT);
authenticatedUserName = user.getUserName();
}
}
final boolean localhostAccess = header.accessFromLocalhost();
final String promoteSearchPageGreeting =
(env.getConfigBool(SwitchboardConstants.GREETING_NETWORK_NAME, false)) ? env.getConfig(
@@ -118,7 +127,7 @@ public static serverObjects respond(
// in case that the crawler is running and the search user is the peer admin, we expect that the user wants to check recently crawled document
// to ensure that recent crawl results are inside the search results, we do a soft commit here. This is also important for live demos!
if (authenticated && sb.getThread(SwitchboardConstants.CRAWLJOB_LOCAL_CRAWL).getJobCount() > 0) {
if (extendedSearchRights && sb.getThread(SwitchboardConstants.CRAWLJOB_LOCAL_CRAWL).getJobCount() > 0) {
sb.index.fulltext().commit(true);
}
final boolean focus = (post == null) ? true : post.get("focus", "1").equals("1");
@@ -198,7 +207,7 @@ public static serverObjects respond(
return prop;
}
if (post.containsKey("auth") && !authenticated) {
if (post.containsKey("auth") && !extendedSearchRights) {
/*
* Access to authentication protected features is explicitely requested here
* but no authentication is provided : ask now for authentication.
@@ -209,7 +218,7 @@ public static serverObjects respond(
prop.authenticationRequired();
return prop;
}
// check for JSONP
if ( post.containsKey("callback") ) {
final String jsonp = post.get("callback") + "([";
@@ -266,7 +275,7 @@ public static serverObjects respond(
if ( !global ) {
// we count only searches on the local peer here, because global searches
// are counted on the target peer to preserve privacy of the searcher
if ( authenticated ) {
if ( extendedSearchRights ) {
// local or authenticated search requests are counted separately
// because they are not part of a public available peer statistic
sb.searchQueriesRobinsonFromLocal++;
@@ -299,7 +308,7 @@ public static serverObjects respond(
ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: BLACKLISTED CLIENT FROM "
+ client
+ " gets no permission to search");
} else if ( !authenticated && !localhostAccess && !intranetMode ) {
} else if ( !extendedSearchRights && !localhostAccess && !intranetMode ) {
// in case that we do a global search or we want to fetch snippets, we check for DoS cases
synchronized ( trackerHandles ) {
final int accInThreeSeconds =
@@ -659,7 +668,7 @@ public static serverObjects respond(
DigestURL.hosthashess(sb.getConfig("search.excludehosth", "")),
MultiProtocolURL.TLD_any_zone_filter,
client,
authenticated,
extendedSearchRights,
indexSegment,
ranking,
header.get(HeaderFramework.USER_AGENT, ""),
@@ -724,7 +733,7 @@ public static serverObjects respond(
theSearch.resortCachedResults();
}
if ( startRecord == 0 && authenticated && !stealthmode ) {
if ( startRecord == 0 && extendedSearchRights && !stealthmode ) {
if ( modifier.sitehost != null && sb.getConfigBool(SwitchboardConstants.HEURISTIC_SITE, false) ) {
sb.heuristicSite(theSearch, modifier.sitehost);
}
@@ -776,7 +785,7 @@ public static serverObjects respond(
RequestHeader.FileType.HTML,
0,
theQuery,
suggestion, true, authenticated).toString());
suggestion, true, extendedSearchRights).toString());
prop.put("didYouMean_suggestions_" + meanCount + "_sep", "|");
meanCount++;
} catch (final ConcurrentModificationException e) {
@@ -844,7 +853,7 @@ public static serverObjects respond(
prop.put("num-results_globalresults_remoteIndexCount", Formatter.number(theSearch.remote_rwi_available.get() + theSearch.remote_solr_available.get(), true));
prop.put("num-results_globalresults_remotePeerCount", Formatter.number(theSearch.remote_rwi_peerCount.get() + theSearch.remote_solr_peerCount.get(), true));
final boolean jsResort = global && authenticated // for now enable JavaScript resorting only for authenticated users as it requires too much resources per search request
final boolean jsResort = global && extendedSearchRights // for now enable JavaScript resorting only for authenticated users as it requires too much resources per search request
&& (contentdom == ContentDomain.ALL || contentdom == ContentDomain.TEXT) // For now JavaScript resorting can only be applied for text search
&& sb.getConfigBool(SwitchboardConstants.SEARCH_JS_RESORT, SwitchboardConstants.SEARCH_JS_RESORT_DEFAULT);
prop.put("jsResort", jsResort);
@@ -854,7 +863,7 @@ public static serverObjects respond(
* eventually including fetched results with higher ranks from the Solr and RWI stacks */
prop.put("resortEnabled", !jsResort && global && !stealthmode && theSearch.resortCacheAllowed.availablePermits() > 0 ? 1 : 0);
prop.put("resortEnabled_url",
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, authenticated)
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, extendedSearchRights)
.append("&startRecord=").append(startRecord).append("&resortCachedResults=true")
.toString());
@@ -893,8 +902,26 @@ public static serverObjects respond(
prop.put("depth", "0");
prop.put("localQuery", theSearch.query.isLocal() ? "1" : "0");
prop.put("jsResort_localQuery", theSearch.query.isLocal() ? "1" : "0");
final boolean showLogin = sb.getConfigBool(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT);
if(showLogin) {
if(authenticatedUserName != null) {
/* Show the name of the authenticated user */
prop.put("showLogin", 1);
prop.put("showLogin_userName", authenticatedUserName);
} else {
/* Show a login link */
prop.put("showLogin", 2);
prop.put("showLogin_loginURL",
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, true).toString());
}
} else {
prop.put("showLogin", 0);
}
}
prop.put("focus", focus ? 1 : 0); // focus search field
prop.put("searchagain", global ? "1" : "0");
String former = originalquerystring.replaceAll(Segment.catchallString, "*");
@@ -3823,6 +3823,10 @@ public int adminAuthenticated(final RequestHeader requestHeader) {
return 1;
}
/**
* @param header servlet request headers
* @return true when the headers contains valid admin authentication information
*/
public boolean verifyAuthentication(final RequestHeader header) {
// handle access rights
switch ( adminAuthenticated(header) ) {
@@ -552,6 +552,12 @@
/** Default setting value controlling whether search results resorting by browser JavaScript is enabled */
public static final boolean SEARCH_JS_RESORT_DEFAULT = false;
/** Key of the setting controlling whether the search public top navigation bar includes a login link/status */
public static final String SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN = "search.publicTopNavBar.login";
/** Default setting value controlling whether the search public top navigation bar includes a login link/status */
public static final boolean SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT = true;
/** Key of the setting controlling the max lines displayed in standard search navigators/facets */
public static final String SEARCH_NAVIGATION_MAXCOUNT = "search.navigation.maxcount";

2 comments on commit af198b9

@smokingwheels

This comment has been minimized.

smokingwheels replied Oct 23, 2017

Wow

@luccioman

This comment has been minimized.

Member

luccioman replied Oct 24, 2017

Glad to see that you are happy with the recent commits ;)

Please sign in to comment.