1
0
Fork 0
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:
Knut Ahlers 2018-09-25 01:18:01 +02:00
parent c31b86d22a
commit 0cba83022d
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
4 changed files with 101 additions and 49 deletions

71
app.js
View file

@ -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())

View file

@ -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

View file

@ -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}))

View file

@ -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>