Commit f1b381a1 authored by Sebastian's avatar Sebastian

oauth, serverseitige konfiguration der genutzten api.

parent a9f7c2af
......@@ -122,6 +122,11 @@
<version>2.27</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
......@@ -151,6 +156,13 @@
<version>${jersey2.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.scribejava/scribejava-apis -->
<dependency>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-apis</artifactId>
<version>6.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
......@@ -265,14 +277,21 @@
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>de.westnordost</groupId>
<artifactId>osmapi</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>oauth.signpost</groupId>
<artifactId>signpost-core</artifactId>
<version>1.2.1.2</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
<build>
......
......@@ -19,16 +19,18 @@ import io.jsonwebtoken.SignatureAlgorithm;
public class Settings {
public final static String propertiesFile = "geoportal.properties.xml";
private final static String oAuthParametersFile = "OAuthParameters.xml";
private final static String oAuthParametersFile = "OAuthParameters";
private Boolean userRegistrationEnabled = null;
private Boolean debugModeEnabled = null;
private String osmApiUrl = "";
private String overpassApiURL = "";
private static Settings instance = null;
private static OAuthParameters oAuthParameters;
public String inputStreamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
String line;
......@@ -44,9 +46,14 @@ public class Settings {
return this.osmApiUrl;
}
public String getOverpassApiURL() {
return this.overpassApiURL;
}
public OAuthParameters OAuthParameters(){
return Settings.oAuthParameters;
}
}
private Settings() {
InputStream is = getClass().getClassLoader().getResourceAsStream(propertiesFile);
Properties properties = new Properties();
......@@ -56,6 +63,8 @@ public class Settings {
System.out.println("Properties loaded.");
String ureString = (String)properties.getProperty("userRegistration.enabled");
osmApiUrl = (String)properties.getProperty("osm.apiURL");
overpassApiURL = (String)properties.getProperty("overpass.apiURL");
this.userRegistrationEnabled = (ureString.toLowerCase().equals("true"));
String dbgString = (String)properties.getProperty("debug");
this.debugModeEnabled = (ureString.toLowerCase().equals("true"));
......@@ -80,15 +89,18 @@ public class Settings {
}
public static Settings getInstance() {
if(instance == null) {
instance = new Settings();
}
return instance;
}
public Boolean debugMode() {
return this.debugModeEnabled;
}
public Boolean userRegistrationEnabled() {
return this.userRegistrationEnabled;
}
......
......@@ -16,9 +16,14 @@ import java.time.LocalDateTime;
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
......@@ -50,12 +55,20 @@ import de.transformationsstadt.geoportal.DAO.UserDAO;
import de.transformationsstadt.geoportal.apiparameters.KeyValuePairParameter;
import de.transformationsstadt.geoportal.apiparameters.OsmNodeParameter;
import de.transformationsstadt.geoportal.entities.KeyValuePair;
import de.transformationsstadt.geoportal.entities.OAuthToken;
import de.transformationsstadt.geoportal.entities.OsmElementType;
import de.transformationsstadt.geoportal.entities.OsmReference;
import de.transformationsstadt.geoportal.entities.Rectangle;
import de.transformationsstadt.geoportal.entities.User;
import de.transformationsstadt.geoportal.services.KeyValuePairService;
import de.transformationsstadt.geoportal.services.OAuthTokenService;
import de.transformationsstadt.geoportal.services.OsmReferenceService;
import de.transformationsstadt.geoportal.services.UserService;
import de.westnordost.osmapi.OsmConnection;
import de.westnordost.osmapi.map.MapDataDao;
import de.westnordost.osmapi.map.data.Element;
import de.westnordost.osmapi.map.data.Node;
import de.westnordost.osmapi.user.UserDao;
@Path("/GeoElements/")
public class GeoElements {
......@@ -472,15 +485,23 @@ public class GeoElements {
Subject subject = SecurityUtils.getSubject();
System.out.println((String)subject.getPrincipal());
if(!subject.isAuthenticated()) {
return Response.status(Status.FORBIDDEN).entity("{error:\"you need to be logged in to proceed\"}").build();
}
OsmReference existingNode = osmRefService.get(id);
if(existingNode == null) {
return Response.status(Status.NOT_FOUND).entity("{error:\"I know of no item with this id\"}").build();
}else {
}else{
OsmReference node = osmRefService.update(existingNode, osmnode);
if(node != null) {
User currentUser = userService.getCurrentUser();
if(currentUser != null && tokenService.getTokenForUser(currentUser)!=null && osmnode != null) {
this.updateOsmNode(osmnode,currentUser);
}
return Response.status(Status.OK).entity(node).build();
}else {
return Response.status(Status.BAD_REQUEST).entity(null).build();
......@@ -488,8 +509,6 @@ public class GeoElements {
}
}
/**
* Gibt alle (!) Elemente aus der Datenbank zurück.
*
......@@ -505,6 +524,15 @@ public class GeoElements {
return Response.status(Status.OK).entity(elements).build();
}
@GET
@Path("/AvailableOsmTags/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getAvailableOsmTags(){
return Response.status(Status.OK).entity(validOsmTags()).build();
}
/**
* Gibt die EdgeList zurück
......@@ -543,4 +571,138 @@ public class GeoElements {
return Response.status(Status.OK).entity(result).build();
}
@Autowired
OAuthTokenService tokenService;
public void updateOsmNode(OsmNodeParameter r, User user){
OAuthToken t = tokenService.getFirstTokenForUser(user);
if(t == null) {
System.out.println("Got no token for this user...");
return;
}
OsmConnection con = t.getOsmConnection();
UserDao ud = new UserDao(con);
ud.getMine();
MapDataDao mdd = new MapDataDao(con);
Element el = null;
switch(r.getOsmElementType()) {
case NODE:{
el = mdd.getNode(r.getOsmId());
break;
}
case WAY:{
el = mdd.getWay(r.getOsmId());
break;
}
default:
return;
}
el = applyChanges(r, el);
if(el == null) {
return;
}
ArrayList<Element> elements = new ArrayList<Element>();
elements.add(el);
System.out.println("Changing "+el.getId());
for (Map.Entry<String, String> entry : el.getTags().entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
Long changeSetId = mdd.updateMap("transformationsstadt", "", elements, null);
}
private Element applyChanges(OsmNodeParameter ref, Element osmElement) {
List<String> consideredTags = validOsmTags();
ArrayList<KeyValuePairParameter> deletedTags = new ArrayList<KeyValuePairParameter>();
ArrayList<KeyValuePairParameter> newTags = new ArrayList<KeyValuePairParameter>();
ArrayList<KeyValuePairParameter> changedTags = new ArrayList<KeyValuePairParameter>();
Map<String,String> osmTags = osmElement.getTags();
ArrayList<KeyValuePairParameter> refTags = (ArrayList<KeyValuePairParameter>)ref.getOsmTags();
for(KeyValuePairParameter refTag : refTags) {
if(!consideredTags.contains(refTag.key)) {
continue;
}
if(osmTags.containsKey(refTag.key)){
if(!osmTags.get(refTag.key).equals(refTag.value)) {
System.out.println("Changed: "+refTag.key);
changedTags.add(refTag);
}else {
System.out.println("Unchanged: "+refTag.key );
}
}else {
System.out.println("New: "+refTag.key);
newTags.add(refTag);
}
}
Iterator<Entry<String, String>> it = osmTags.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String,String> pair = (Map.Entry<String,String>)it.next();
String key = (String)pair.getKey();
if(!consideredTags.contains(key)) {
continue;
}
String value = (String)pair.getValue();
Boolean found = false;
for(KeyValuePairParameter refTag : refTags) {
if(refTag.key == null) {
System.out.println("reftag.key is null");
}
if(key == null) {
System.out.println("key is null");
}
if(refTag.key.equals(key)) {
found=true;
continue;
}
}
if(!found) {
KeyValuePairParameter deleteMe = new KeyValuePairParameter();
deleteMe.key = key;
deleteMe.value = value;
System.out.println("Removed: "+key);
deletedTags.add(deleteMe);
}
it.remove(); // avoids a ConcurrentModificationException
}
if(deletedTags.isEmpty() && changedTags.isEmpty() && newTags.isEmpty()) {
return null;
}
if(!deletedTags.isEmpty()) {
for(KeyValuePairParameter kvp : deletedTags) {
osmElement.getTags().remove(kvp.key);
System.out.println("Removing: "+kvp.key);
}
}
if(!newTags.isEmpty()) {
for(KeyValuePairParameter kvp : newTags) {
osmElement.getTags().put(kvp.key,kvp.value);
System.out.println("Adding "+kvp.key);
}
}
if(!changedTags.isEmpty()) {
for(KeyValuePairParameter kvp : changedTags) {
osmElement.getTags().put(kvp.key,kvp.value);
System.out.println("Changing "+kvp.key);
}
}
return osmElement;
}
private List<String> validOsmTags(){
return Arrays.asList("name", "source", "addr:country","addr:street","addr:housenumber","addr:postcode","addr:city","email","opening_hours","start_date","operator:type");
}
}
......@@ -142,14 +142,9 @@ public class OAuth {
System.out.println("Error: token has no accesstoken.");
return null;
}
OAuthConsumer consumer = t.getSignPostConsumer();
System.out.println("Consumer created: "+consumer.getConsumerKey()+" / "+consumer.getConsumerSecret());
//https://github.com/westnordost/osmapi
try {
OsmConnection osm = new OsmConnection(
osmApi,
"Geoportal",
consumer);
OsmConnection osm = t.getOsmConnection();
UserDetails user = new UserDao(osm).getMine();
String localUsername = "osm:"+(new Long(user.id)).toString();
User gpUser = userService.getUser(localUsername);
......@@ -160,8 +155,9 @@ public class OAuth {
gpUser.setActive(true);
gpUser.setValidated(true);
gpUser.setDescription(user.displayName);
gpUser = userService.create(gpUser);
gpUser = userService.create(gpUser);
System.out.println("Created: "+localUsername);
}
t.setUser(gpUser);
tokenService.update(t);
......@@ -172,10 +168,6 @@ public class OAuth {
}catch(Exception e) {
System.out.println("Error getting user: "+e.getMessage()+ " on "+osmApi);
System.out.println("ConsumerKey:"+consumer.getConsumerKey());
System.out.println("ConsumerSecret:"+consumer.getConsumerSecret());
System.out.println("ACCESS_TOKEN:"+consumer.getToken());
System.out.println("ACCESS_SECRET:"+consumer.getTokenSecret());
return null;
}
......@@ -229,7 +221,18 @@ public class OAuth {
URI frontend = null;
if(t.getOauthTokenVerifier() != null && !t.getOauthTokenVerifier().isEmpty()) {
try {
getUserCredentials(t);
User user = getUserCredentials(t);
if(user == null) {
return Response.status(Status.UNAUTHORIZED).entity("{\"error\":\"unauthorized.\"}").build();
}else {
System.out.println("###############################");
System.out.println("###############################");
System.out.println("###############################");
System.out.println("Created user: "+user.getDescription());
System.out.println("###############################");
System.out.println("###############################");
System.out.println("###############################");
}
frontend = new URI("http", null, "localhost", 4200, "", null, "/login;rt="+t.getOauthToken());
//return Response.temporaryRedirect(frontend).build();
return Response.temporaryRedirect(frontend).build();
......@@ -239,9 +242,6 @@ public class OAuth {
}
t.setOauthTokenVerifier(oauth_verifier);
HashMap<String,String> ret = new HashMap<String,String>();
ret.put("oauth_token",oauth_token);
......@@ -314,4 +314,67 @@ public class OAuth {
return Response.status(Status.OK).entity(api.getOAuthParameters()).build();
}
private boolean tokenActive(OAuthToken t) {
OsmConnection osm = t.getOsmConnection();
try{
new UserDao(osm).getMine();
return true;
}catch(Exception e) {
System.out.println("Token invalid: "+t.getId());
return false;
}
}
public Response cleanTokens(User user) {
HashMap<String,String> response = new HashMap<String,String>();
ArrayList<OAuthToken> tokens = (ArrayList<OAuthToken>)tokenService.getTokenForUser(user.getId());
response.put("checkedTokens", (new Integer(tokens.size())).toString());
Integer validTokens = 0;
Integer invalidTokens = 0;
for(OAuthToken token: tokens) {
if(tokenActive(token)) {
validTokens++;
System.out.println("Checked token, is valid: "+token.getId());
}else {
invalidTokens++;
tokenService.delete(token);
System.out.println("Checked token, is invalid: "+token.getId());
}
}
response.put("valid", validTokens.toString());
response.put("invalid", invalidTokens.toString());
return Response.status(Status.OK).entity(response).build();
}
@GET
@Path("/cleanTokens/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response cleanTokens() {
HashMap<String,String> response = new HashMap<String,String>();
ArrayList<OAuthToken> tokens = (ArrayList<OAuthToken>)tokenService.getAll();
response.put("checkedTokens", (new Integer(tokens.size())).toString());
Integer validTokens = 0;
Integer invalidTokens = 0;
for(OAuthToken token: tokens) {
if(tokenActive(token)) {
validTokens++;
System.out.println("Checked token, is valid: "+token.getId());
}else {
invalidTokens++;
tokenService.delete(token);
System.out.println("Checked token, is invalid: "+token.getId());
}
}
response.put("valid", validTokens.toString());
response.put("invalid", invalidTokens.toString());
return Response.status(Status.OK).entity(response).build();
}
}
package de.transformationsstadt.geoportal.api;
import java.util.HashMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import de.transformationsstadt.geoportal.Settings;
@Path("/parameters/")
public class Parameters {
@GET
@Path("overpass_api_url")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getOverPassApiUrl() {
HashMap<String,String> arr = new HashMap<String,String>();
arr.put("overpass_api_url", Settings.getInstance().getOverpassApiURL());
return Response.status(Status.OK).entity(arr).build();
}
@GET
@Path("osm_api_url")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getOsmApiURL() {
HashMap<String,String> arr = new HashMap<String,String>();
arr.put("osm_api_url", Settings.getInstance().getOsmApiURL());
return Response.status(Status.OK).entity(arr).build();
}
}
package de.transformationsstadt.geoportal.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.springframework.beans.factory.annotation.Autowired;
import de.transformationsstadt.geoportal.apiparameters.KeyValuePairParameter;
import de.transformationsstadt.geoportal.apiparameters.OsmNodeParameter;
import de.transformationsstadt.geoportal.entities.OAuthToken;
import de.transformationsstadt.geoportal.services.OAuthTokenService;
import de.westnordost.osmapi.OsmConnection;
import de.westnordost.osmapi.map.MapDataDao;
import de.westnordost.osmapi.map.data.Node;
import de.westnordost.osmapi.map.data.Element;
import de.westnordost.osmapi.user.UserDao;
@Path("/playground/")
public class Playground {
@Autowired
OAuthTokenService tokenService;
private List<String> validOsmTags(){
return Arrays.asList("name", "source", "addr:country","addr:street","addr:housenumber","addr:postcode","addr:city","email","opening_hours","start_date","operator:type");
}
@GET
@Path("/test/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getNodeFromOSMApi() {
OAuthToken t = tokenService.getAll().get(0);
OsmConnection con = t.getOsmConnection();
UserDao ud = new UserDao(con);
ud.getMine();
MapDataDao mdd = new MapDataDao(con);
Node node = mdd.getNode(28);
node.getTags().put("addr:city", "anywhere");
ArrayList<Element> elements = new ArrayList<Element>();
elements.add(node);
//Long changeSetId = mdd.updateMap("test update", "test", elements, null);
return Response.status(Status.OK).entity(node).build();
}
}
......@@ -84,10 +84,10 @@ public class OsmNodeParameter {
public void setOsmId(Long osmId) {
this.osmId = osmId;
}
public List<KeyValuePairParameter> getOsmtags() {
public List<KeyValuePairParameter> getOsmTags() {
return osmtags;
}
public void setOsmtags(List<KeyValuePairParameter> osmtags) {
public void setOsmTags(List<KeyValuePairParameter> osmtags) {
this.osmtags = osmtags;
}
public List<KeyValuePairParameter> getTags() {
......@@ -142,7 +142,10 @@ public class OsmNodeParameter {
String name;
List<BliDimensionParameter> dimensions = new ArrayList<BliDimensionParameter>();
public List<DataGroupParameter> dataGroups = new ArrayList<DataGroupParameter>();
public OsmElementType getOsmElementType() {
if(this.osmType == null) {
System.out.println("OsmType was null on "+this.getName());
......@@ -159,15 +162,19 @@ public class OsmNodeParameter {
}
return OsmElementType.UNSET;
}
public Long getMapId() {
return mapId;
}
public void setMapId(Long mapId) {
this.mapId = mapId;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
......
......@@ -20,8 +20,10 @@ import org.hibernate.annotations.CreationTimestamp;
import com.github.scribejava.core.model.OAuth1AccessToken;
import de.transformationsstadt.geoportal.Settings;
import de.transformationsstadt.geoportal.auth.oauth.ConfiguredOAuthApi10a;
import de.transformationsstadt.geoportal.config.OAuthParameters;
import de.westnordost.osmapi.OsmConnection;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.basic.DefaultOAuthConsumer;
import oauth.signpost.signature.OAuthMessageSigner;
......@@ -134,4 +136,13 @@ public class OAuthToken implements Serializable{
this.accessTokenSecret = accessTokenSecret;
}
public OsmConnection getOsmConnection() {
final String osmApi = Settings.getInstance().getOsmApiURL();
OAuthConsumer consumer = getSignPostConsumer();
OsmConnection osm = new OsmConnection(
osmApi,
"Geoportal",
consumer);
return osm;
}
}
package de.transformationsstadt.geoportal.entities;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
......@@ -32,6 +33,7 @@ import com.fasterxml.jackson.annotation.JsonManagedReference;
import de.transformationsstadt.geoportal.DAO.RoleDAO;
import de.transformationsstadt.geoportal.apiparameters.UserParameters;
import de.transformationsstadt.geoportal.services.OAuthTokenService;
import de.transformationsstadt.geoportal.services.RoleService;
/**
......@@ -524,4 +526,5 @@ public class User implements Serializable{
return Long.hashCode(this.getId());
}
}
......@@ -17,6 +17,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import antlr.collections.List;
import de.transformationsstadt.geoportal.Settings;
import de.transformationsstadt.geoportal.SpringContextProvider;
import de.transformationsstadt.geoportal.entities.OsmElementType;
import de.transformationsstadt.geoportal.entities.OsmReference;
......@@ -41,8 +42,14 @@ public class Overpass {
}
public Overpass() {
}