feature (readonly): respect readonly restriction on the editor

This commit is contained in:
Mickael KERJEAN 2019-01-10 01:13:36 +11:00
parent 50506dcff9
commit 3b65cdf417
8 changed files with 64 additions and 7 deletions

View file

@ -90,6 +90,29 @@ export function http_delete(url){
});
}
export function http_options(url){
return new Promise((done, err) => {
var xhr = new XMLHttpRequest();
xhr.open("OPTIONS", url, true);
xhr.withCredentials = true;
xhr.onload = function(){
if(xhr.readyState === XMLHttpRequest.DONE){
if(xhr.status !== 200){
handle_error_response(xhr, err);
return
}
done(xhr.getAllResponseHeaders()
.split("\n")
.reduce((acc, r) => {
const a = r.split(": ");
acc[a[0]] = a[1];
return acc;
}, {}));
}
}
xhr.send(null);
})
}
function handle_error_response(xhr, err){

View file

@ -7,7 +7,7 @@ export { cache } from './cache';
export { pathBuilder, basename, dirname, absoluteToRelative, filetype, currentShare, findParams, appendShareToUrl } from './path';
export { memory } from './memory';
export { prepare } from './navigate';
export { invalidate, http_get, http_post, http_delete } from './ajax';
export { invalidate, http_get, http_post, http_delete, http_options } from './ajax';
export { prompt, alert, confirm } from './popup';
export { notify } from './notify';
export { gid, randomString } from './random';

View file

@ -1,6 +1,6 @@
"use strict";
import { http_get, http_post, prepare, basename, dirname, pathBuilder } from '../helpers/';
import { http_get, http_post, http_options, prepare, basename, dirname, pathBuilder } from '../helpers/';
import { filetype, currentShare, appendShareToUrl } from '../helpers/';
import { Observable } from 'rxjs/Observable';
@ -190,6 +190,12 @@ class FileSystem{
});
});
}
options(path){
const url = appendShareToUrl('/api/files/cat?path='+prepare(path));
return http_options(url);
}
url(path){
const url = appendShareToUrl('/api/files/cat?path='+prepare(path));
return Promise.resolve(url);

View file

@ -62,16 +62,26 @@ export class ViewerPage extends React.Component {
};
const data_fetch = (app) => {
if(app === 'editor'){
Files.cat(this.state.path).then((content) => {
this.setState({content: content, loading: false});
}).catch(err => {
return Promise.all([
Files.cat(this.state.path),
Files.options(this.state.path)
]).then((d) => {
const [content, options] = d;
console.log(options);
options.allowed
this.setState({
content: content,
loading: false,
acl: options["allow"]
});
}).catch((err) => {
console.log(err);
if(err && err.code === 'BINARY_FILE'){
this.setState({opener: 'download', loading: false});
}else{
this.props.error(err);
}
});
return;
}
this.setState({loading: false});
};
@ -134,6 +144,7 @@ export class ViewerPage extends React.Component {
content={this.state.content || ""}
url={this.state.url}
path={this.state.path}
acl={this.state.acl}
filename={this.state.filename}/>
</NgIf>
<NgIf cond={this.state.opener === 'image'}>

View file

@ -98,6 +98,7 @@ export class Editor extends React.Component {
mode: mode,
keyMap: CONFIG["editor"],
lineWrapping: true,
readOnly: !this.props.readonly,
foldOptions: {
widget: "..."
}

View file

@ -145,6 +145,7 @@ export class IDE extends React.Component {
<ReactCSSTransitionGroup transitionName="editor" transitionAppear={true} transitionEnter={false} transitionLeave={false} transitionAppearTimeout={300} className="editor_container">
<Editor onSave={this.save.bind(this)} filename={this.props.filename}
content={this.state.contentToSave}
readonly={/PUT/.test(this.props.acl)}
event={this.state.event.asObservable()}
onModeChange={this.onUpdate.bind(this, 'mode', false)}
onFoldChange={this.onUpdate.bind(this, 'folding', false)}

View file

@ -138,6 +138,21 @@ func FileCat(ctx App, res http.ResponseWriter, req *http.Request) {
io.Copy(res, file)
}
func FileAccess(ctx App, res http.ResponseWriter, req *http.Request) {
allowed := []string{}
if model.CanRead(&ctx){
allowed = append(allowed, "GET")
}
if model.CanEdit(&ctx){
allowed = append(allowed, "PUT")
}
if model.CanUpload(&ctx){
allowed = append(allowed, "POST")
}
res.Header().Set("Allow", strings.Join(allowed, ", "))
SendSuccessResult(res, nil)
}
func FileSave(ctx App, res http.ResponseWriter, req *http.Request) {
if model.CanEdit(&ctx) == false {
SendErrorResult(res, NewError("Permission denied", 403))

View file

@ -68,6 +68,7 @@ func Init(a *App) {
middlewares = []Middleware{ ApiHeaders, SecureHeaders, SessionStart, LoggedInOnly }
files.HandleFunc("/ls", NewMiddlewareChain(FileLs, middlewares, *a)).Methods("GET")
files.HandleFunc("/cat", NewMiddlewareChain(FileCat, middlewares, *a)).Methods("GET")
files.HandleFunc("/cat", NewMiddlewareChain(FileAccess, middlewares, *a)).Methods("OPTIONS")
files.HandleFunc("/cat", NewMiddlewareChain(FileSave, middlewares, *a)).Methods("POST")
files.HandleFunc("/mv", NewMiddlewareChain(FileMv, middlewares, *a)).Methods("GET")
files.HandleFunc("/rm", NewMiddlewareChain(FileRm, middlewares, *a)).Methods("GET")
@ -78,7 +79,6 @@ func Init(a *App) {
middlewares = []Middleware{ ApiHeaders, SecureHeaders, RedirectSharedLoginIfNeeded, SessionStart, LoggedInOnly }
r.PathPrefix("/api/export/{share}/{mtype0}/{mtype1}").Handler(NewMiddlewareChain(FileExport, middlewares, *a))
// API for Shared link
share := r.PathPrefix("/api/share").Subrouter()
middlewares = []Middleware{ ApiHeaders, SecureHeaders, SessionStart, LoggedInOnly }