Commit 4c84e87b authored by Mat's avatar Mat

Merge branch 'feature/client' into develop

parents 9355f4e6 6fb8301f
Pipeline #79403099 passed with stages
in 24 minutes and 17 seconds
package searchitect.client.dynrh2levplugin;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
......@@ -13,6 +16,8 @@ import java.util.concurrent.ExecutionException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.io.output.ByteArrayOutputStream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Multimap;
......@@ -138,8 +143,30 @@ public class Clientdynrh2levImpl implements ClientScheme{
e.printStackTrace();
throw new SearchitectException(e.getMessage());
}
}
@Override
public byte[] serializeState() {
if(state == null)
return null;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
new ObjectOutputStream(out).writeObject(this.state);
return out.toByteArray();
}catch (Exception e) {
return null;
}
}
@Override
public void deserializeState(byte[] state) throws SearchitectException{
if(state == null)
this.state = null;
try (ByteArrayInputStream in = new ByteArrayInputStream(state)) {
this.state = (ClientStatedynrh2lev)(new ObjectInputStream(in).readObject());
RH2LevModifiedMap.master = this.state.getSk();
}catch (Exception e) {
throw new SearchitectException("Could not deserialize state", e);
}
}
......
......@@ -2,7 +2,10 @@ package searchitect.client.dynrh2levplugin;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
......@@ -15,11 +18,14 @@ import java.util.concurrent.ExecutionException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.io.output.ByteArrayOutputStream;
import searchitect.common.viewdynrh2lev.SearchTokendynrh2lev;
import searchitect.common.viewdynrh2lev.UpdateIndexdynrh2lev;
import searchitect.common.viewdynrh2lev.UploadIndexdynrh2levMap;
import searchitect.clusion.CryptoPrimitivesModified;
import searchitect.clusion.DynRH2LevModifiedRocks;
import searchitect.clusion.RH2LevModifiedMap;
import searchitect.clusion.RH2LevModifiedRocks;
import com.fasterxml.jackson.core.JsonProcessingException;
......@@ -143,8 +149,30 @@ public class Clientdynrh2levrocksImpl implements ClientScheme{
e.printStackTrace();
throw new SearchitectException(e.getMessage());
}
}
@Override
public byte[] serializeState() {
if(state == null)
return null;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
new ObjectOutputStream(out).writeObject(this.state);
return out.toByteArray();
}catch (Exception e) {
return null;
}
}
@Override
public void deserializeState(byte[] state) throws SearchitectException{
if(state == null)
this.state = null;
try (ByteArrayInputStream in = new ByteArrayInputStream(state)) {
this.state = (ClientStatedynrh2levrocks)(new ObjectInputStream(in).readObject());
RH2LevModifiedRocks.master = this.state.getSk();
}catch (Exception e) {
throw new SearchitectException("Could not deserialize state", e);
}
}
}
package searchitect.client.sophos;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyException;
......@@ -11,6 +14,8 @@ import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.util.HashMap;
import org.apache.commons.io.output.ByteArrayOutputStream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Multimap;
......@@ -85,6 +90,8 @@ public class ClientSophosImpl implements ClientScheme {
* @see searchitect.scheme.IClientScheme#search(java.lang.String)
*/
public String search(String query) throws SearchitectException {
if(state == null)
throw new SearchitectException("Client state has not been initialized");
try {
// generate search token
SearchTokenSophos token = Sophos.token(query, state);
......@@ -125,6 +132,26 @@ public class ClientSophosImpl implements ClientScheme {
}
@Override
public byte[] serializeState() {
if(state == null)
return null;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
new ObjectOutputStream(out).writeObject(this.state);
return out.toByteArray();
}catch (Exception e) {
return null;
}
}
@Override
public void deserializeState(byte[] state) throws SearchitectException{
if(state == null)
this.state = null;
try (ByteArrayInputStream in = new ByteArrayInputStream(state)) {
this.state = (ClientStateSophos)(new ObjectInputStream(in).readObject());
}catch (Exception e) {
throw new SearchitectException("Could not deserialize state", e);
}
}
}
......@@ -150,6 +150,12 @@ public class ClientSophosImplTest {
assertEquals(sophos.getImplName(),"sophos");
}
@Test(expected = SearchitectException.class)
public void searchWithoutStateTest(){
ClientSophosImpl sophos = new ClientSophosImpl();
sophos.search("foo");
}
@Test
public void setupKeywordSearchSuccessTest() throws KeyException, NoSuchAlgorithmException, InvalidKeySpecException, FactoriesException, InvalidAlgorithmParameterException, NoSuchProviderException, NoSuchPaddingException, IOException {
......
......@@ -117,6 +117,11 @@
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<plugins>
......@@ -127,6 +132,27 @@
<release>10</release>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.6.RELEASE</version>
<configuration>
<mainClass>searchitect.ClientRunner</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
8@rq Y
\ No newline at end of file
#!/bin/sh
JAR_PATH="./target/searchitect-client-0.0.1-SNAPSHOT-exec.jar"
java -jar $JAR_PATH $@
package searchitect;
import org.apache.commons.cli.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import searchitect.client.Client;
import searchitect.client.DocumentIndexer;
import searchitect.client.dynrh2levplugin.Clientdynrh2levImpl;
import searchitect.client.dynrh2levplugin.Clientdynrh2levrocksImpl;
import searchitect.client.sophos.ClientSophosImpl;
import searchitect.common.client.ClientScheme;
import searchitect.common.exception.SearchitectException;
import searchitect.common.view.RepositoryInfo;
import searchitect.common.view.SearchResult;
import searchitect.common.view.UserAuthRequest;
......@@ -17,125 +21,311 @@ import searchitect.common.view.UserAuthResponse;
@SpringBootApplication
public class ClientRunner {
private static Options cliOptions;
static {
cliOptions = new Options();
cliOptions.addOption("s", "serverurl", true, "URL of a Searchitect Gate");
cliOptions.addOption("u", "username", true, "Username on the Searchitect Gate");
cliOptions.addOption("p", "password", true, "Password on the Searchitect Gate");
cliOptions.addOption("P", "repository-password", true, "Password for the encryption of the search index. Must be given when a repository is created.");
cliOptions.addOption("c", "createuser", false, "Create a new user on the Searchitect Gate");
cliOptions.addOption("d", "path", true, "Path to the document folder");
cliOptions.addOption("U", "update", true, "Path to the document folder for an update operation");
cliOptions.addOption("r", "repository", true, "Name of the SE repository");
cliOptions.addOption("q", "search", true, "Search query string");
cliOptions.addOption("S", "state", true, "File where the client state is stored");
cliOptions.addOption("b", "backend", true, "The backend to use. Allowed values: sophos (default), dynrh2lev, dynrh2levrocks");
cliOptions.addOption("v", "verbose", false, "Enable verbose output");
cliOptions.addOption("h", "help", true, "Print help");
}
public static void printHelpAndExit() {
printHelpAndExit(-1);
}
/**
* Prints the help message to stdout and exits the program
* @param status The exit status of the programm. Defaults to -1
*/
public static void printHelpAndExit(int status) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp( "searchitect-client", cliOptions );
System.exit(status);
}
public static void main(String[] args) {
SpringApplication.run(ClientRunner.class, args);
System.out.println("welcome to searchitect");
final String uri = "https://localhost:8433/";
String setuppath = "/home/nan/Downloads/maildir/allen-p/";
String updatepath = "../update";
String username ="xyz";
String query= "first";
String uri = "https://localhost:8433/";
String setuppath = null;
String updatepath = null;
String username = null;
String password = null;
String repositoryPassword = null;
String searchString = "";
String repositoryName = "";
String stateFile = null;
boolean verbose = false;
boolean createUser = false;
ClientScheme clientimpl = null;
// Parse the commandline input
try {
CommandLineParser cliParser = new DefaultParser();
CommandLine cmd = cliParser.parse( cliOptions, args);
if(cmd.hasOption("help")) {
printHelpAndExit(0);
}
if(cmd.hasOption("verbose"))
verbose = true;
if(cmd.hasOption("createuser"))
createUser = true;
if(cmd.hasOption("serverurl")) {
uri = cmd.getOptionValue("serverurl");
System.out.println("URL set to "+uri);
}else
if(verbose)
System.out.println("No server URL specified. Using the default value " + uri);
if(cmd.hasOption("username")) {
username = cmd.getOptionValue("username");
if(verbose)
System.out.println("Using the username " + username);
}else {
//Required option
System.err.println("No username specified.");
printHelpAndExit();
}
if(cmd.hasOption("password")) {
password = cmd.getOptionValue("password").trim();
}
if(password == null || password == "") {
//Read password from the console
char[] pwEntered = System.console().readPassword("Please enter the password for user " + username + ":");
password = new String(pwEntered).trim();
}
if(cmd.hasOption("path")) {
setuppath = cmd.getOptionValue("path");
}
if(cmd.hasOption("repository-password")) {
repositoryPassword = cmd.getOptionValue("repository-password").trim();
}
if(setuppath != null) {
// We need a repository-password if we setup a new repository
if(repositoryPassword == null || repositoryPassword == "") {
//Read password from the console
char[] pwEntered = System.console().readPassword("Please enter the password for the new repository:");
repositoryPassword = new String(pwEntered).trim();
}
}
if(cmd.hasOption("update")) {
updatepath = cmd.getOptionValue("update");
}
if(cmd.hasOption("search")) {
searchString = cmd.getOptionValue("search").toLowerCase();
}
if(cmd.hasOption("repository")) {
repositoryName = cmd.getOptionValue("repository");
}
if(cmd.hasOption("state")) {
stateFile = cmd.getOptionValue("state");
}
if(cmd.hasOption("backend")) {
switch(cmd.getOptionValue("backend").toLowerCase()) {
case "sophos":
clientimpl = new ClientSophosImpl();
break;
case "dynrh2lev":
clientimpl = new Clientdynrh2levImpl();
break;
case "dynrh2levrocks":
clientimpl = new Clientdynrh2levrocksImpl();
break;
default:
System.err.println("Unknown backend specified.");
printHelpAndExit();
break;
}
} else
//Set the default backend if none is specified
clientimpl = new ClientSophosImpl();
}catch (Exception e) {
System.err.println("Illegal commandline option used.");
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp( "searchitect-client", cliOptions );
return;
}
DocumentIndexer parser = DocumentIndexer.parseDirectory(setuppath);
//Disable Spring logging
System.setProperty("logging.level.org.springframework", "OFF");
System.setProperty("logging.level.root", "OFF");
System.setProperty("spring.main.banner-mode", "off");
SpringApplication.run(ClientRunner.class, args);
if(verbose)
System.out.println("welcome to Searchitect!");
try {
// ClientScheme clientimpl = (ClientScheme) new Clientdynrh2levImpl();
ClientScheme clientimpl = (ClientScheme) new ClientSophosImpl();
Client client = new Client(uri,clientimpl);
System.out.println(client.check());
//System.out.println(client.checkBackend());
try {
System.out.println("create user\n");
ResponseEntity<String> string = client.createUser(new UserAuthRequest(username, "notsecurepassword"));
System.out.println(string.getStatusCodeValue());
System.out.println("authenticate user\n");
}
catch(Exception e) {
System.out.println("user exists!! \n");
}
UserAuthResponse token = client.authenticateUser(new UserAuthRequest(username, "notsecurepassword"));
System.out.println(token.getToken());
System.out.println("Check authentication and backend communication: \n");
System.out.println(client.checkAuthBackend());
System.out.println("Setup: \n");
while(parser.isFinished()==false){
System.out.println("...is Parsing");
}
RepositoryInfo repo = client.setup("testpwd", parser.getInvertedIndex(),parser.getSizeOfDocuments());
System.out.println("Repository has been initialized: \n" + repo.getrepositoryName());
System.out.println("1. Search: \n");
SearchResult result1 = client.search(repo.getrepositoryName(), query);
System.out.println("Searchresult1: \n" + result1.getResultList().toString());
parser = DocumentIndexer.parseDirectory(updatepath);
System.out.println("Update: \n");
ResponseEntity<String> up = client.update(repo.getrepositoryName(), parser.getInvertedIndex(), username);
System.out.println("Update result: \n" + up.getStatusCodeValue());
System.out.println("2. Search: \n");
SearchResult result2 =client.search(repo.getrepositoryName(), query);
System.out.println("Searchresult2: \n" + result2.getResultList().toString());
System.out.println("2. Update: \n");
ResponseEntity<String> up2 = client.update(repo.getrepositoryName(), parser.getInvertedIndex(), username);
System.out.println("Update result: \n" + up2.getStatusCodeValue());
System.out.println("3. Search: \n");
SearchResult result3 =client.search(repo.getrepositoryName(), query);
System.out.println("Searchresult3: \n" + result3.getResultList().toString());
Client client = new Client(uri,clientimpl);
//Check availability of the Gate
try {
client.check();
}catch(Exception e) {
System.err.println(String.format("Searchitect Gate at %s not available", uri));
System.exit(-1);
}
try {
//Create the user (if neccessary)
if(createUser) {
ResponseEntity<String> createUserResponse = client.createUser(new UserAuthRequest(username, password));
System.out.println(String.format("User '%s' created", username));
if(verbose)
System.out.println(String.format("Return code from the server: %s", createUserResponse.getStatusCodeValue()));
}
} catch(Exception e) {
System.err.println("Error creating the user.\n");
if(verbose)
System.err.println(e.toString());
System.exit(-1);
}
//Authenticate to the gate
UserAuthResponse token = null;
try{
token = client.authenticateUser(new UserAuthRequest(username, password));
}catch(HttpClientErrorException e) {
if(e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
System.err.println("Authentication failed.");
} else {
//Unknown error. We still cannot go on
System.err.println("Unknown error during authentication with the Searchitect Gate.");
}
System.exit(-1);
}
if(verbose)
System.out.println(String.format("User '%s' authenticated.", username));
if(verbose)
System.out.println("Token: '" + token.getToken() + "'.");
//Check if the SE backend is available for the authenticated use
try {
String checkAuthBackendMsg = client.checkAuthBackend().toString();
if(verbose)
System.out.println(String.format("Welcome message from the SE backend: '%s'", checkAuthBackendMsg));
}catch(HttpClientErrorException e) {
System.err.println("The backend is currently not available for this user.");
if(verbose) System.err.println(e.toString());
System.exit(-1);
}
//Setup the repository (if necessary)
if(setuppath != null) {
// Parse the documents
DocumentIndexer parser = DocumentIndexer.parseDirectory(setuppath);
System.out.println("Setup: \n");
RepositoryInfo repo = client.setup(repositoryPassword, parser.getInvertedIndex(), parser.getSizeOfDocuments());
if(repo == null) {
System.err.println("Repository setup failed.");
System.exit(-1);
}
repositoryName = repo.getrepositoryName();
System.out.println(String.format("The new repository '%s' has been initialized.", repositoryName));
//Store the new state
if(stateFile != null) {
try {
client.writeState(stateFile);
if(verbose)
System.out.println(String.format("Client state stored to '%s'.", stateFile));
}catch(SearchitectException e) {
System.err.println("Could not store the client state.");
if(verbose)
e.printStackTrace();
}
}
}else if (stateFile != null) {
//Load the stored state
try {
client.readState(stateFile);
if(verbose)
System.out.println(String.format("Client state read from '%s'.", stateFile));
}catch(SearchitectException e) {
System.err.println(String.format("Error while reading the state from '%s'.", stateFile));
if(verbose)
e.printStackTrace();
printHelpAndExit();
}
}else {
//neither a statefile was given nor a new repository was setup.
System.err.println("No statefile was given and a new repository has not been setup either. This will likely cause an error.");
//We just print this warning and try to continue anyway
}
//Run the update operation
if(updatepath != null) {
if(verbose)