Use runeliteplus.properties for settings instead of runelite.properties (#240)
This commit is contained in:
@@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.runelite.http.api.config;
|
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.UUID;
|
|
||||||
import net.runelite.http.api.RuneLiteAPI;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.Callback;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class ConfigClient
|
|
||||||
{
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConfigClient.class);
|
|
||||||
|
|
||||||
private static final MediaType TEXT_PLAIN = MediaType.parse("text/plain");
|
|
||||||
|
|
||||||
private final UUID uuid;
|
|
||||||
|
|
||||||
public ConfigClient(UUID uuid)
|
|
||||||
{
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Configuration get() throws IOException
|
|
||||||
{
|
|
||||||
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
|
|
||||||
.addPathSegment("config")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
logger.debug("Built URI: {}", url);
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString())
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
|
||||||
{
|
|
||||||
InputStream in = response.body().byteStream();
|
|
||||||
return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), Configuration.class);
|
|
||||||
}
|
|
||||||
catch (JsonParseException ex)
|
|
||||||
{
|
|
||||||
throw new IOException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(String key, String value)
|
|
||||||
{
|
|
||||||
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
|
|
||||||
.addPathSegment("config")
|
|
||||||
.addPathSegment(key)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
logger.debug("Built URI: {}", url);
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.put(RequestBody.create(TEXT_PLAIN, value))
|
|
||||||
.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString())
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onFailure(Call call, IOException e)
|
|
||||||
{
|
|
||||||
logger.warn("Unable to synchronize configuration item", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(Call call, Response response)
|
|
||||||
{
|
|
||||||
response.close();
|
|
||||||
logger.debug("Synchronized configuration value '{}' to '{}'", key, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unset(String key)
|
|
||||||
{
|
|
||||||
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
|
|
||||||
.addPathSegment("config")
|
|
||||||
.addPathSegment(key)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
logger.debug("Built URI: {}", url);
|
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.delete()
|
|
||||||
.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString())
|
|
||||||
.url(url)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onFailure(Call call, IOException e)
|
|
||||||
{
|
|
||||||
logger.warn("Unable to unset configuration item", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(Call call, Response response)
|
|
||||||
{
|
|
||||||
response.close();
|
|
||||||
logger.debug("Unset configuration value '{}'", key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.runelite.http.api.config;
|
|
||||||
|
|
||||||
public class ConfigEntry
|
|
||||||
{
|
|
||||||
private String key;
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
public String getKey()
|
|
||||||
{
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(String key)
|
|
||||||
{
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue()
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(String value)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.runelite.http.api.config;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Configuration
|
|
||||||
{
|
|
||||||
private List<ConfigEntry> config = new ArrayList<>();
|
|
||||||
|
|
||||||
public Configuration(List<ConfigEntry> config)
|
|
||||||
{
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ConfigEntry> getConfig()
|
|
||||||
{
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.runelite.http.service.config;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import net.runelite.http.api.config.Configuration;
|
|
||||||
import net.runelite.http.service.account.AuthFilter;
|
|
||||||
import net.runelite.http.service.account.beans.SessionEntry;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/config")
|
|
||||||
public class ConfigController
|
|
||||||
{
|
|
||||||
private final ConfigService configService;
|
|
||||||
private final AuthFilter authFilter;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ConfigController(ConfigService configService, AuthFilter authFilter)
|
|
||||||
{
|
|
||||||
this.configService = configService;
|
|
||||||
this.authFilter = authFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException
|
|
||||||
{
|
|
||||||
SessionEntry session = authFilter.handle(request, response);
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return configService.get(session.getUser());
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(path = "/{key:.+}", method = PUT)
|
|
||||||
public void setKey(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
@PathVariable String key,
|
|
||||||
@RequestBody(required = false) String value
|
|
||||||
) throws IOException
|
|
||||||
{
|
|
||||||
SessionEntry session = authFilter.handle(request, response);
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
configService.setKey(session.getUser(), key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(path = "/{key:.+}", method = DELETE)
|
|
||||||
public void unsetKey(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
@PathVariable String key
|
|
||||||
) throws IOException
|
|
||||||
{
|
|
||||||
SessionEntry session = authFilter.handle(request, response);
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
configService.unsetKey(session.getUser(), key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017-2019, Adam <Adam@sigterm.info>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.runelite.http.service.config;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
|
||||||
import com.mongodb.client.MongoClient;
|
|
||||||
import com.mongodb.client.MongoCollection;
|
|
||||||
import com.mongodb.client.MongoDatabase;
|
|
||||||
import static com.mongodb.client.model.Filters.eq;
|
|
||||||
import com.mongodb.client.model.IndexOptions;
|
|
||||||
import com.mongodb.client.model.Indexes;
|
|
||||||
import com.mongodb.client.model.UpdateOptions;
|
|
||||||
import static com.mongodb.client.model.Updates.set;
|
|
||||||
import static com.mongodb.client.model.Updates.unset;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import net.runelite.http.api.RuneLiteAPI;
|
|
||||||
import net.runelite.http.api.config.ConfigEntry;
|
|
||||||
import net.runelite.http.api.config.Configuration;
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Slf4j
|
|
||||||
public class ConfigService
|
|
||||||
{
|
|
||||||
private final Gson GSON = RuneLiteAPI.GSON;
|
|
||||||
private final UpdateOptions upsertUpdateOptions = new UpdateOptions().upsert(true);
|
|
||||||
|
|
||||||
private final MongoCollection<Document> mongoCollection;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ConfigService(
|
|
||||||
MongoClient mongoClient
|
|
||||||
)
|
|
||||||
{
|
|
||||||
|
|
||||||
MongoDatabase database = mongoClient.getDatabase("config");
|
|
||||||
MongoCollection<Document> collection = database.getCollection("config");
|
|
||||||
this.mongoCollection = collection;
|
|
||||||
|
|
||||||
// Create unique index on _userId
|
|
||||||
IndexOptions indexOptions = new IndexOptions().unique(true);
|
|
||||||
collection.createIndex(Indexes.ascending("_userId"), indexOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Document getConfig(int userId)
|
|
||||||
{
|
|
||||||
return mongoCollection.find(eq("_userId", userId)).first();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Configuration get(int userId)
|
|
||||||
{
|
|
||||||
Map<String, Object> configMap = getConfig(userId);
|
|
||||||
|
|
||||||
if (configMap == null || configMap.isEmpty())
|
|
||||||
{
|
|
||||||
return new Configuration(Collections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ConfigEntry> config = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String group : configMap.keySet())
|
|
||||||
{
|
|
||||||
// Reserved keys
|
|
||||||
if (group.startsWith("_") || group.startsWith("$"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> groupMap = (Map) configMap.get(group);
|
|
||||||
|
|
||||||
for (Map.Entry<String, Object> entry : groupMap.entrySet())
|
|
||||||
{
|
|
||||||
String key = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
|
|
||||||
if (value instanceof Map || value instanceof Collection)
|
|
||||||
{
|
|
||||||
value = GSON.toJson(entry.getValue());
|
|
||||||
}
|
|
||||||
else if (value == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigEntry configEntry = new ConfigEntry();
|
|
||||||
configEntry.setKey(group + "." + key.replace(':', '.'));
|
|
||||||
configEntry.setValue(value.toString());
|
|
||||||
config.add(configEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Configuration(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(
|
|
||||||
int userId,
|
|
||||||
String key,
|
|
||||||
@Nullable String value
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (key.startsWith("$") || key.startsWith("_"))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] split = key.split("\\.", 2);
|
|
||||||
if (split.length != 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object jsonValue = parseJsonString(value);
|
|
||||||
mongoCollection.updateOne(eq("_userId", userId),
|
|
||||||
set(split[0] + "." + split[1].replace('.', ':'), jsonValue),
|
|
||||||
upsertUpdateOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unsetKey(
|
|
||||||
int userId,
|
|
||||||
String key
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (key.startsWith("$") || key.startsWith("_"))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] split = key.split("\\.", 2);
|
|
||||||
if (split.length != 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mongoCollection.updateOne(eq("_userId", userId),
|
|
||||||
unset(split[0] + "." + split[1].replace('.', ':')));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object parseJsonString(String value)
|
|
||||||
{
|
|
||||||
Object jsonValue;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
jsonValue = RuneLiteAPI.GSON.fromJson(value, Object.class);
|
|
||||||
|
|
||||||
if (jsonValue instanceof Double || jsonValue instanceof Float)
|
|
||||||
{
|
|
||||||
Number number = (Number) jsonValue;
|
|
||||||
if (Math.floor(number.doubleValue()) == number.doubleValue() && !Double.isInfinite(number.doubleValue()))
|
|
||||||
{
|
|
||||||
// value is an int or long. 'number' might be truncated so parse it from 'value'
|
|
||||||
try
|
|
||||||
{
|
|
||||||
jsonValue = Integer.parseInt(value);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException ex)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
jsonValue = Long.parseLong(value);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException ex2)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (JsonSyntaxException ex)
|
|
||||||
{
|
|
||||||
jsonValue = value;
|
|
||||||
}
|
|
||||||
return jsonValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.runelite.http.service.config;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import net.runelite.http.service.account.AuthFilter;
|
|
||||||
import net.runelite.http.service.account.beans.SessionEntry;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Matchers.anyInt;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
|
||||||
@WebMvcTest(ConfigController.class)
|
|
||||||
@Slf4j
|
|
||||||
@ActiveProfiles("test")
|
|
||||||
public class ConfigControllerTest
|
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@MockBean
|
|
||||||
private ConfigService configService;
|
|
||||||
|
|
||||||
@MockBean
|
|
||||||
private AuthFilter authFilter;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void before() throws IOException
|
|
||||||
{
|
|
||||||
when(authFilter.handle(any(HttpServletRequest.class), any(HttpServletResponse.class)))
|
|
||||||
.thenReturn(mock(SessionEntry.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetKey() throws Exception
|
|
||||||
{
|
|
||||||
mockMvc.perform(put("/config/key")
|
|
||||||
.content("value")
|
|
||||||
.contentType(MediaType.TEXT_PLAIN))
|
|
||||||
.andExpect(status().isOk());
|
|
||||||
|
|
||||||
verify(configService).setKey(anyInt(), eq("key"), eq("value"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -43,20 +43,16 @@ import java.lang.reflect.Modifier;
|
|||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.nio.channels.FileLock;
|
import java.nio.channels.FileLock;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -69,28 +65,20 @@ import net.runelite.client.RuneLite;
|
|||||||
import net.runelite.client.account.AccountSession;
|
import net.runelite.client.account.AccountSession;
|
||||||
import net.runelite.client.eventbus.EventBus;
|
import net.runelite.client.eventbus.EventBus;
|
||||||
import net.runelite.client.util.ColorUtil;
|
import net.runelite.client.util.ColorUtil;
|
||||||
import net.runelite.http.api.config.ConfigClient;
|
|
||||||
import net.runelite.http.api.config.ConfigEntry;
|
|
||||||
import net.runelite.http.api.config.Configuration;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class ConfigManager
|
public class ConfigManager
|
||||||
{
|
{
|
||||||
private static final String SETTINGS_FILE_NAME = "settings.properties";
|
private static final String SETTINGS_FILE_NAME = "runeliteplus.properties";
|
||||||
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
private static final File SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
||||||
private static final String[] KEY_ARRAY = new String[]{"fuckadam", "runelitisthebest", "sixtynine", "blazeit"};
|
private static final File STANDARD_SETTINGS_FILE = new File(RuneLite.RUNELITE_DIR, "settings.properties");
|
||||||
private static final Random r = new Random();
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
EventBus eventBus;
|
EventBus eventBus;
|
||||||
|
|
||||||
private final ScheduledExecutorService executor;
|
private final ScheduledExecutorService executor;
|
||||||
|
|
||||||
private AccountSession session;
|
|
||||||
private ConfigClient client;
|
|
||||||
private File propertiesFile;
|
|
||||||
|
|
||||||
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
||||||
private final Properties properties = new Properties();
|
private final Properties properties = new Properties();
|
||||||
private final Map<String, String> pendingChanges = new HashMap<>();
|
private final Map<String, String> pendingChanges = new HashMap<>();
|
||||||
@@ -99,7 +87,6 @@ public class ConfigManager
|
|||||||
public ConfigManager(ScheduledExecutorService scheduledExecutorService)
|
public ConfigManager(ScheduledExecutorService scheduledExecutorService)
|
||||||
{
|
{
|
||||||
this.executor = scheduledExecutorService;
|
this.executor = scheduledExecutorService;
|
||||||
this.propertiesFile = getPropertiesFile();
|
|
||||||
|
|
||||||
executor.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
executor.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
@@ -107,106 +94,12 @@ public class ConfigManager
|
|||||||
public final void switchSession(AccountSession session)
|
public final void switchSession(AccountSession session)
|
||||||
{
|
{
|
||||||
// Ensure existing config is saved
|
// Ensure existing config is saved
|
||||||
sendConfig();
|
load();
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
{
|
|
||||||
this.session = null;
|
|
||||||
this.client = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.session = session;
|
|
||||||
this.client = new ConfigClient(session.getUuid());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.propertiesFile = getPropertiesFile();
|
|
||||||
|
|
||||||
load(); // load profile specific config
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getLocalPropertiesFile()
|
|
||||||
{
|
|
||||||
return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getPropertiesFile()
|
|
||||||
{
|
|
||||||
// Sessions that aren't logged in have no username
|
|
||||||
if (session == null || session.getUsername() == null)
|
|
||||||
{
|
|
||||||
return getLocalPropertiesFile();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
File profileDir = new File(RuneLite.PROFILES_DIR, session.getUsername().toLowerCase());
|
|
||||||
return new File(profileDir, SETTINGS_FILE_NAME);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load()
|
public void load()
|
||||||
{
|
{
|
||||||
if (client == null)
|
loadFromFile();
|
||||||
{
|
|
||||||
loadFromFile();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Configuration configuration;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
configuration = client.get();
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
log.debug("Unable to load configuration from client, using saved configuration from disk", ex);
|
|
||||||
loadFromFile();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configuration.getConfig() == null || configuration.getConfig().isEmpty())
|
|
||||||
{
|
|
||||||
log.debug("No configuration from client, using saved configuration on disk");
|
|
||||||
loadFromFile();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
properties.clear();
|
|
||||||
|
|
||||||
for (ConfigEntry entry : configuration.getConfig())
|
|
||||||
{
|
|
||||||
log.debug("Loading configuration value from client {}: {}", entry.getKey(), entry.getValue());
|
|
||||||
final String[] split = entry.getKey().split("\\.", 2);
|
|
||||||
|
|
||||||
if (split.length != 2)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String groupName = split[0];
|
|
||||||
final String key = split[1];
|
|
||||||
final String value = entry.getValue();
|
|
||||||
final String oldValue = (String) properties.setProperty(entry.getKey(), value);
|
|
||||||
|
|
||||||
ConfigChanged configChanged = new ConfigChanged();
|
|
||||||
configChanged.setGroup(groupName);
|
|
||||||
configChanged.setKey(key);
|
|
||||||
configChanged.setOldValue(oldValue);
|
|
||||||
configChanged.setNewValue(value);
|
|
||||||
eventBus.post(configChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
saveToFile(propertiesFile);
|
|
||||||
|
|
||||||
log.debug("Updated configuration on disk with the latest version");
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
log.warn("Unable to update configuration on disk", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void syncPropertiesFromFile(File propertiesFile)
|
private synchronized void syncPropertiesFromFile(File propertiesFile)
|
||||||
@@ -257,38 +150,21 @@ public class ConfigManager
|
|||||||
|
|
||||||
public void importLocal()
|
public void importLocal()
|
||||||
{
|
{
|
||||||
if (session == null)
|
log.info("Nothing changed, don't worry!");
|
||||||
{
|
|
||||||
// No session, no import
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final File file = new File(propertiesFile.getParent(), propertiesFile.getName() + "." + TIME_FORMAT.format(new Date()));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
saveToFile(file);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
log.warn("Backup failed, skipping import", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
syncPropertiesFromFile(getLocalPropertiesFile());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void loadFromFile()
|
private synchronized void loadFromFile()
|
||||||
{
|
{
|
||||||
properties.clear();
|
properties.clear();
|
||||||
|
|
||||||
try (FileInputStream in = new FileInputStream(propertiesFile))
|
try (FileInputStream in = new FileInputStream(SETTINGS_FILE))
|
||||||
{
|
{
|
||||||
properties.load(new InputStreamReader(in, Charset.forName("UTF-8")));
|
properties.load(new InputStreamReader(in, Charset.forName("UTF-8")));
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException ex)
|
catch (FileNotFoundException ex)
|
||||||
{
|
{
|
||||||
log.debug("Unable to load settings - no such file");
|
log.debug("Unable to load settings - no such file, syncing from standard settings");
|
||||||
|
syncPropertiesFromFile(STANDARD_SETTINGS_FILE);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException | IOException ex)
|
catch (IllegalArgumentException | IOException ex)
|
||||||
{
|
{
|
||||||
@@ -705,22 +581,6 @@ public class ConfigManager
|
|||||||
boolean changed;
|
boolean changed;
|
||||||
synchronized (pendingChanges)
|
synchronized (pendingChanges)
|
||||||
{
|
{
|
||||||
if (client != null)
|
|
||||||
{
|
|
||||||
for (Map.Entry<String, String> entry : pendingChanges.entrySet())
|
|
||||||
{
|
|
||||||
String value = entry.getValue();
|
|
||||||
|
|
||||||
if (Strings.isNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
client.unset("GDPR-Alert!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client.set(getRandomElement(KEY_ARRAY), "NiceGDPRViolationNerds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
changed = !pendingChanges.isEmpty();
|
changed = !pendingChanges.isEmpty();
|
||||||
pendingChanges.clear();
|
pendingChanges.clear();
|
||||||
}
|
}
|
||||||
@@ -729,7 +589,7 @@ public class ConfigManager
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
saveToFile(propertiesFile);
|
saveToFile(SETTINGS_FILE);
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
@@ -737,10 +597,4 @@ public class ConfigManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getRandomElement(String[] ary)
|
|
||||||
{
|
|
||||||
int randomNumber=r.nextInt(ary.length);
|
|
||||||
return ary[randomNumber];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user