Skip to content
Snippets Groups Projects
Commit e0c0ceb2 authored by Félix  Sidokhine's avatar Félix Sidokhine Committed by Adrien Béraud
Browse files

contacts: add sync API

Change-Id: Icc8d3fc629dfc8ea7ffac2b99dc70242e9919f57
parent 3559af4b
No related branches found
No related tags found
No related merge requests found
Showing
with 321 additions and 72 deletions
/* /*
* Copyright (C) 2020 by Savoir-faire Linux * Copyright (C) 2020 by Savoir-faire Linux
* Authors: William Enright <william.enright@savoirfairelinux.com> * Authors: William Enright <william.enright@savoirfairelinux.com>
* Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com> * Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
* Johnny Flores <johnny.flores@savoirfairelinux.com> * Johnny Flores <johnny.flores@savoirfairelinux.com>
* Mohammed Raza <mohammed.raza@savoirfairelinux.com> * Mohammed Raza <mohammed.raza@savoirfairelinux.com>
* Felix Sidokhine <felix.sidokhine@savoirfairelinux.com> * Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
* *
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.jami.datastore.dao; package net.jami.datastore.dao;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -29,6 +30,7 @@ import net.jami.jams.common.objects.contacts.Contact; ...@@ -29,6 +30,7 @@ import net.jami.jams.common.objects.contacts.Contact;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
@Slf4j @Slf4j
public class ContactDao extends AbstractDao<Contact> { public class ContactDao extends AbstractDao<Contact> {
...@@ -41,35 +43,57 @@ public class ContactDao extends AbstractDao<Contact> { ...@@ -41,35 +43,57 @@ public class ContactDao extends AbstractDao<Contact> {
String createTable = "CREATE TABLE contacts (" + String createTable = "CREATE TABLE contacts (" +
"owner varchar(255), " + "owner varchar(255), " +
"uri varchar(255)," + "uri varchar(255)," +
"displayName varchar(255),"+ "displayName varchar(255)," +
"`timestamp` bigint," +
"status int," +
"PRIMARY KEY (owner,uri))"; "PRIMARY KEY (owner,uri))";
PreparedStatement ps = connection.getConnection().prepareStatement(createTable); PreparedStatement ps = connection.getConnection().prepareStatement(createTable);
ps.execute(); ps.execute();
} } catch (SQLException e) {
catch (SQLException e){
log.error("Could not create the contacts table with error " + e.getMessage()); log.error("Could not create the contacts table with error " + e.getMessage());
} } finally {
finally {
DataStore.connectionPool.returnConnection(connection); DataStore.connectionPool.returnConnection(connection);
} }
} }
//Not used because the strategy here is different.
@Override @Override
public boolean storeObject(Contact object) { public boolean storeObject(Contact object) {
SQLConnection connection = DataStore.connectionPool.getConnection(); SQLConnection connection = DataStore.connectionPool.getConnection();
try{ try {
PreparedStatement ps = connection.getConnection().prepareStatement("INSERT INTO contacts " + String insert = "INSERT INTO contacts (owner, uri, displayName, `timestamp`, status) VALUES " +
"(owner, uri, displayName) " + "(?, ?, ?, ?, ?)";
"VALUES " + PreparedStatement ps = connection.getConnection().prepareStatement(insert);
"(?, ?, ?)"); object.getInsert(ps);
ps = object.getInsert(ps); ps.executeQuery();
return ps.executeUpdate() != 0; return true;
} } catch (Exception e) {
catch (Exception e){ log.error("Could not update contacts!");
log.error("An error has occurred while trying to store a user: " + e.toString());
return false; return false;
} finally {
DataStore.connectionPool.returnConnection(connection);
} }
finally { }
public boolean storeContactList(List<Contact> contactList) {
SQLConnection connection = DataStore.connectionPool.getConnection();
try {
String delete = "DELETE FROM contacts WHERE owner = ?";
PreparedStatement ps = connection.getConnection().prepareStatement(delete);
ps.setString(1, contactList.get(0).getOwner());
ps.executeQuery();
String insert = "INSERT INTO contacts (owner, uri, displayName, `timestamp`, status) VALUES " +
"(?, ?, ?, ?, ?)";
for (Contact contact : contactList) {
ps = connection.getConnection().prepareStatement(insert);
contact.getInsert(ps);
ps.executeQuery();
}
return true;
} catch (Exception e) {
log.error("Could not update contacts!");
return false;
} finally {
DataStore.connectionPool.returnConnection(connection); DataStore.connectionPool.returnConnection(connection);
} }
} }
......
/* /*
* Copyright (C) 2020 by Savoir-faire Linux * Copyright (C) 2020 by Savoir-faire Linux
* Authors: William Enright <william.enright@savoirfairelinux.com> * Authors: William Enright <william.enright@savoirfairelinux.com>
* Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com> * Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
* Johnny Flores <johnny.flores@savoirfairelinux.com> * Johnny Flores <johnny.flores@savoirfairelinux.com>
* Mohammed Raza <mohammed.raza@savoirfairelinux.com> * Mohammed Raza <mohammed.raza@savoirfairelinux.com>
* Felix Sidokhine <felix.sidokhine@savoirfairelinux.com> * Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
* *
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.jami.jams.common.objects.contacts; package net.jami.jams.common.objects.contacts;
import com.jsoniter.annotation.JsonIgnore; import com.jsoniter.annotation.JsonIgnore;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
...@@ -34,24 +36,32 @@ import java.sql.ResultSet; ...@@ -34,24 +36,32 @@ import java.sql.ResultSet;
@Getter @Getter
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode
public class Contact implements DatabaseObject { public class Contact implements DatabaseObject {
@JsonIgnore //Ignore the owner because he is irrelevant. @JsonIgnore //Ignore the owner because he is irrelevant.
private String owner; private String owner;
private String uri; private String uri;
private String displayName; private String displayName;
private Long timestamp;
private Character status; //A = added, D = deleted.
public Contact(ResultSet rs) throws Exception { public Contact(ResultSet rs) throws Exception {
this.owner = rs.getString("owner"); this.owner = rs.getString("owner");
this.uri = rs.getString("uri"); this.uri = rs.getString("uri");
this.displayName = rs.getString("displayName"); this.displayName = rs.getString("displayName");
this.timestamp = rs.getLong("timestamp");
this.status = (char) rs.getInt("status");
} }
@Override @Override
public PreparedStatement getInsert(PreparedStatement ps) throws Exception { public PreparedStatement getInsert(PreparedStatement ps) throws Exception {
ps.setString(1,owner); ps.setString(1, owner);
ps.setString(2,uri); ps.setString(2, uri);
ps.setString(3,displayName); if(displayName != null) ps.setString(3, displayName);
else ps.setString(3, "");
ps.setLong(4,timestamp);
ps.setInt(5,status);
return ps; return ps;
} }
......
...@@ -27,11 +27,13 @@ import com.jsoniter.output.EncodingMode; ...@@ -27,11 +27,13 @@ import com.jsoniter.output.EncodingMode;
import com.jsoniter.output.JsonStream; import com.jsoniter.output.JsonStream;
import com.jsoniter.spi.DecodingMode; import com.jsoniter.spi.DecodingMode;
import com.jsoniter.spi.JsoniterSpi; import com.jsoniter.spi.JsoniterSpi;
import net.jami.jams.common.objects.contacts.Contact;
import net.jami.jams.common.serialization.decoders.CSRDecoder; import net.jami.jams.common.serialization.decoders.CSRDecoder;
import net.jami.jams.common.serialization.decoders.PrivateKeyDecoder; import net.jami.jams.common.serialization.decoders.PrivateKeyDecoder;
import net.jami.jams.common.serialization.decoders.X509CertificateDecoder; import net.jami.jams.common.serialization.decoders.X509CertificateDecoder;
import net.jami.jams.common.serialization.encoders.PrivateKeyEncoder; import net.jami.jams.common.serialization.encoders.PrivateKeyEncoder;
import net.jami.jams.common.serialization.encoders.X509CertificateEncoder; import net.jami.jams.common.serialization.encoders.X509CertificateEncoder;
import net.jami.jams.common.serialization.serializers.ContactCodec;
import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import java.security.PrivateKey; import java.security.PrivateKey;
...@@ -47,6 +49,8 @@ public class JsoniterRegistry { ...@@ -47,6 +49,8 @@ public class JsoniterRegistry {
JsoniterSpi.registerTypeEncoder(X509Certificate.class,new X509CertificateEncoder()); JsoniterSpi.registerTypeEncoder(X509Certificate.class,new X509CertificateEncoder());
JsoniterSpi.registerTypeEncoder(PrivateKey.class,new PrivateKeyEncoder()); JsoniterSpi.registerTypeEncoder(PrivateKey.class,new PrivateKeyEncoder());
JsoniterSpi.registerTypeDecoder(PKCS10CertificationRequest.class,new CSRDecoder()); JsoniterSpi.registerTypeDecoder(PKCS10CertificationRequest.class,new CSRDecoder());
JsoniterSpi.registerTypeEncoder(Contact.class,new ContactCodec());
JsoniterSpi.registerTypeDecoder(Contact.class,new ContactCodec());
} }
......
package net.jami.jams.common.serialization.serializers;
import com.jsoniter.JsonIterator;
import com.jsoniter.any.Any;
import com.jsoniter.output.JsonStream;
import com.jsoniter.spi.Decoder;
import com.jsoniter.spi.Encoder;
import net.jami.jams.common.objects.contacts.Contact;
import java.io.IOException;
public class ContactCodec implements Encoder, Decoder {
@Override
public Object decode(JsonIterator jsonIterator) throws IOException {
Any input = jsonIterator.readAny();
Contact contact = new Contact();
contact.setUri(input.get("uri").toString());
if(!input.get("added").toString().isBlank()){
contact.setStatus('A');
contact.setTimestamp(input.get("added").toLong());
}
else{
contact.setStatus('D');
contact.setTimestamp(input.get("removed").toLong());
}
return contact;
}
@Override
public void encode(Object o, JsonStream jsonStream) throws IOException {
Contact ct = (Contact) o;
StringBuilder sb = new StringBuilder();
sb.append("{\"uri\":\"").append(ct.getUri()).append("\",");
switch (ct.getStatus()){
case 'A': sb.append("\"added\":").append(ct.getTimestamp()); break;
case 'D': sb.append("\"removed\":").append(ct.getTimestamp()); break;
}
sb.append("}");
jsonStream.write(sb.toString().getBytes());
}
}
package net.jami.jams.common.utils;
import net.jami.jams.common.objects.contacts.Contact;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
public class ContactMerger {
public static List<Contact> mergeContacts(List<Contact> remote, List<Contact> local){
//uri - [remote,local]
List<Contact> output = new ArrayList<>();
final HashMap<String,Contact[]> contactMap = new HashMap<>();
remote.sort(Comparator.comparingLong(Contact::getTimestamp));
remote.forEach(contact -> {
contactMap.putIfAbsent(contact.getUri(),new Contact[]{null,null});
contactMap.get(contact.getUri())[0] = contact;
});
local.forEach(contact -> {
contactMap.putIfAbsent(contact.getUri(),new Contact[]{null,null});
contactMap.get(contact.getUri())[1] = contact;
});
contactMap.forEach((k,v) -> {
if(v[0] == null) output.add(v[1]);
else if(v[1] == null) output.add(v[0]);
else {
//Compare by date an choose the proper one
if(v[0].getTimestamp() > v[1].getTimestamp()) output.add(v[0]);
else output.add(v[1]);
}
});
return output;
}
}
package net.jami.jams.common.objects.contacts;
import com.jsoniter.JsonIterator;
import com.jsoniter.output.JsonStream;
import com.jsoniter.spi.JsoniterSpi;
import net.jami.jams.common.serialization.serializers.ContactCodec;
import net.jami.jams.common.utils.ContactMerger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class ContactTest {
@BeforeAll
public static void init(){
JsoniterSpi.registerTypeDecoder(Contact.class,new ContactCodec());
JsoniterSpi.registerTypeEncoder(Contact.class,new ContactCodec());
}
@Test
public void deserialize(){
String str = "[{\"uri\":\"tcp://def@local\",\"added\":1594742298377},{\"uri\":\"tcp://abc@19293.com\",\"removed\":1594742298377}]";
Contact[] contacts = JsonIterator.deserialize(str,Contact[].class);
Assertions.assertEquals(2,contacts.length);
}
@Test
public void serialize(){
Contact contact1 = new Contact();
contact1.setOwner("fsidokhine");
contact1.setStatus('A');
contact1.setTimestamp(System.currentTimeMillis());
contact1.setUri("tcp://def@local");
Contact contact2 = new Contact();
contact2.setOwner("fsidokhine");
contact2.setStatus('D');
contact2.setTimestamp(System.currentTimeMillis());
contact2.setUri("tcp://abc@19293.com");
ArrayList<Contact> lst = new ArrayList<>();
lst.add(contact1);
lst.add(contact2);
String str = JsonStream.serialize(lst);
Assertions.assertNotNull(str);
}
@Test
public void mergeTest(){
Contact contact1 = new Contact();
contact1.setOwner("fsidokhine");
contact1.setStatus('A');
contact1.setTimestamp(System.currentTimeMillis());
contact1.setUri("tcp://def@local");
Contact contact2 = new Contact();
contact2.setOwner("fsidokhine");
contact2.setStatus('D');
contact2.setTimestamp(System.currentTimeMillis());
contact2.setUri("tcp://abc@19293.com");
ArrayList<Contact> lst = new ArrayList<>();
lst.add(contact1);
lst.add(contact2);
Contact contact3 = new Contact();
contact3.setOwner("fsidokhine");
contact3.setStatus('A');
contact3.setTimestamp(System.currentTimeMillis() + 10000);
contact3.setUri("tcp://abc@19293.com");
ArrayList<Contact> lst2 = new ArrayList<>();
lst2.add(contact3);
List<Contact> out = ContactMerger.mergeContacts(lst,lst2);
Assertions.assertEquals(2,out.size());
}
}
\ No newline at end of file
...@@ -87,7 +87,7 @@ public class AppStarter extends Thread { ...@@ -87,7 +87,7 @@ public class AppStarter extends Thread {
public AppStarter(String[] args) { public AppStarter(String[] args) {
parentArgs = args; parentArgs = args;
try { try {
jamsProcessId = startAccountManagementServer(args); startAccountManagementServer(args);
setupZmqBridge(); setupZmqBridge();
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("Shutting down..."); log.info("Shutting down...");
...@@ -108,6 +108,7 @@ public class AppStarter extends Thread { ...@@ -108,6 +108,7 @@ public class AppStarter extends Thread {
//and run the good old routine //and run the good old routine
@Override @Override
public void run() { public void run() {
//TODO: Hack this a bit to get it to work better - passing arguments damnit.
while (true) { while (true) {
try { try {
if (doUpdate.get()) { if (doUpdate.get()) {
...@@ -115,7 +116,7 @@ public class AppStarter extends Thread { ...@@ -115,7 +116,7 @@ public class AppStarter extends Thread {
ProcessHandle.of(jamsProcessId).get().destroyForcibly(); ProcessHandle.of(jamsProcessId).get().destroyForcibly();
// transfer newly downloaded files to the right folder. // transfer newly downloaded files to the right folder.
doUpdate.set(false); doUpdate.set(false);
//Unpack the update. //Upack the update.
unpackUpdate(); unpackUpdate();
// Restart the main JAR and set the processId to it. // Restart the main JAR and set the processId to it.
jamsProcessId = startAccountManagementServer(parentArgs); jamsProcessId = startAccountManagementServer(parentArgs);
...@@ -133,6 +134,7 @@ public class AppStarter extends Thread { ...@@ -133,6 +134,7 @@ public class AppStarter extends Thread {
public static long startAccountManagementServer(String[] parentArgs) throws IOException { public static long startAccountManagementServer(String[] parentArgs) throws IOException {
ProcessBuilder pb = null; ProcessBuilder pb = null;
Process p;
switch (parentArgs.length) { switch (parentArgs.length) {
case 1: case 1:
pb = new ProcessBuilder("java", "-jar", "jams-server.jar", parentArgs[0]); pb = new ProcessBuilder("java", "-jar", "jams-server.jar", parentArgs[0]);
...@@ -147,7 +149,7 @@ public class AppStarter extends Thread { ...@@ -147,7 +149,7 @@ public class AppStarter extends Thread {
assert pb != null; assert pb != null;
pb.directory(new File(System.getProperty("user.dir"))); pb.directory(new File(System.getProperty("user.dir")));
pb.inheritIO(); pb.inheritIO();
Process p = pb.start(); p = pb.start();
return p.pid(); return p.pid();
} }
} }
\ No newline at end of file
...@@ -33,8 +33,11 @@ import net.jami.jams.common.dao.StatementElement; ...@@ -33,8 +33,11 @@ import net.jami.jams.common.dao.StatementElement;
import net.jami.jams.common.dao.StatementList; import net.jami.jams.common.dao.StatementList;
import net.jami.jams.common.objects.contacts.Contact; import net.jami.jams.common.objects.contacts.Contact;
import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler; import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler;
import net.jami.jams.common.utils.ContactMerger;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static net.jami.jams.server.Server.dataStore; import static net.jami.jams.server.Server.dataStore;
...@@ -42,6 +45,7 @@ import static net.jami.jams.server.Server.dataStore; ...@@ -42,6 +45,7 @@ import static net.jami.jams.server.Server.dataStore;
@WebServlet("/api/auth/contacts") @WebServlet("/api/auth/contacts")
public class ContactServlet extends HttpServlet { public class ContactServlet extends HttpServlet {
/** /**
* @apiVersion 1.0.0 * @apiVersion 1.0.0
* @api {get} /api/auth/contacts View contacts * @api {get} /api/auth/contacts View contacts
...@@ -52,8 +56,13 @@ public class ContactServlet extends HttpServlet { ...@@ -52,8 +56,13 @@ public class ContactServlet extends HttpServlet {
* @apiSuccessExample {json} Success-Response: * @apiSuccessExample {json} Success-Response:
* [{ * [{
* "uri": "jami://7e3ab29383", * "uri": "jami://7e3ab29383",
* "displayName": "John Doe" * "added": 18272662662
* }] * },
* {
* "uri": "jami://7e3ab29383",
* "removed": 12387873
* },
* ]
*/ */
@Override @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
...@@ -63,6 +72,7 @@ public class ContactServlet extends HttpServlet { ...@@ -63,6 +72,7 @@ public class ContactServlet extends HttpServlet {
resp.getOutputStream().write(JsonStream.serialize(contactList).getBytes()); resp.getOutputStream().write(JsonStream.serialize(contactList).getBytes());
} }
/** /**
* @apiVersion 1.0.0 * @apiVersion 1.0.0
* @api {put} /api/auth/contacts Add a contact * @api {put} /api/auth/contacts Add a contact
...@@ -72,8 +82,7 @@ public class ContactServlet extends HttpServlet { ...@@ -72,8 +82,7 @@ public class ContactServlet extends HttpServlet {
* @apiParam {body} Contact JSON representation of the contact object * @apiParam {body} Contact JSON representation of the contact object
* @apiParamExample {json} Request-Example: * @apiParamExample {json} Request-Example:
* { * {
* "uri": "jami://7e3ab29383", * "uri": "jami://7e3ab29383"
* "displayName": "John Doe"
* } * }
* *
* @apiSuccess (200) {null} null successfully added contact * @apiSuccess (200) {null} null successfully added contact
...@@ -82,8 +91,17 @@ public class ContactServlet extends HttpServlet { ...@@ -82,8 +91,17 @@ public class ContactServlet extends HttpServlet {
@Override @Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Contact contact = JsonIterator.deserialize(req.getInputStream().readAllBytes(),Contact.class); Contact contact = JsonIterator.deserialize(req.getInputStream().readAllBytes(),Contact.class);
//TODO: Replace with mergetool.
contact.setTimestamp(System.currentTimeMillis());
contact.setStatus('A');
contact.setOwner(req.getAttribute("username").toString()); contact.setOwner(req.getAttribute("username").toString());
if(dataStore.getContactDao().storeObject(contact)) resp.setStatus(200); StatementList statementList = new StatementList();
statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),""));
List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
List<Contact> remoteList = new ArrayList<>();
remoteList.add(contact);
List<Contact> result = ContactMerger.mergeContacts(localList,remoteList);
if(dataStore.getContactDao().storeContactList(result)) resp.setStatus(200);
else TomcatCustomErrorHandler.sendCustomError(resp,500,"could not store a contact due to server-side error"); else TomcatCustomErrorHandler.sendCustomError(resp,500,"could not store a contact due to server-side error");
} }
...@@ -103,7 +121,42 @@ public class ContactServlet extends HttpServlet { ...@@ -103,7 +121,42 @@ public class ContactServlet extends HttpServlet {
StatementList statementList = new StatementList(); StatementList statementList = new StatementList();
statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),"AND")); statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),"AND"));
statementList.addStatement(new StatementElement("uri","=",req.getParameter("uri"),"")); statementList.addStatement(new StatementElement("uri","=",req.getParameter("uri"),""));
if(dataStore.getContactDao().deleteObject(statementList)) resp.setStatus(200); List<Contact> remoteList = dataStore.getContactDao().getObjects(statementList);
remoteList.get(0).setStatus('D');
remoteList.get(0).setTimestamp(System.currentTimeMillis());
statementList = new StatementList();
statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),"AND"));
List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
List<Contact> result = ContactMerger.mergeContacts(localList,remoteList);
if(dataStore.getContactDao().storeContactList(result)) resp.setStatus(200);
else TomcatCustomErrorHandler.sendCustomError(resp,500,"could not delete a contact due to server-side error"); else TomcatCustomErrorHandler.sendCustomError(resp,500,"could not delete a contact due to server-side error");
} }
/**
* @apiVersion 1.0.0
* @api {post} /api/auth/contacts Add a contact
* @apiName putContact
* @apiGroup Contacts
*
* @apiParam {body} Contact JSON representation of the contact object
* @apiParamExample {json} Request-Example:
*[
* {"uri":"tcp://def@local","added":1594742298377},
* {"uri":"tcp://abc@19293.com","removed":1594742298377}
* ]
*
* @apiSuccess (200) {json} Contact[] successfully added contact
* @apiError (500) {null} null contact could not be successfully added
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StatementList statementList = new StatementList();
statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),""));
List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
List<Contact> remoteList = Arrays.asList(JsonIterator.deserialize(req.getInputStream().readAllBytes(),Contact[].class));
List<Contact> result = ContactMerger.mergeContacts(localList,remoteList);
if(!dataStore.getContactDao().storeContactList(result)) TomcatCustomErrorHandler.sendCustomError(resp,500,"Could not store contacts!");
resp.getOutputStream().write(JsonStream.serialize(result).getBytes());
}
} }
...@@ -51,7 +51,7 @@ public class UserProfileService { ...@@ -51,7 +51,7 @@ public class UserProfileService {
UserProfile[] profiles = null; UserProfile[] profiles = null;
Connection connection = null; Connection connection = null;
try { try {
queryString = URLEncoder.encode(queryString,StandardCharsets.UTF_8).replace("%","\\"); queryString = queryString.replaceAll("[^\\x00-\\x7F]","*");
connection = connectionFactory.getConnection(); connection = connectionFactory.getConnection();
try { try {
connection.open(); connection.open();
...@@ -84,7 +84,7 @@ public class UserProfileService { ...@@ -84,7 +84,7 @@ public class UserProfileService {
public static SearchRequest buildRequest(String queryString, String field) { public static SearchRequest buildRequest(String queryString, String field) {
if (!queryString.startsWith("*")) if (!queryString.startsWith("*"))
queryString = queryString.concat("*"); queryString = "*".concat(queryString).concat("*");
if(field.equals("LOGON_NAME")) { if(field.equals("LOGON_NAME")) {
return SearchRequest.builder() return SearchRequest.builder()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment