mirror of
https://github.com/penpot/penpot.git
synced 2025-05-20 14:16:19 +02:00
✨ Add debugging pages for download/upload file data.
This commit is contained in:
parent
ffdd539233
commit
e6e3f2cbd5
10 changed files with 392 additions and 309 deletions
|
@ -1,94 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="robots" content="noindex,nofollow">
|
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
|
||||||
<title>penpot - error report {{id}}</title>
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono">
|
|
||||||
<style>
|
|
||||||
* {
|
|
||||||
font-family: "JetBrains Mono", monospace;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
margin: 20px;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
position: fixed;
|
|
||||||
width: 100vw;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
padding: 5px 20px;
|
|
||||||
display: flex;
|
|
||||||
background: #e3e3e3;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav > div {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
display: flex;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
height: calc(100vh - 75px);
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
line-height: 18px;
|
|
||||||
min-width: 210px;
|
|
||||||
margin: 0px 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
li:hover {
|
|
||||||
background-color: #e9e9e9;
|
|
||||||
}
|
|
||||||
|
|
||||||
li > a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<nav>
|
|
||||||
<h1>Latest error reports:</h1>
|
|
||||||
</nav>
|
|
||||||
<main>
|
|
||||||
<ul>
|
|
||||||
{% for item in items %}
|
|
||||||
<li><a href="/dbg/error/{{item.id}}">{{item.created-at}}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,169 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="robots" content="noindex,nofollow">
|
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
|
||||||
<title>penpot - error report {{id}}</title>
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
margin: 0px;
|
|
||||||
line-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
position: fixed;
|
|
||||||
width: 100vw;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
padding: 5px 20px;
|
|
||||||
display: flex;
|
|
||||||
background: #e3e3e3;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav > div {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav > div:not(:last-child) {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
font-family: "JetBrains Mono", monospace;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.table {
|
|
||||||
margin-top: 25px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
/* width: 100%; */
|
|
||||||
/* border: 1px solid red; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-key {
|
|
||||||
font-weight: 600;
|
|
||||||
width: 60px;
|
|
||||||
padding: 4px;
|
|
||||||
|
|
||||||
padding-top: 40px;
|
|
||||||
margin-top: -40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-val {
|
|
||||||
font-weight: 200;
|
|
||||||
color: #333;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiline {
|
|
||||||
margin-top: 15px;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiline .table-key {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border-bottom: 1px dashed #dddddd;
|
|
||||||
/* padding: 4px; */
|
|
||||||
width: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav>
|
|
||||||
<div>[<a href="/dbg/error"><<</a>]</div>
|
|
||||||
<div>[<a href="#context">context</a>]</div>
|
|
||||||
<div>[<a href="#params">request params</a>]</div>
|
|
||||||
{% if spec-problems %}
|
|
||||||
<div>[<a href="#spec-problems">spec problems</a>]</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if spec-value %}
|
|
||||||
<div>[<a href="#spec-value">spec value</a>]</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if data %}
|
|
||||||
<div>[<a href="#edata">error data</a>]</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if trace %}
|
|
||||||
<div>[<a href="#trace">error trace</a>]</div>
|
|
||||||
{% endif %}
|
|
||||||
</nav>
|
|
||||||
<main>
|
|
||||||
<div class="table">
|
|
||||||
<div class="table-row multiline">
|
|
||||||
<div id="context" class="table-key">CONTEXT: </div>
|
|
||||||
|
|
||||||
<div class="table-val">
|
|
||||||
<h1>{{hint}}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-val">
|
|
||||||
<pre>{{context}}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if params %}
|
|
||||||
<div class="table-row multiline">
|
|
||||||
<div id="params" class="table-key">REQUEST PARAMS: </div>
|
|
||||||
<div class="table-val">
|
|
||||||
<pre>{{params}}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if data %}
|
|
||||||
<div class="table-row multiline">
|
|
||||||
<div id="edata" class="table-key">ERROR DATA: </div>
|
|
||||||
<div class="table-val">
|
|
||||||
<pre>{{data}}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if spec-problems %}
|
|
||||||
<div class="table-row multiline">
|
|
||||||
<div id="spec-problems" class="table-key">SPEC PROBLEMS: </div>
|
|
||||||
<div class="table-val">
|
|
||||||
<pre>{{spec-problems}}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if spec-value %}
|
|
||||||
<div class="table-row multiline">
|
|
||||||
<div id="spec-value" class="table-key">SPEC VALUE: </div>
|
|
||||||
<div class="table-val">
|
|
||||||
<pre>{{spec-value}}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if trace %}
|
|
||||||
<div class="table-row multiline">
|
|
||||||
<div id="trace" class="table-key">TRACE:</div>
|
|
||||||
<div class="table-val">
|
|
||||||
<pre>{{trace}}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
18
backend/resources/templates/base.tmpl
Normal file
18
backend/resources/templates/base.tmpl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<title>{% block title %}{% endblock %}</title>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono">
|
||||||
|
<style>
|
||||||
|
{% include "templates/styles.css" %}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
32
backend/resources/templates/debug.tmpl
Normal file
32
backend/resources/templates/debug.tmpl
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{% extends "templates/base.tmpl" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Debug Main Page
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav>
|
||||||
|
<h1>Debug INDEX:</h1>
|
||||||
|
<div>[<a href="/dbg/error">ERRORS</a>]</div>
|
||||||
|
</nav>
|
||||||
|
<main class="index">
|
||||||
|
<section>
|
||||||
|
<h2>Download file data:</h2>
|
||||||
|
<desc>Given an FILE-ID, downloads the file data as file. The file data is encoded using transit.</desc>
|
||||||
|
<form method="get" action="/dbg/file/data">
|
||||||
|
<input type="text" style="width:300px" name="file-id" placeholder="file-id" />
|
||||||
|
<input type="hidden" name="download" value="1" />
|
||||||
|
<input type="submit" value="Download" />
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Upload File Data:</h2>
|
||||||
|
<desc>Create a new file on your draft projects using the file downloaded from the previous section.</desc>
|
||||||
|
<form method="post" enctype="multipart/form-data" action="/dbg/file/data">
|
||||||
|
<input type="file" name="file" value="" />
|
||||||
|
<input type="submit" value="Upload" />
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
18
backend/resources/templates/error-list.tmpl
Normal file
18
backend/resources/templates/error-list.tmpl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "templates/base.tmpl" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
penpot - error list
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav>
|
||||||
|
<h1>Latest error reports:</h1>
|
||||||
|
</nav>
|
||||||
|
<main class="horizontal-list">
|
||||||
|
<ul>
|
||||||
|
{% for item in items %}
|
||||||
|
<li><a href="/dbg/error/{{item.id}}">{{item.created-at}}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
86
backend/resources/templates/error-report.tmpl
Normal file
86
backend/resources/templates/error-report.tmpl
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
{% extends "templates/base.tmpl" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
penpot - error report {{id}}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav>
|
||||||
|
<div>[<a href="/dbg/error">⮜</a>]</div>
|
||||||
|
<div>[<a href="#context">context</a>]</div>
|
||||||
|
<div>[<a href="#params">request params</a>]</div>
|
||||||
|
{% if spec-problems %}
|
||||||
|
<div>[<a href="#spec-problems">spec problems</a>]</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if spec-value %}
|
||||||
|
<div>[<a href="#spec-value">spec value</a>]</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if data %}
|
||||||
|
<div>[<a href="#edata">error data</a>]</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if trace %}
|
||||||
|
<div>[<a href="#trace">error trace</a>]</div>
|
||||||
|
{% endif %}
|
||||||
|
</nav>
|
||||||
|
<main>
|
||||||
|
<div class="table">
|
||||||
|
<div class="table-row multiline">
|
||||||
|
<div id="context" class="table-key">CONTEXT: </div>
|
||||||
|
|
||||||
|
<div class="table-val">
|
||||||
|
<h1>{{hint}}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-val">
|
||||||
|
<pre>{{context}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if params %}
|
||||||
|
<div class="table-row multiline">
|
||||||
|
<div id="params" class="table-key">REQUEST PARAMS: </div>
|
||||||
|
<div class="table-val">
|
||||||
|
<pre>{{params}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if data %}
|
||||||
|
<div class="table-row multiline">
|
||||||
|
<div id="edata" class="table-key">ERROR DATA: </div>
|
||||||
|
<div class="table-val">
|
||||||
|
<pre>{{data}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if spec-problems %}
|
||||||
|
<div class="table-row multiline">
|
||||||
|
<div id="spec-problems" class="table-key">SPEC PROBLEMS: </div>
|
||||||
|
<div class="table-val">
|
||||||
|
<pre>{{spec-problems}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if spec-value %}
|
||||||
|
<div class="table-row multiline">
|
||||||
|
<div id="spec-value" class="table-key">SPEC VALUE: </div>
|
||||||
|
<div class="table-val">
|
||||||
|
<pre>{{spec-value}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if trace %}
|
||||||
|
<div class="table-row multiline">
|
||||||
|
<div id="trace" class="table-key">TRACE:</div>
|
||||||
|
<div class="table-val">
|
||||||
|
<pre>{{trace}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
150
backend/resources/templates/styles.css
Normal file
150
backend/resources/templates/styles.css
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
* {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text], input[type=submit] {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
position: fixed;
|
||||||
|
width: 100vw;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 5px 20px;
|
||||||
|
display: flex;
|
||||||
|
background: #e3e3e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > h1 {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > div {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > div:not(:last-child) {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
margin-top: 25px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
/* width: 100%; */
|
||||||
|
/* border: 1px solid red; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-key {
|
||||||
|
font-weight: 600;
|
||||||
|
width: 60px;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
padding-top: 40px;
|
||||||
|
margin-top: -40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-val {
|
||||||
|
font-weight: 200;
|
||||||
|
color: #333;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiline {
|
||||||
|
margin-top: 15px;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiline .table-key {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-bottom: 1px dashed #dddddd;
|
||||||
|
/* padding: 4px; */
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index > section {
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #e3e3e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index > section:not(:last-child) {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.index > section > h2 {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-list {
|
||||||
|
margin: 20px;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-list ul {
|
||||||
|
display: flex;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
height: calc(100vh - 75px);
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-list li {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
line-height: 18px;
|
||||||
|
min-width: 210px;
|
||||||
|
margin: 0px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-list li:hover {
|
||||||
|
background-color: #e9e9e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-list li > a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
|
@ -111,17 +111,20 @@
|
||||||
["/by-file-media-id/:id" {:get (:file-objects-handler assets)}]
|
["/by-file-media-id/:id" {:get (:file-objects-handler assets)}]
|
||||||
["/by-file-media-id/:id/thumbnail" {:get (:file-thumbnails-handler assets)}]]
|
["/by-file-media-id/:id/thumbnail" {:get (:file-thumbnails-handler assets)}]]
|
||||||
|
|
||||||
["/dbg" {:middleware [[middleware/params]
|
["/dbg" {:middleware [[middleware/multipart-params]
|
||||||
|
[middleware/params]
|
||||||
[middleware/keyword-params]
|
[middleware/keyword-params]
|
||||||
[middleware/format-response-body]
|
[middleware/format-response-body]
|
||||||
[middleware/errors errors/handle]
|
[middleware/errors errors/handle]
|
||||||
[middleware/cookies]
|
[middleware/cookies]
|
||||||
[(:middleware session)]]}
|
[(:middleware session)]]}
|
||||||
|
["" {:get (:index debug)}]
|
||||||
["/error-by-id/:id" {:get (:retrieve-error debug)}]
|
["/error-by-id/:id" {:get (:retrieve-error debug)}]
|
||||||
["/error/:id" {:get (:retrieve-error debug)}]
|
["/error/:id" {:get (:retrieve-error debug)}]
|
||||||
["/error" {:get (:retrieve-error-list debug)}]
|
["/error" {:get (:retrieve-error-list debug)}]
|
||||||
["/file/data/:id" {:get (:retrieve-file-data debug)}]
|
["/file/data" {:get (:retrieve-file-data debug)
|
||||||
["/file/changes/:id" {:get (:retrieve-file-changes debug)}]]
|
:post (:upload-file-data debug)}]
|
||||||
|
["/file/changes" {:get (:retrieve-file-changes debug)}]]
|
||||||
|
|
||||||
["/webhooks"
|
["/webhooks"
|
||||||
["/sns" {:post (:sns-webhook cfg)}]]
|
["/sns" {:post (:sns-webhook cfg)}]]
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
|
[app.rpc.mutations.files :as m.files]
|
||||||
[app.rpc.queries.profile :as profile]
|
[app.rpc.queries.profile :as profile]
|
||||||
[app.util.blob :as blob]
|
[app.util.blob :as blob]
|
||||||
[app.util.template :as tmpl]
|
[app.util.template :as tmpl]
|
||||||
|
@ -19,13 +20,10 @@
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.pprint :as ppr]
|
[clojure.pprint :as ppr]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
[datoteka.core :as fs]
|
||||||
[integrant.core :as ig]))
|
[integrant.core :as ig]))
|
||||||
|
|
||||||
(def sql:retrieve-range-of-changes
|
;; (selmer.parser/cache-off!)
|
||||||
"select revn, changes from file_change where file_id=? and revn >= ? and revn <= ? order by revn")
|
|
||||||
|
|
||||||
(def sql:retrieve-single-change
|
|
||||||
"select revn, changes, data from file_change where file_id=? and revn = ?")
|
|
||||||
|
|
||||||
(defn authorized?
|
(defn authorized?
|
||||||
[pool {:keys [profile-id]}]
|
[pool {:keys [profile-id]}]
|
||||||
|
@ -34,35 +32,73 @@
|
||||||
admins (or (cf/get :admins) #{})]
|
admins (or (cf/get :admins) #{})]
|
||||||
(contains? admins (:email profile)))))
|
(contains? admins (:email profile)))))
|
||||||
|
|
||||||
(defn prepare-response
|
(defn index
|
||||||
[body]
|
|
||||||
(when-not body
|
|
||||||
(ex/raise :type :not-found
|
|
||||||
:code :enpty-data
|
|
||||||
:hint "empty response"))
|
|
||||||
|
|
||||||
{:status 200
|
|
||||||
:headers {"content-type" "application/transit+json"}
|
|
||||||
:body body})
|
|
||||||
|
|
||||||
(defn retrieve-file-data
|
|
||||||
[{:keys [pool]} request]
|
[{:keys [pool]} request]
|
||||||
(when-not (authorized? pool request)
|
(when-not (authorized? pool request)
|
||||||
(ex/raise :type :authentication
|
(ex/raise :type :authentication
|
||||||
:code :only-admins-allowed))
|
:code :only-admins-allowed))
|
||||||
|
|
||||||
(let [id (some-> (get-in request [:path-params :id]) uuid/uuid)
|
{:status 200
|
||||||
|
:headers {"content-type" "text/html"}
|
||||||
|
:body (-> (io/resource "templates/debug.tmpl")
|
||||||
|
(tmpl/render {}))})
|
||||||
|
|
||||||
|
|
||||||
|
(def sql:retrieve-range-of-changes
|
||||||
|
"select revn, changes from file_change where file_id=? and revn >= ? and revn <= ? order by revn")
|
||||||
|
|
||||||
|
(def sql:retrieve-single-change
|
||||||
|
"select revn, changes, data from file_change where file_id=? and revn = ?")
|
||||||
|
|
||||||
|
(defn prepare-response
|
||||||
|
[{:keys [params] :as request} body]
|
||||||
|
(when-not body
|
||||||
|
(ex/raise :type :not-found
|
||||||
|
:code :enpty-data
|
||||||
|
:hint "empty response"))
|
||||||
|
|
||||||
|
(cond-> {:status 200
|
||||||
|
:headers {"content-type" "application/transit+json"}
|
||||||
|
:body body}
|
||||||
|
(contains? params :download)
|
||||||
|
(update :headers assoc "content-disposition" "attachment")))
|
||||||
|
|
||||||
|
(defn retrieve-file-data
|
||||||
|
[{:keys [pool]} {:keys [params] :as request}]
|
||||||
|
(when-not (authorized? pool request)
|
||||||
|
(ex/raise :type :authentication
|
||||||
|
:code :only-admins-allowed))
|
||||||
|
|
||||||
|
(let [file-id (some-> (get-in request [:params :file-id]) uuid/uuid)
|
||||||
revn (some-> (get-in request [:params :revn]) d/parse-integer)]
|
revn (some-> (get-in request [:params :revn]) d/parse-integer)]
|
||||||
(when-not id
|
(when-not file-id
|
||||||
(ex/raise :type :validation
|
(ex/raise :type :validation
|
||||||
:code :missing-arguments))
|
:code :missing-arguments))
|
||||||
|
|
||||||
(if (integer? revn)
|
(let [data (if (integer? revn)
|
||||||
(let [fchange (db/exec-one! pool [sql:retrieve-single-change id revn])]
|
(some-> (db/exec-one! pool [sql:retrieve-single-change file-id revn]) :data)
|
||||||
(prepare-response (some-> fchange :data blob/decode)))
|
(some-> (db/get-by-id pool :file file-id) :data))]
|
||||||
|
(if (contains? params :download)
|
||||||
|
(-> (prepare-response request data)
|
||||||
|
(update :headers assoc "content-type" "application/octet-stream"))
|
||||||
|
(prepare-response request (some-> data blob/decode))))))
|
||||||
|
|
||||||
(let [file (db/get-by-id pool :file id)]
|
(defn upload-file-data
|
||||||
(prepare-response (some-> file :data blob/decode))))))
|
[{:keys [pool]} {:keys [profile-id params] :as request}]
|
||||||
|
(let [project-id (some-> (profile/retrieve-additional-data pool profile-id) :default-project-id)
|
||||||
|
data (some-> params :file :tempfile fs/slurp-bytes blob/decode)]
|
||||||
|
|
||||||
|
(if (and data project-id)
|
||||||
|
(do
|
||||||
|
(m.files/create-file pool {:id (uuid/next)
|
||||||
|
:name "imported-file"
|
||||||
|
:project-id project-id
|
||||||
|
:profile-id profile-id
|
||||||
|
:data data})
|
||||||
|
{:status 200
|
||||||
|
:body "OK"})
|
||||||
|
{:status 500
|
||||||
|
:body "error"})))
|
||||||
|
|
||||||
(defn retrieve-file-changes
|
(defn retrieve-file-changes
|
||||||
[{:keys [pool]} request]
|
[{:keys [pool]} request]
|
||||||
|
@ -70,30 +106,30 @@
|
||||||
(ex/raise :type :authentication
|
(ex/raise :type :authentication
|
||||||
:code :only-admins-allowed))
|
:code :only-admins-allowed))
|
||||||
|
|
||||||
(let [id (some-> (get-in request [:path-params :id]) uuid/uuid)
|
(let [file-id (some-> (get-in request [:params :id]) uuid/uuid)
|
||||||
revn (get-in request [:params :revn] "latest")]
|
revn (or (get-in request [:params :revn]) "latest")]
|
||||||
|
|
||||||
(when (or (not id) (not revn))
|
(when (or (not file-id) (not revn))
|
||||||
(ex/raise :type :validation
|
(ex/raise :type :validation
|
||||||
:code :invalid-arguments
|
:code :invalid-arguments
|
||||||
:hint "missing arguments"))
|
:hint "missing arguments"))
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(d/num-string? revn)
|
(d/num-string? revn)
|
||||||
(let [item (db/exec-one! pool [sql:retrieve-single-change id (d/parse-integer revn)])]
|
(let [item (db/exec-one! pool [sql:retrieve-single-change file-id (d/parse-integer revn)])]
|
||||||
(prepare-response (some-> item :changes blob/decode vec)))
|
(prepare-response request (some-> item :changes blob/decode vec)))
|
||||||
|
|
||||||
(str/includes? revn ":")
|
(str/includes? revn ":")
|
||||||
(let [[start end] (->> (str/split revn #":")
|
(let [[start end] (->> (str/split revn #":")
|
||||||
(map str/trim)
|
(map str/trim)
|
||||||
(map d/parse-integer))
|
(map d/parse-integer))
|
||||||
items (db/exec! pool [sql:retrieve-range-of-changes id start end])]
|
items (db/exec! pool [sql:retrieve-range-of-changes file-id start end])]
|
||||||
(prepare-response (some->> items
|
(prepare-response request
|
||||||
|
(some->> items
|
||||||
(map :changes)
|
(map :changes)
|
||||||
(map blob/decode)
|
(map blob/decode)
|
||||||
(mapcat identity)
|
(mapcat identity)
|
||||||
(vec))))
|
(vec))))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(ex/raise :type :validation :code :invalid-arguments))))
|
(ex/raise :type :validation :code :invalid-arguments))))
|
||||||
|
|
||||||
|
@ -112,7 +148,9 @@
|
||||||
|
|
||||||
(render-template [report]
|
(render-template [report]
|
||||||
(binding [ppr/*print-right-margin* 300]
|
(binding [ppr/*print-right-margin* 300]
|
||||||
(let [context (dissoc report :trace :cause :params :data :spec-problems :spec-value :error :explain :hint :message)
|
(let [context (dissoc report
|
||||||
|
:trace :cause :params :data :spec-problems
|
||||||
|
:spec-value :error :explain :hint :message)
|
||||||
params {:context (with-out-str (ppr/pprint context))
|
params {:context (with-out-str (ppr/pprint context))
|
||||||
:hint (:hint report)
|
:hint (:hint report)
|
||||||
:spec-problems (:spec-problems report)
|
:spec-problems (:spec-problems report)
|
||||||
|
@ -122,7 +160,7 @@
|
||||||
(:trace report)
|
(:trace report)
|
||||||
(some-> report :error :trace))
|
(some-> report :error :trace))
|
||||||
:params (:params report)}]
|
:params (:params report)}]
|
||||||
(-> (io/resource "error-report.tmpl")
|
(-> (io/resource "templates/error-report.tmpl")
|
||||||
(tmpl/render params)))))
|
(tmpl/render params)))))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -154,12 +192,14 @@
|
||||||
{:status 200
|
{:status 200
|
||||||
:headers {"content-type" "text/html; charset=utf-8"
|
:headers {"content-type" "text/html; charset=utf-8"
|
||||||
"x-robots-tag" "noindex"}
|
"x-robots-tag" "noindex"}
|
||||||
:body (-> (io/resource "error-list.tmpl")
|
:body (-> (io/resource "templates/error-list.tmpl")
|
||||||
(tmpl/render {:items items}))}))
|
(tmpl/render {:items items}))}))
|
||||||
|
|
||||||
(defmethod ig/init-key ::handlers
|
(defmethod ig/init-key ::handlers
|
||||||
[_ cfg]
|
[_ cfg]
|
||||||
{:retrieve-file-data (partial retrieve-file-data cfg)
|
{:index (partial index cfg)
|
||||||
|
:retrieve-file-data (partial retrieve-file-data cfg)
|
||||||
:retrieve-file-changes (partial retrieve-file-changes cfg)
|
:retrieve-file-changes (partial retrieve-file-changes cfg)
|
||||||
:retrieve-error (partial retrieve-error cfg)
|
:retrieve-error (partial retrieve-error cfg)
|
||||||
:retrieve-error-list (partial retrieve-error-list cfg)})
|
:retrieve-error-list (partial retrieve-error-list cfg)
|
||||||
|
:upload-file-data (partial upload-file-data cfg)})
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
|
|
||||||
(sv/defmethod ::profile {:auth false}
|
(sv/defmethod ::profile {:auth false}
|
||||||
[{:keys [pool] :as cfg} {:keys [profile-id] :as params}]
|
[{:keys [pool] :as cfg} {:keys [profile-id] :as params}]
|
||||||
|
|
||||||
;; We need to return the anonymous profile object in two cases, when
|
;; We need to return the anonymous profile object in two cases, when
|
||||||
;; no profile-id is in session, and when db call raises not found. In all other
|
;; no profile-id is in session, and when db call raises not found. In all other
|
||||||
;; cases we need to reraise the exception.
|
;; cases we need to reraise the exception.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue