diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulClasses.java b/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulClasses.java index e906ec668..24bbad945 100644 --- a/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulClasses.java +++ b/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulClasses.java @@ -20,9 +20,7 @@ import java.util.HashSet; import java.util.Set; import li.strolch.rest.endpoint.*; -import li.strolch.rest.filters.AccessControlResponseFilter; -import li.strolch.rest.filters.AuthenticationRequestFilter; -import li.strolch.rest.filters.AuthenticationResponseFilter; +import li.strolch.rest.filters.*; /** * @author Robert von Burg @@ -41,6 +39,7 @@ public class StrolchRestfulClasses { restfulClasses.add(ReportResource.class); restfulClasses.add(ControlResource.class); restfulClasses.add(Inspector.class); + restfulClasses.add(I18nService.class); restfulClasses.add(VersionQuery.class); restfulClasses.add(ModelQuery.class); restfulClasses.add(EnumQuery.class); @@ -58,6 +57,8 @@ public class StrolchRestfulClasses { providerClasses.add(AccessControlResponseFilter.class); providerClasses.add(AuthenticationRequestFilter.class); providerClasses.add(AuthenticationResponseFilter.class); + providerClasses.add(CharsetResponseFilter.class); + providerClasses.add(HttpCacheResponseFilter.class); StrolchRestfulClasses.restfulClasses = Collections.unmodifiableSet(restfulClasses); StrolchRestfulClasses.providerClasses = Collections.unmodifiableSet(providerClasses); diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/I18nService.java b/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/I18nService.java new file mode 100644 index 000000000..f18b12231 --- /dev/null +++ b/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/I18nService.java @@ -0,0 +1,120 @@ +package li.strolch.rest.endpoint; + +import static li.strolch.model.StrolchModelConstants.ROLE_STROLCH_ADMIN; +import static li.strolch.rest.StrolchRestfulConstants.DATA; +import static li.strolch.rest.StrolchRestfulConstants.STROLCH_CERTIFICATE; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import li.strolch.persistence.api.Operation; +import li.strolch.privilege.model.Certificate; +import li.strolch.privilege.model.PrivilegeContext; +import li.strolch.privilege.model.SimpleRestrictable; +import li.strolch.rest.RestfulStrolchComponent; +import li.strolch.rest.helper.ResponseUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("i18n") +public class I18nService { + + private static final Logger logger = LoggerFactory.getLogger(I18nService.class); + + @GET + @Path("data") + @Produces(MediaType.TEXT_PLAIN) + public Response getI18nDataPlain(@Context HttpServletRequest request) { + Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE); + PrivilegeContext ctx = RestfulStrolchComponent.getInstance().validate(cert); + if (!ctx.hasRole(ROLE_STROLCH_ADMIN)) + ctx.validateAction(new SimpleRestrictable("I18n", Operation.GET.getPrivilegePrefix())); + + File webPath = new File(RestfulStrolchComponent.getInstance().getWebPath()); + File i18nFile = new File(webPath, "/locales.json"); + + JsonObject i18nJ; + try (FileReader in = new FileReader(i18nFile)) { + i18nJ = new JsonParser().parse(in).getAsJsonObject(); + } catch (IOException e) { + throw new IllegalStateException("Failed to read i18n file at " + i18nFile); + } + + logger.info("Returning I18n data to user " + cert.getUsername()); + String response = new GsonBuilder().setPrettyPrinting().create().toJson(i18nJ); + return Response.ok(response, MediaType.APPLICATION_JSON).build(); + } + + @GET + @Path("data") + @Produces(MediaType.APPLICATION_JSON) + public Response getI18nData(@Context HttpServletRequest request) { + Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE); + PrivilegeContext ctx = RestfulStrolchComponent.getInstance().validate(cert); + if (!ctx.hasRole(ROLE_STROLCH_ADMIN)) + ctx.validateAction(new SimpleRestrictable("I18n", Operation.GET.getPrivilegePrefix())); + + File webPath = new File(RestfulStrolchComponent.getInstance().getWebPath()); + File i18nFile = new File(webPath, "/locales.json"); + + JsonObject i18nJ; + try (FileReader in = new FileReader(i18nFile)) { + i18nJ = new JsonParser().parse(in).getAsJsonObject(); + } catch (IOException e) { + throw new IllegalStateException("Failed to read i18n file at " + i18nFile); + } + + logger.info("Returning I18n data to user " + cert.getUsername()); + return ResponseUtil.toResponse(DATA, i18nJ); + } + + @PUT + @Path("data") + @Consumes(MediaType.APPLICATION_JSON) + public Response setI18nData(@Context HttpServletRequest request, String data) { + Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE); + PrivilegeContext ctx = RestfulStrolchComponent.getInstance().validate(cert); + if (!ctx.hasRole(ROLE_STROLCH_ADMIN)) + ctx.validateAction(new SimpleRestrictable("I18n", Operation.UPDATE.getPrivilegePrefix())); + + JsonObject i18nJ = new JsonParser().parse(data).getAsJsonObject(); + + File webPath = new File(RestfulStrolchComponent.getInstance().getWebPath()); + File i18nFile = new File(webPath, "/locales.json"); + File i18nBackupFile = new File(webPath, "/locales.json_" + System.currentTimeMillis()); + + if (i18nFile.exists() && !i18nFile.canWrite()) + throw new IllegalStateException("Can not write to " + i18nFile); + + if (i18nFile.exists() && !i18nFile.renameTo(i18nBackupFile)) + throw new IllegalStateException("Failed to create backup of i18n file to " + i18nBackupFile); + + logger.info("Overwriting I18n data by user " + cert.getUsername() + " to file " + i18nFile); + try (FileWriter out = new FileWriter(i18nFile)) { + new GsonBuilder().setPrettyPrinting().create().toJson(i18nJ, out); + } catch (IOException e) { + if (i18nBackupFile.exists()) { + if (i18nFile.exists() && !i18nFile.delete()) + throw new IllegalStateException( + "Failed to restore backup after failing to write i18n file to " + i18nBackupFile, e); + if (!i18nBackupFile.renameTo(i18nFile)) + throw new IllegalStateException( + "Failed to restore backup after failing to write i18n file to " + i18nBackupFile, e); + } + + throw new IllegalStateException("Failed to write i18n file to " + i18nFile, e); + } + + return ResponseUtil.toResponse(); + } +}