feature (framework): create the basis for the development custom backends

This commit is contained in:
Mickael Kerjean 2018-08-25 16:14:32 +10:00
parent 696b852186
commit bfacd4bcc5
12 changed files with 117 additions and 16 deletions

View file

@ -10,4 +10,13 @@ build_frontend:
NODE_ENV=production npm run build
build_backend:
CGO_CFLAGS_ALLOW='-fopenmp' go build -o dist/nuage server/main.go
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ CGO_CFLAGS_ALLOW='-fopenmp' go build -o dist/nuage server/main.go
package:
rm -rf dist/
make build_backend
make build_frontend
cp -R config dist/data/config
mv dist nuage
tar -zcvf nuage.tar.gz nuage
rm -rf nuage

View file

@ -156,7 +156,7 @@ Data.prototype.fetchAll = function(fn, type = this.FILE_PATH, key = "/"){
const tx = db.transaction([type], "readonly");
const store = tx.objectStore(type);
const index = store.index("idx_path");
const request = index.openCursor(IDBKeyRange.lowerBound(key));
const request = index.openCursor(IDBKeyRange.bound(key, key+("z".repeat(5000))));
return new Promise((done, error) => {
request.onsuccess = function(event) {

View file

@ -16,8 +16,12 @@ class SessionManager{
let url = '/api/session/auth/gdrive';
return http_get(url)
.then(data => data.result);
}else if(type === 'custombackend'){
let url = '/api/session/auth/custombackend';
return http_get(url)
.then(data => data.result);
}else{
return Promise.error({message: 'not authorization backend for: '+type, code: 'UNKNOWN_PROVIDER'})
return Promise.reject({message: 'no authorization backend', code: 'UNKNOWN_PROVIDER'});
}
}

View file

@ -36,6 +36,9 @@ export class ConnectPage extends React.Component {
}else if(state === "googledrive"){
this.setState({doing_a_third_party_login: true});
this.authenticate({code: getParam('code'), type: 'gdrive'});
}else if(state === "custombackend"){
this.setState({doing_a_third_party_login: true});
this.authenticate({code: getParam('code'), type: 'custombackend'});
}
}
@ -76,6 +79,13 @@ export class ConnectPage extends React.Component {
this.setState({loading: false});
notify.send(err, 'error');
});
}else if(source === 'custombackend'){
Session.url('custombackend').then((url) => {
window.location.href = url;
}).catch((err) => {
this.setState({loading: false});
notify.send(err, 'error');
});
}
}

View file

@ -16,7 +16,7 @@ export class Form extends React.Component {
};
const select = settings_get("login_tab");
if(select !== null){ this.state.select = select; }
if(select !== null && select < CONFIG["connections"].length){ this.state.select = select; }
this.rerender = this.rerender.bind(this);
}
@ -94,7 +94,7 @@ export class Form extends React.Component {
{
this.state.backends.map((backend, i) => {
return (
<Button key={"menu-"+i} className={i == this.state.select ? "active primary" : ""} onClick={this.onTypeChange.bind(this, i)}>
<Button key={"menu-"+i} className={i === this.state.select ? "active primary" : ""} onClick={this.onTypeChange.bind(this, i)}>
{backend.label}
</Button>
);
@ -107,7 +107,7 @@ export class Form extends React.Component {
{
this.state.backends.map((conn, i) => {
return (
<NgIf key={"form-"+i} cond={this.state.select == i}>
<NgIf key={"form-"+i} cond={this.state.select === i}>
<NgIf cond={conn.type === "webdav"}>
<WebDavForm values={conn} config={CONFIG["connections"][i]} onChange={this.onFormUpdate.bind(this, i)} />
</NgIf>
@ -129,6 +129,9 @@ export class Form extends React.Component {
<NgIf cond={conn.type === "gdrive"} className="third-party">
<GDriveForm values={conn} config={CONFIG["connections"][i]} onThirdPartyLogin={this.redirect.bind(this)} />
</NgIf>
<NgIf cond={conn.type === "custombackend"} className="third-party">
<CustomForm values={conn} config={CONFIG["connections"][i]} onThirdPartyLogin={this.redirect.bind(this)} />
</NgIf>
</NgIf>
);
})
@ -142,7 +145,7 @@ export class Form extends React.Component {
const WebDavForm = formHelper(function(props){
const onAdvanced = (value) => {
if(value == true){
if(value === true){
props.values.path = "";
}else{
delete props.values.path;
@ -179,7 +182,7 @@ const WebDavForm = formHelper(function(props){
const FtpForm = formHelper(function(props){
const onAdvanced = (value) => {
if(value == true){
if(value === true){
props.values.path = "";
props.values.port = "";
}else{
@ -227,7 +230,7 @@ const FtpForm = formHelper(function(props){
const SftpForm = formHelper(function(props){
const onAdvanced = (value) => {
if(value == true){
if(value === true){
props.values.path = "";
props.values.port = "";
props.values.passphrase = "";
@ -279,7 +282,7 @@ const SftpForm = formHelper(function(props){
const GitForm = formHelper(function(props){
const onAdvanced = (value) => {
if(value == true){
if(value === true){
props.values.path = "";
props.values.passphrase = "";
props.values.commit = "";
@ -361,7 +364,7 @@ const GitForm = formHelper(function(props){
const S3Form = formHelper(function(props){
const onAdvanced = (value) => {
if(value == true){
if(value === true){
props.values.path = "";
props.values.endpoint = "";
props.values.region = "";
@ -417,6 +420,9 @@ const DropboxForm = formHelper(function(props){
const redirect = () => {
return props.onThirdPartyLogin("dropbox");
};
if(CONFIG.connections.length === 1){
redirect();
}
return (
<div>
<div onClick={redirect}>
@ -431,6 +437,9 @@ const GDriveForm = formHelper(function(props){
const redirect = () => {
return props.onThirdPartyLogin("google");
};
if(CONFIG.connections.length === 1){
redirect();
}
return (
<div>
<div onClick={redirect}>
@ -441,6 +450,22 @@ const GDriveForm = formHelper(function(props){
);
});
const CustomForm = formHelper(function(props){
const redirect = () => {
return props.onThirdPartyLogin("custombackend");
};
if(CONFIG.connections.length === 1 && CONFIG.auto_connect === true){
redirect();
}
return (
<div>
<Button type="button" onClick={redirect} theme="emphasis">LOGIN</Button>
</div>
);
});
function formHelper(WrappedComponent){
return (props) => {
const helpers = {

View file

@ -5,6 +5,7 @@
display: flex;
margin: -10px -11px 10px;
padding: 0px 0px 6px 0;
overflow-x: auto;
button{
min-width: 80px;
border-top-left-radius: 0;

View file

@ -13,8 +13,6 @@ self.onmessage = function(message){
}, null, () => {
self.postMessage({type: "search::completed"})
});
}else if(message.data.action === "search::index"){
Indexing(message.data.config);
}
}

View file

@ -7,7 +7,8 @@
"fork_button": true,
"display_hidden": false,
"client_search_enable": true,
"client_search_per_min": 20
"client_search_per_min": 20,
"auto_connect": false
},
"log": {
"enable": true,

View file

@ -27,6 +27,7 @@ type Config struct {
Editor string `json:"editor"`
ForkButton bool `json:"fork_button"`
DisplayHidden bool `json:"display_hidden"`
AutoConnect bool `json:"auto_connect"`
} `json:"general"`
Log struct {
Enable bool `json:"enable"`
@ -41,6 +42,10 @@ type Config struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
} `json:"gdrive"`
Custom struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
} `json:"custom"`
} `json:"oauth"`
Connections []struct {
Type string `json:"type"`
@ -67,8 +72,8 @@ type Config struct {
Dirname string
ConfigPath string
FirstSetup bool
} `-`
MimeTypes map[string]string `json:"mimetypes,omitempty"`
} `json:"-"`
MimeTypes map[string]string `json:"-"`
}
func (c *Config) Initialise() {
@ -161,12 +166,14 @@ func (c *Config) Export() (string, error) {
Editor string `json:"editor"`
ForkButton bool `json:"fork_button"`
DisplayHidden bool `json:"display_hidden"`
AutoConnect bool `json:"auto_connect"`
Connections interface{} `json:"connections"`
MimeTypes map[string]string `json:"mime"`
}{
Editor: c.General.Editor,
ForkButton: c.General.ForkButton,
DisplayHidden: c.General.DisplayHidden,
AutoConnect: c.General.AutoConnect,
Connections: c.Connections,
MimeTypes: c.MimeTypes,
}

View file

@ -0,0 +1,42 @@
package backend
import (
. "github.com/mickael-kerjean/nuage/server/common"
"io"
"os"
"strings"
)
type CustomBackend struct {
}
func NewCustomBackend(params map[string]string, app *App) (*CustomBackend, error) {
return &CustomBackend{}, nil
}
func (b CustomBackend) Info() string {
return "N/A"
}
func (b CustomBackend) Ls(path string) ([]os.FileInfo, error) {
return nil, NewError("", 401)
}
func (b CustomBackend) Cat(path string) (io.Reader, error) {
return strings.NewReader(""), NewError("", 401)
}
func (b CustomBackend) Mkdir(path string) error {
return NewError("", 401)
}
func (b CustomBackend) Rm(path string) error {
return NewError("", 401)
}
func (b CustomBackend) Mv(from string, to string) error {
return NewError("", 401)
}
func (b CustomBackend) Touch(path string) error {
return NewError("", 401)
}
func (b CustomBackend) Save(path string, file io.Reader) error {
return NewError("", 401)
}

View file

@ -21,6 +21,8 @@ func NewBackend(ctx *App, conn map[string]string) (IBackend, error) {
return backend.NewDropbox(conn, ctx)
case "gdrive":
return backend.NewGDrive(conn, ctx)
case "custombackend":
return backend.NewCustomBackend(conn, ctx)
default:
return backend.NewNothing(conn, ctx)
}

View file

@ -45,10 +45,12 @@ func SessionAuthenticate(ctx App, res http.ResponseWriter, req *http.Request) {
err := obj.OAuthToken(&ctx.Body)
if err != nil {
sendErrorResult(res, NewError("Can't authenticate (OAuth error)", 401))
return
}
backend, err = model.NewBackend(&ctx, ctx.Body)
if err != nil {
sendErrorResult(res, NewError("Can't authenticate", 401))
return
}
}