Created
February 13, 2020 14:22
-
-
Save juanplopes/4f4a2bdea6d511981d322b957bc43cdc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import net.intelie.live.* | |
import net.intelie.live.util.* | |
import net.intelie.live.queries.* | |
import net.intelie.live.model.* | |
import javax.ws.rs.* | |
import javax.ws.rs.core.* | |
import javax.servlet.http.* | |
import org.springframework.security.web.csrf.* | |
import org.springframework.web.util.* | |
import com.google.gson.* | |
@Path("/") | |
@Consumes("text/html") | |
@Produces("text/html") | |
@UseProxy | |
class SettingsResource { | |
String rootUrl, otherUrl; | |
SettingsNode root; | |
EntityContext entities; | |
boolean safe; | |
SettingsResource(boolean safe, String rootUrl, String otherUrl, SettingsNode root, EntityContext entities) { | |
this.safe = safe; | |
this.rootUrl = rootUrl | |
this.otherUrl = otherUrl | |
this.root = root | |
this.entities = entities | |
} | |
@GET | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
Response index() { | |
return Response.seeOther(URI.create("/tree/")).build(); | |
} | |
@GET | |
@Path("/raw/{path:.*}") | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
@Produces("application/json") | |
String raw(@PathParam("path") String path) { | |
return root.cd(path).raw(); | |
} | |
@GET | |
@Path("/rawlog/{id}/old") | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
@Produces("application/json") | |
String rawOld(@PathParam("id") int id) { | |
return entities.get(SettingLog.class, id).oldValue; | |
} | |
@GET | |
@Path("/rawlog/{id}/new") | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
@Produces("application/json") | |
String rawNew(@PathParam("id") int id) { | |
return entities.get(SettingLog.class, id).newValue; | |
} | |
@GET | |
@Path("/log/{path:.*}") | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
String fulllog(@PathParam("path") String path, @QueryParam("children") @DefaultValue("false") boolean children, @Context HttpServletRequest request) { | |
def dir = root.cd(path) | |
def level = PathUtils.level(dir.path()) | |
def list = entities.find(new AllSettingLogs().byIdPrefixAndLevel(dir.path(), level, children?Integer.MAX_VALUE:level) | |
.orderByDescending("dateCreated") | |
.page(1) | |
.pageSize(100)) | |
def builder = new StringBuilder() | |
header(builder, dir, request) | |
builder.append("<p><it>Showing at most 100 recent operations</it></p>") | |
builder.append("<table border=1>") | |
builder.append("<tr>"); | |
builder.append("<th>id</th>"); | |
builder.append("<th>date</th>"); | |
builder.append("<th>user</th>"); | |
builder.append("<th>op</th>"); | |
builder.append("<th>path</th>"); | |
builder.append("<th>new</th>"); | |
builder.append("<th>old</th>"); | |
builder.append("</tr>"); | |
list.each { | |
builder.append("<tr>"); | |
builder.append("<td>${it.id}</td>"); | |
builder.append("<td>${new Date(it.dateCreated)}</td>"); | |
if (it.author != null) | |
builder.append("<td><a href='${LiveUrls.user(it.author.id)}'>${it.author.displayName}</a></td>"); | |
else | |
builder.append("<td><system></td>"); | |
builder.append("<td>${it.operation}</td>"); | |
builder.append("<td><a href='${rootUrl}/tree${it.settingId}'>${it.settingId}</a></td>"); | |
builder.append("<td><a href='${rootUrl}/rawlog/${it.id}/new'>[raw]</a> ${truncate(it.newValue, 32)}</td>"); | |
builder.append("<td><a href='${rootUrl}/rawlog/${it.id}/old'>[raw]</a> ${truncate(it.oldValue, 32)}</td>"); | |
builder.append("</tr>"); | |
} | |
builder.append("</table>") | |
return builder.toString() | |
} | |
@POST | |
@Path("/delete/{path:.*}") | |
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
Response delete(@PathParam("path") String path) { | |
def dir = root.cd(path) | |
dir.delete() | |
String returl = "/tree" + PathUtils.parents(dir.path()).stream().findFirst().orElse('/') | |
return Response.seeOther(new URI(returl)).build(); | |
} | |
@GET | |
@Path("/tree/{path:.*}") | |
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
String tree(@PathParam("path") String path, @Context HttpServletRequest request) { | |
def dir = root.cd(path) | |
def builder = new StringBuilder() | |
header(builder, dir, request) | |
builder.append("<b>Value:</b><br/>${truncate(dir.raw(), 1024)}<br/>"); | |
builder.append("<hr/>"); | |
def children = dir.children() | |
if (children.size() > 0) { | |
builder.append("<b>Children:</b><br/>"); | |
builder.append("<table>") | |
children.each { | |
builder.append("<tr>"); | |
builder.append("<td><a href='${rootUrl}/log${it.path()}'>[log]</a></td>"); | |
builder.append("<td><a href='${rootUrl}/log${it.path()}?children=true'>[full log]</a></td>"); | |
builder.append("<td><a href='${it.name()}/'>${it.name()}/</a><td>"); | |
builder.append("<td>(${truncate(it.raw(), 80)} <a href='${rootUrl}/raw${it.path()}'>[raw]</a>)</td>"); | |
builder.append("</tr>"); | |
} | |
builder.append("</table>") | |
} | |
return builder.toString() | |
} | |
@GET | |
@Path("/new/{path:.*}") | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
String newChild(@PathParam("path") String path, @Context HttpServletRequest request) { | |
def dir = root.cd(path) | |
def builder = new StringBuilder() | |
header(builder, dir, request) | |
builder.append("<form method='post'>"); | |
builder.append(csrfInput(request)) | |
builder.append("<b>New node name:</b><br><input type='text' name='name' size=80 /><br/>"); | |
builder.append("<b>Value:</b><br/><textarea name='raw' rows='20' cols='120'></textarea><br/>"); | |
builder.append(""" | |
<input type='submit' value='ARE YOU SURE YOU WANT TO SUBMIT? OF COURSE I WILL CONFIRM AGAIN IF YOU CLICK.' onclick='return confirm("ARE YOU REALLY SURE?\\nnew child at: ${dir.path()}");'> | |
"""); | |
builder.append("</form>"); | |
return builder.toString() | |
} | |
@POST | |
@Path("/new/{path:.*}") | |
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
Response newChildPost(@PathParam("path") String path, @FormParam("name") String name, @FormParam("raw") String raw) { | |
if (name.isEmpty()) throw new IllegalArgumentException("Must have name") | |
def dir = root.cd(path).cd(name) | |
dir.set(LiveJson.create().fromJson(raw, JsonElement.class)) | |
String returl = "/tree${dir.path()}" | |
return Response.seeOther(new URI(returl)).build(); | |
} | |
@GET | |
@Path("/edit/{path:.*}") | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
String edit(@PathParam("path") String path, @Context HttpServletRequest request) { | |
def dir = root.cd(path) | |
def builder = new StringBuilder() | |
header(builder, dir, request) | |
builder.append("<form method='post'>"); | |
builder.append(csrfInput(request)) | |
builder.append("<b>Value:</b><br/><textarea name='raw' rows='20' cols='120'>${HtmlUtils.htmlEscape(dir.raw())}</textarea><br/>"); | |
builder.append(""" | |
<input type='submit' value='ARE YOU SURE YOU WANT TO SUBMIT? OF COURSE I WILL CONFIRM AGAIN IF YOU CLICK.' onclick='return confirm("ARE YOU REALLY SURE?\\nediting: ${dir.path()}");'> | |
"""); | |
builder.append("</form>"); | |
return builder.toString() | |
} | |
@POST | |
@Path("/edit/{path:.*}") | |
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) | |
@NeedsAuthority(value = [Permission.ADMIN]) | |
Response editPost(@PathParam("path") String path, @FormParam("raw") String raw) { | |
def dir = root.cd(path) | |
dir.set(LiveJson.create().fromJson(raw, JsonElement.class)) | |
String returl = "/tree${dir.path()}" | |
return Response.seeOther(new URI(returl)).build(); | |
} | |
CsrfToken getCsrf(HttpServletRequest request) { | |
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); | |
CsrfToken token = repository.loadToken(request); | |
if (token == null) { | |
token = repository.generateToken(request); | |
repository.saveToken(token, request, null); | |
} | |
return token; | |
} | |
def deleteButton(String path, HttpServletRequest request) { | |
} | |
def csrfInput(HttpServletRequest request) { | |
def csrf = getCsrf(request) | |
return "<input type='hidden' name='${csrf.parameterName}' value='${csrf.token}'/>" | |
} | |
def truncate(String s, int size) { | |
if (s == null) return null; | |
if (s.length() > size) return HtmlUtils.htmlEscape(s.substring(0, size)) + "..."; | |
return s | |
} | |
def header(StringBuilder builder, SettingsNode dir, HttpServletRequest request) { | |
builder.append("<h1>") | |
builder.append("<a href='${rootUrl}/tree/'><root></a>"); | |
PathUtils.parents(dir.path()).reverse().each { | |
builder.append(" / <a href='${rootUrl}/tree${it}'>${PathUtils.last(it)}</a>"); | |
} | |
if (dir.path() != "/") | |
builder.append(" / <a href='${rootUrl}/tree${dir.path()}'>${PathUtils.last(dir.path())}</a>"); | |
builder.append("</h1>") | |
builder.append("<a href='${rootUrl}/tree${dir.path()}'>[tree]</a>"); | |
builder.append(" <a href='${rootUrl}/log${dir.path()}'>[log]</a>"); | |
builder.append(" <a href='${rootUrl}/log${dir.path()}?children=true'>[full log]</a>"); | |
builder.append(" <a href='${rootUrl}/raw${dir.path()}'>[raw]</a>"); | |
if (!safe) { | |
builder.append("""<hr/> | |
<form method='post' action='${rootUrl}/delete${dir.path()}'> | |
${csrfInput(request)} | |
UNSAFE: | |
<a href='${otherUrl}${request.getPathInfo()}'>[BACK TO SAFETY]</a> | |
<a href='${rootUrl}/edit${dir.path()}'>[edit]</a> | |
<a href='${rootUrl}/new${dir.path()}'>[new child]</a> | |
<input type='submit' value='DELETE (OF COURSE I WILL CONFIRM AGAIN IF YOU CLICK)' onclick='return confirm("ARE YOU REALLY SURE?\\ndeleting: ${dir.path()}");'> | |
</form> | |
"""); | |
} else { | |
builder.append("""<hr/> | |
<a href='${otherUrl}${request.getPathInfo()}'>[ENABLE UNSAFE CONTROLS]</a> | |
"""); | |
} | |
builder.append("<hr/>"); | |
} | |
} | |
def root = live.settings().root() | |
def entities = live.data().getContext() | |
def safeUrl = live.web().resolveService('settings') | |
def unsafeUrl = live.web().resolveService('settings/unsafe') | |
live.web().addService('settings', new SettingsResource( | |
true, safeUrl, unsafeUrl, root, entities)); | |
live.web().addService('settings/unsafe', new SettingsResource( | |
false, unsafeUrl, safeUrl, root, entities)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment