
com.arcadedb.server.security.SecurityGroupFileRepository Maven / Gradle / Ivy
The newest version!
/*
* Copyright © 2021-present Arcade Data Ltd ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: 2021-present Arcade Data Ltd ([email protected])
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.server.security;
import com.arcadedb.database.DatabaseFactory;
import com.arcadedb.log.LogManager;
import com.arcadedb.security.SecurityManager;
import com.arcadedb.serializer.json.JSONArray;
import com.arcadedb.serializer.json.JSONObject;
import com.arcadedb.utility.Callable;
import com.arcadedb.utility.FileUtils;
import java.io.*;
import java.util.*;
import java.util.logging.*;
public class SecurityGroupFileRepository {
public static final String FILE_NAME = "server-groups.json";
private final String securityConfPath;
private final File file;
private final int checkConfigReloadEveryMs;
private long fileLastUpdated = 0L;
private Timer checkFileUpdatedTimer;
private Callable reloadCallback = null;
private volatile JSONObject latestGroupConfiguration;
public SecurityGroupFileRepository(String securityConfPath, final int checkConfigReloadEveryMs) {
if (!securityConfPath.endsWith(File.separator))
securityConfPath += File.separator;
this.securityConfPath = securityConfPath;
file = new File(securityConfPath, FILE_NAME);
this.checkConfigReloadEveryMs = checkConfigReloadEveryMs;
}
public void stop() {
if (checkFileUpdatedTimer != null)
checkFileUpdatedTimer.cancel();
}
public synchronized void save(final JSONObject configuration) throws IOException {
if (!file.exists())
file.getParentFile().mkdirs();
try (final FileWriter writer = new FileWriter(file, DatabaseFactory.getDefaultCharset())) {
writer.write(configuration.toString(2));
latestGroupConfiguration = configuration;
}
}
public synchronized void saveInError(final Exception e) {
if (latestGroupConfiguration == null)
return;
LogManager.instance().log(this, Level.SEVERE,
"Error on loading file '%s', using the default configuration and saving the corrupt file as 'config/server-groups-error.json'",
e, FILE_NAME);
final String fileName = securityConfPath + FILE_NAME;
final int pos = fileName.lastIndexOf(".");
final String errorFileName = fileName.substring(0, pos) + "-error.json";
final File file = new File(errorFileName);
if (!file.exists())
file.getParentFile().mkdirs();
try {
try (final FileWriter writer = new FileWriter(file, DatabaseFactory.getDefaultCharset())) {
writer.write(latestGroupConfiguration.toString());
}
} catch (final Exception e2) {
LogManager.instance().log(this, Level.SEVERE, "Error on saving configuration in error in config/security-error.json", e2);
}
}
public JSONObject getGroups() {
if (latestGroupConfiguration == null) {
try {
load();
} catch (final Exception e) {
LogManager.instance().log(this, Level.SEVERE, "Error on loading file '%s', using default configuration", e, FILE_NAME);
saveInError(e);
latestGroupConfiguration = createDefault();
}
}
return latestGroupConfiguration;
}
protected synchronized JSONObject load() throws IOException {
if (checkFileUpdatedTimer == null) {
checkFileUpdatedTimer = new Timer();
final Timer timer = checkFileUpdatedTimer;
checkFileUpdatedTimer.schedule(new TimerTask() {
@Override
public void run() {
// CHECK THE INSTANCE IS NOT CHANGED (THIS COULD HAPPEN DURING TESTS)
if (checkFileUpdatedTimer == timer)
try {
if (file.exists() && file.lastModified() > fileLastUpdated) {
LogManager.instance().log(this, Level.INFO, "Server groups configuration changed, reloading it...");
load();
if (reloadCallback != null)
reloadCallback.call(latestGroupConfiguration);
}
} catch (final Throwable e) {
LogManager.instance().log(this, Level.SEVERE, "Error on reloading file '%s' after was changed", e, FILE_NAME);
}
}
}, checkConfigReloadEveryMs, checkConfigReloadEveryMs);
}
JSONObject json = null;
if (file.exists()) {
fileLastUpdated = file.lastModified();
try (final FileInputStream fis = new FileInputStream(file)) {
json = new JSONObject(FileUtils.readStreamAsString(fis, "UTF-8"));
}
if (!json.has("version"))
json = null;
}
if (json == null)
json = createDefault();
if (json != null)
latestGroupConfiguration = json;
return json;
}
public JSONObject createDefault() {
final JSONObject json = new JSONObject();
// DEFAULT DATABASE
final JSONObject defaultDatabase = new JSONObject()//
.put("groups", new JSONObject()//
.put("admin", new JSONObject().put("resultSetLimit", -1L).put("readTimeout", -1L)//
.put("access", new JSONArray(new String[] { "updateSecurity", "updateSchema", "updateDatabaseSettings" }))//
.put("types", new JSONObject().put(SecurityManager.ANY, new JSONObject().put("access",
new JSONArray(new String[] { "createRecord", "readRecord", "updateRecord", "deleteRecord" })))))//
.put(SecurityManager.ANY, new JSONObject().put("resultSetLimit", -1L).put("readTimeout", -1L)//
.put("access", new JSONArray())
.put("types", new JSONObject().put(SecurityManager.ANY, new JSONObject().put("access", new JSONArray())))));
json.put("databases", new JSONObject().put(SecurityManager.ANY, defaultDatabase));
json.put("version", ServerSecurity.LATEST_VERSION);
try {
save(json);
} catch (final IOException e) {
LogManager.instance().log(this, Level.SEVERE, "Error on saving default group configuration to file '%s'", e, FILE_NAME);
}
return json;
}
public SecurityGroupFileRepository onReload(final Callable callback) {
reloadCallback = callback;
return this;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy