Skip to content
This repository has been archived by the owner on Feb 12, 2023. It is now read-only.

Commit

Permalink
Merge pull request #462 from ggalmazor/issue_461_backport_460
Browse files Browse the repository at this point in the history
Issue 461 backport 460
  • Loading branch information
ggalmazor authored Apr 23, 2019
2 parents fa98449 + 9c9cf89 commit 7f71148
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 102 deletions.
30 changes: 14 additions & 16 deletions src/main/java/org/opendatakit/aggregate/client/LayoutUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,14 @@
import static org.opendatakit.aggregate.buildconfig.BuildConfig.VERSION;

import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.UIObject;

public class LayoutUtils {
private static String latestVersion;

static native String getLatestVersion() /*-{
var req = new XMLHttpRequest();
req.open('GET', 'https://api.github.com/repos/opendatakit/aggregate/releases/latest', false);
req.send(null);
if (req.readyState === 4 && req.status === 200)
return JSON.parse(req.responseText).tag_name;
}-*/;

static HTML buildVersionNote(UIObject parent) {
if (latestVersion == null)
latestVersion = getLatestVersion();
String shortVersion = VERSION.contains("-") ? VERSION.substring(0, VERSION.indexOf("-")) : VERSION;
String versionNote = shortVersion.equals(latestVersion)
? "You're up to date!"
: "<a href=\"https://github.com/opendatakit/aggregate/releases/latest\" target=\"_blank\">Update available</a>";
HTML html = new HTML("<small>" + shortVersion + " - " + versionNote + "</small>");
HTML html = new HTML("<small>" + shortVersion + " - Checking versions...</small>");
Style style = html.getElement().getStyle();
style.setProperty("position", "fixed");
style.setProperty("bottom", "0");
Expand All @@ -35,6 +21,18 @@ static HTML buildVersionNote(UIObject parent) {
Style parentStyle = parent.getElement().getStyle();
parentStyle.setProperty("paddingBottom", "40px");

SecureGWT.getPreferenceService().getVersioNote(new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
html.setHTML("<small>" + shortVersion + " - Version check failed</small>");
}

@Override
public void onSuccess(String versionNote) {
html.setHTML("<small>" + versionNote + "</small>");
}
});

return html;
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,49 @@
/*
* Copyright (C) 2011 University of Washington
*
* 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.
*/

package org.opendatakit.aggregate.client.preferences;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.google.gwt.user.server.rpc.XsrfProtect;
import org.opendatakit.aggregate.client.exception.RequestFailureException;
import org.opendatakit.common.persistence.client.exception.DatastoreFailureException;
import org.opendatakit.common.security.client.exception.AccessDeniedException;

/**
* These actions require the ROLE_USER privilege, which is the least capable
* privilege (granted to all authorized users of the system).
*
* @author [email protected]
*/
@RemoteServiceRelativePath("preferenceservice")
public interface PreferenceService extends RemoteService {
PreferenceSummary getPreferences() throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setSkipMalformedSubmissions(Boolean skipMalformedSubmissions) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setFasterBackgroundActionsDisabled(Boolean disabled) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setOdkTablesEnabled(Boolean enabled) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setOdkAppName(String appName) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;
}
/*
* Copyright (C) 2011 University of Washington
*
* 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.
*/

package org.opendatakit.aggregate.client.preferences;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.google.gwt.user.server.rpc.XsrfProtect;
import org.opendatakit.aggregate.client.exception.RequestFailureException;
import org.opendatakit.common.persistence.client.exception.DatastoreFailureException;
import org.opendatakit.common.security.client.exception.AccessDeniedException;

/**
* These actions require the ROLE_USER privilege, which is the least capable
* privilege (granted to all authorized users of the system).
*
* @author [email protected]
*/
@RemoteServiceRelativePath("preferenceservice")
public interface PreferenceService extends RemoteService {
PreferenceSummary getPreferences() throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setSkipMalformedSubmissions(Boolean skipMalformedSubmissions) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setFasterBackgroundActionsDisabled(Boolean disabled) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setOdkTablesEnabled(Boolean enabled) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

@XsrfProtect
void setOdkAppName(String appName) throws AccessDeniedException, RequestFailureException, DatastoreFailureException;

String getVersioNote();
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
/*
* Copyright (C) 2011 University of Washington
*
* 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.
*/

package org.opendatakit.aggregate.client.preferences;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface PreferenceServiceAsync {

void getPreferences(AsyncCallback<PreferenceSummary> callback);

void setOdkTablesEnabled(Boolean enabled, AsyncCallback<Void> callback);

void setFasterBackgroundActionsDisabled(Boolean disabled, AsyncCallback<Void> callback);

void setOdkAppName(String appName, AsyncCallback<Void> callback);

void setSkipMalformedSubmissions(Boolean skipMalformedSubmissions, AsyncCallback<Void> callback);

}
/*
* Copyright (C) 2011 University of Washington
*
* 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.
*/

package org.opendatakit.aggregate.client.preferences;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface PreferenceServiceAsync {

void getPreferences(AsyncCallback<PreferenceSummary> callback);

void setOdkTablesEnabled(Boolean enabled, AsyncCallback<Void> callback);

void setFasterBackgroundActionsDisabled(Boolean disabled, AsyncCallback<Void> callback);

void setOdkAppName(String appName, AsyncCallback<Void> callback);

void setSkipMalformedSubmissions(Boolean skipMalformedSubmissions, AsyncCallback<Void> callback);

void getVersioNote(AsyncCallback<String> callback);

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,20 @@

package org.opendatakit.aggregate.server;

import javax.servlet.http.HttpServletRequest;
import static org.opendatakit.aggregate.buildconfig.BuildConfig.VERSION;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import org.opendatakit.aggregate.ContextFactory;
import org.opendatakit.aggregate.client.exception.RequestFailureException;
import org.opendatakit.aggregate.client.preferences.PreferenceSummary;
Expand All @@ -31,17 +41,35 @@
import org.opendatakit.common.persistence.exception.ODKOverQuotaException;
import org.opendatakit.common.security.client.exception.AccessDeniedException;
import org.opendatakit.common.web.CallingContext;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PreferenceServiceImpl extends RemoteServiceServlet implements
org.opendatakit.aggregate.client.preferences.PreferenceService {

private static final Logger log = LoggerFactory.getLogger(PreferenceServiceImpl.class);
/**
* Holds the latest available version as reported by GitHub
*/
private static String LATEST_AVAILABLE_VERSION = null;
/**
* Defines the period to refresh the latest available version value
*/
private static final Duration PERIOD_OF_REFRESH_LATEST_AVAILABLE_VERSION = Duration.ofDays(1);
/**
* Holds the date of the last refresh of the latest available version.
* <p>
* On launch, holds a remote date in the past to ensure that we will
* refresh the value even if the first request comes before the set
* period has passed since the server's launch.
*/
private static LocalDate LAST_REFRESH_OF_LATEST_AVAILABLE_VERSION = LocalDate.of(2000, 1, 1);

/**
* Serialization Identifier
*/
private static final long serialVersionUID = -489283284844600170L;
public static final ObjectMapper JSON = new ObjectMapper();

@Override
public PreferenceSummary getPreferences() throws AccessDeniedException, RequestFailureException,
Expand Down Expand Up @@ -147,4 +175,44 @@ public void setSkipMalformedSubmissions(Boolean skipMalformedSubmissions)
}

}

@Override
public String getVersioNote() {
String shortVersion = VERSION.contains("-") ? VERSION.substring(0, VERSION.indexOf("-")) : VERSION;
String latestAvailableVersion = getLatestAvailableVersion();
return latestAvailableVersion == null
? shortVersion + " - Version check failed"
: shortVersion.equals(latestAvailableVersion)
? shortVersion + " - You're up to date!"
: shortVersion + " - <a href=\"https://github.com/opendatakit/aggregate/releases/latest\" target=\"_blank\">Update available</a>";
}

synchronized private static String getLatestAvailableVersion() {
if (latestAvailableVersionRefreshRequired()) {
try {
log.warn("Getting latest available version");
URL url = new URL("https://api.github.com/repos/opendatakit/aggregate/releases/latest");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
if (con.getResponseCode() == 200)
try (InputStream in = con.getInputStream()) {
LATEST_AVAILABLE_VERSION = Optional.ofNullable(JSON.readTree(in))
.map(node -> node.get("tag_name"))
.map(JsonNode::asText)
.orElse(null);
}
else
log.error("Can't get latest available version - GitHub responded with HTTP " + con.getResponseCode() + " " + con.getResponseMessage());
LAST_REFRESH_OF_LATEST_AVAILABLE_VERSION = LocalDate.now();
} catch (IOException e) {
log.error("Can't get latest available version", e);
}
}
return LATEST_AVAILABLE_VERSION;
}

private static boolean latestAvailableVersionRefreshRequired() {
return Duration.between(LAST_REFRESH_OF_LATEST_AVAILABLE_VERSION.atStartOfDay(), LocalDateTime.now()).abs()
.compareTo(PERIOD_OF_REFRESH_LATEST_AVAILABLE_VERSION) > 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class AggregateHtmlServlet extends ServletUtilBase {
+ " <script type=\"text/javascript\" language=\"javascript\" src=\"javascript/main.js\"></script>"
+ " <script type=\"text/javascript\" language=\"javascript\" src=\"aggregateui/aggregateui.nocache.js\"></script>"
+ " <script type=\"text/javascript\" language=\"javascript\" src=\"https://maps.googleapis.com/maps/api/js?";
public static final String PAGE_CONTENTS_SECOND = "sensor=false\"></script>"
public static final String PAGE_CONTENTS_SECOND = "sensor=false\" async></script>"
+ " <link type=\"text/css\" rel=\"stylesheet\" href=\"AggregateUI.css\">"
+ " <link type=\"text/css\" rel=\"stylesheet\" href=\"stylesheets/button.css\">"
+ " <link type=\"text/css\" rel=\"stylesheet\" href=\"stylesheets/table.css\">"
Expand Down

0 comments on commit 7f71148

Please sign in to comment.