mirror of
https://github.com/Luzifer/past3.git
synced 2024-12-22 20:31:16 +00:00
Fix remaining BS4 update, add private files feature
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
c31b86d22a
commit
0cba83022d
4 changed files with 101 additions and 49 deletions
71
app.js
71
app.js
|
@ -1,3 +1,4 @@
|
|||
const allUsersURI = 'http://acs.amazonaws.com/groups/global/AllUsers'
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm:ss'
|
||||
|
||||
// showAlert creates an alert message and displays it
|
||||
|
@ -47,9 +48,8 @@ function fileActionCallback(err, data) {
|
|||
}
|
||||
|
||||
// filenameInput is the callback for changes in the filename
|
||||
function filenameInput() {
|
||||
setEditorMime($(this).val())
|
||||
$('#file-url').val(window.past3_config.base_url + getFilePrefix() + $(this).val())
|
||||
function filenameInput(e) {
|
||||
updateFileURL()
|
||||
}
|
||||
|
||||
// formatDate formats a Date() object into iso-like format
|
||||
|
@ -95,8 +95,26 @@ function getFile(filename) {
|
|||
Key: getFilePrefix() + filename,
|
||||
}, loadFileIntoEditor)
|
||||
|
||||
// Check whether the file is public
|
||||
s3.getObjectAcl({
|
||||
Bucket: window.past3_config.bucket,
|
||||
Key: getFilePrefix() + filename,
|
||||
}, (err, data) => {
|
||||
if (err) return error(err)
|
||||
|
||||
for (let grant of data.Grants) {
|
||||
if (grant.Grantee.Type == "Group" && grant.Grantee.URI == allUsersURI) {
|
||||
$('#acl').data('public', true)
|
||||
return updateFileURL()
|
||||
}
|
||||
}
|
||||
|
||||
$('#acl').data('public', false)
|
||||
return updateFileURL()
|
||||
})
|
||||
|
||||
$('#filename').val(filename)
|
||||
$('#filename').trigger('input')
|
||||
updateFileURL()
|
||||
}
|
||||
|
||||
// getFilePrefix retrieves the file prefix using the Cognito identityId
|
||||
|
@ -165,7 +183,17 @@ function init() {
|
|||
if (cf) cf.find('i').removeClass('fa-file').addClass('fa-file-upload')
|
||||
})
|
||||
|
||||
$('#acl').data('public', window.past3_config.default_public)
|
||||
|
||||
// Set up bindings
|
||||
$('#acl').bind('click', (e) => {
|
||||
let el = $(e.target)
|
||||
el.data('public', !el.data('public'))
|
||||
|
||||
updateFileURL()
|
||||
return false
|
||||
})
|
||||
|
||||
$('#filename').bind('input', filenameInput)
|
||||
|
||||
$('#newFile').bind('click', () => {
|
||||
|
@ -215,6 +243,12 @@ function init() {
|
|||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
|
||||
if ((e.metaKey || e.ctrlKey) && e.keyCode == 76) { // cmd + l / ctrl + l
|
||||
$('#acl').trigger('click')
|
||||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -274,10 +308,12 @@ function loadFileList(err, data) {
|
|||
fileIcon = 'file'
|
||||
}
|
||||
|
||||
let li = $(`<a href='#${key}' class='list-group-item file-list-item'><span class='badge'></span> <i class="fas fa-fw fa-${fileIcon}"></i> ${key}</a>`)
|
||||
li.find('.badge').text(`${formatDate(obj.LastModified)}`)
|
||||
let li = $(`<a href='#${key}' class='list-group-item file-list-item d-flex justify-content-between align-items-center'><span><i class="fas fa-fw fa-${fileIcon}"></i> ${key}</span></a>`)
|
||||
li.data('file', key)
|
||||
|
||||
let badge = $(`<span class='badge badge-dark badge-pill'>${formatDate(obj.LastModified)}</span>`)
|
||||
badge.appendTo(li)
|
||||
|
||||
if (key === $('#filename').val()) {
|
||||
li.addClass('active')
|
||||
}
|
||||
|
@ -308,13 +344,16 @@ function renderButton() {
|
|||
// saveFile saves the editor content into the S3 bucket
|
||||
function saveFile(filename, content) {
|
||||
let mime = getMimeType(filename)
|
||||
let pub = $('#acl').data('public')
|
||||
|
||||
let s3 = new AWS.S3()
|
||||
s3.putObject({
|
||||
ACL: window.past3_config.acl,
|
||||
ACL: pub ? 'public-read' : 'private',
|
||||
Body: content,
|
||||
Bucket: window.past3_config.bucket,
|
||||
ContentType: mime.mime,
|
||||
Key: getFilePrefix() + filename,
|
||||
ServerSideEncryption: 'AES256',
|
||||
}, saveFileCallback)
|
||||
}
|
||||
|
||||
|
@ -339,7 +378,7 @@ function setEditorMime(filename) {
|
|||
let autoMime = getMimeType(filename)
|
||||
window.editor.setOption('mode', autoMime.mime)
|
||||
CodeMirror.autoLoadMode(window.editor, autoMime.mode)
|
||||
}, 500)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
// signinCallback is triggered by the Google sign-in button
|
||||
|
@ -355,6 +394,22 @@ function signinCallback(authResult) {
|
|||
}
|
||||
}
|
||||
|
||||
// updateFileURL sets the public URL of the file and adjusts the ACL button
|
||||
function updateFileURL() {
|
||||
let pub = $('#acl').data('public')
|
||||
let filename = $('#filename').val()
|
||||
|
||||
setEditorMime(filename)
|
||||
|
||||
if (pub) {
|
||||
$('#file-url').val(window.past3_config.base_url + getFilePrefix() + filename)
|
||||
$('#acl').find('i').removeClass('fa-unlock').addClass('fa-lock')
|
||||
} else {
|
||||
$('#file-url').val('File is private, no URL available')
|
||||
$('#acl').find('i').removeClass('fa-lock').addClass('fa-unlock')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initialize app on document ready
|
||||
$(() => init())
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
---
|
||||
|
||||
# Canned ACL for files stored into S3. One of "private, public-read,
|
||||
# public-read-write, authenticated-read, aws-exec-read, bucket-owner-read,
|
||||
# bucket-owner-full-control"
|
||||
acl: public-read
|
||||
# Default acl setting for new files: If set to true the files are created
|
||||
# using `public-read` acl, if set to false they are created with `private` acl.
|
||||
default_public: true
|
||||
|
||||
# Base URL for the uploaded files, either S3 download URL or CloudFront
|
||||
# distribution URL to which the file path is appended for display in the
|
||||
|
@ -12,7 +11,7 @@ base_url: https://paste.luzifer.io/
|
|||
|
||||
# Theme name (lowercase) of Bootswatch.com theme (Optional, when not
|
||||
# specified the original bootstrap theme is used)
|
||||
bootswatch_theme: cosmo
|
||||
bootswatch_theme: flatly
|
||||
|
||||
# Name of the Bucket used to store the files in. The bucket needs to be
|
||||
# whitelisted for Cognito authenticated users
|
||||
|
|
|
@ -7,5 +7,4 @@ config = yaml.load(open('config.yml', 'r').read())
|
|||
|
||||
env = Environment(loader=FileSystemLoader('./'))
|
||||
template = env.get_template('index.html')
|
||||
print(template.render(config))
|
||||
|
||||
print(template.render({'config': config}))
|
||||
|
|
67
index.html
67
index.html
|
@ -6,8 +6,8 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>PaS(t)3 - S3 file editor</title>
|
||||
|
||||
{% if bootswatch_theme %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/{{ bootswatch_theme }}/bootstrap.min.css" />
|
||||
{% if config.bootswatch_theme %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/4.1.3/{{ config.bootswatch_theme }}/bootstrap.min.css" />
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
|
||||
integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" crossorigin="anonymous" />
|
||||
|
@ -26,47 +26,37 @@
|
|||
</style>
|
||||
|
||||
<!-- Sign-In with Google -->
|
||||
<meta name="google-signin-client_id" content="{{ google_client_id }}">
|
||||
<meta name="google-signin-client_id" content="{{ config.google_client_id }}">
|
||||
<!-- Configure PaS(t)3 -->
|
||||
<script>
|
||||
window.past3_config = {
|
||||
acl: '{{ acl }}',
|
||||
base_url: '{{ base_url }}',
|
||||
bucket: '{{ bucket }}',
|
||||
identity_pool_id: '{{ identity_pool_id }}',
|
||||
region: '{{ region }}',
|
||||
};
|
||||
window.past3_config = {{ config|tojson }};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- NAV -->
|
||||
<nav class="navbar navbar-default">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||
<a class="navbar-brand" href="#">
|
||||
<i class="fas fa-fw fa-clipboard-list"></i>
|
||||
Pa<em>S(t)<strong>3</strong></em>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="container-fluid mt-3">
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-fw fa-file"></i> Files in your namespace
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="list-group" id="fileList">
|
||||
<!--
|
||||
<a href="#" class="list-group-item active">
|
||||
<span class="badge">2006-01-02 15:04:05</span>
|
||||
README.md
|
||||
</a>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush" id="fileList">
|
||||
<!--
|
||||
<a href="#" class="list-group-item active">
|
||||
<span class="badge">2006-01-02 15:04:05</span>
|
||||
README.md
|
||||
</a>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -75,31 +65,42 @@
|
|||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<div class="form-group">
|
||||
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fas fa-fw fa-tag"></i> Filename</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-tag"></i> Filename</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="filename" placeholder="untitled">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div> <!-- /.col-md-10 -->
|
||||
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-default col-md-12" id="newFile"><i class="fas fa-fw fa-file"></i> New File</button>
|
||||
<button class="btn btn-primary col-md-12" id="newFile" title="New File (Ctrl + N)"><i class="fas fa-fw fa-file"></i> New File</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<div class="form-group">
|
||||
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fas fa-fw fa-link"></i> File-URL</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fas fa-fw fa-link"></i> File-URL</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="file-url" placeholder="n/a" readonly>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-secondary" id="acl" title="Change ACL (Ctrl + L)"><i class="fas fa-fw fa-lock"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div> <!-- /.col-md-10 -->
|
||||
|
||||
<div class="col-md-2">
|
||||
<div class="btn-group file-mgmt" role="group">
|
||||
<button type="button" class="btn btn-success col-md-9" id="saveFile"><i class="fas fa-fw fa-save"></i> Save</button>
|
||||
<button type="button" class="btn btn-success col-md-9" id="saveFile" title="Save (Ctrl + S)"><i class="fas fa-fw fa-save"></i> Save</button>
|
||||
<button type="button" class="btn btn-danger col-md-3" id="deleteFile"><i class="fas fa-fw fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -112,13 +113,11 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-fw fa-file-alt"></i> File content
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<textarea style="height:100%;width:100%;" id="editor"></textarea>
|
||||
</div>
|
||||
<textarea style="height:100%;width:100%;" id="editor"></textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue